顯示具有 android 標籤的文章。 顯示所有文章
顯示具有 android 標籤的文章。 顯示所有文章

2016年2月1日 星期一

在 Android 中檢查網路連線是否暢通

在 Android 中檢查網路連線是否暢通

假設今天我們要做一個網路連線的請求, 如果使用者按下 button 你的 app 不管三七二十一就直接去做連線,這樣是很糟的~

運氣好一點你的 function return false 或者 catch exception,歹運的話就等等等等等等到 timeout,為了避免這種運氣差的狀況,你需要在開始連線前先檢查一下使用者的裝置到底有沒有連上網路。

我們可以使用 ConnectivityManager 取得 NetworkInfo 來查查目前裝置的網路狀態,包含目前是使用何種連線方式、網路是否連接、是否漫遊中……等等,應有盡有,簡單一點的話用 NetworkInfo.isConnectedOrConnecting() 就妥當了,以下是範例。

public boolean isOK() {
    ConnectivityManager cm =
        (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo ni = cm.getActiveNetworkInfo();
    return ni != null && ni.isConnectedOrConnecting();
}

而要使用這個功能呢,需要在 manifest 加入以下 permisiion

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

Reference:
How to check internet access on Android? InetAddress never timeouts…

Written with StackEdit.

2015年12月14日 星期一

Android 開發心得整理

Android 開發心得整理

Application

  • 只要有該 App 的任何元件(Activity、Service、BroadcastReceiver)執行,Application 就會存在。

Service

  • 簡單一點的話就用 IntentService

  • 同一個 Intent 的 Service 不會同時間執行(尚未測試不同 Intent 的 Service),若執行了兩個相同的
    Service 在 S1 還沒執行完時不會執行 S2,S2 會在S1 執行完後立刻執行,並且 S1 不會執行 onDestroy 而 Service2 會。

  • 使用 AlarmManager 註冊 Service 預計執行 Service,在時間到達前可以重新註冊(update)達成延後或提 前執行或取消註冊。當有兩個相同的 Service 到達執行時間時,僅有 S1 會執行,S2 處於 ready 狀態,ready 狀態的 Service 無法更新、取消註冊。

  • 已經向 AlarmManager 註冊的 Service 就算重新開機,一樣會執行,可以理解為是向 OS 註冊。

  • 當 Service 執行到一半,以 Android task 關閉方式 Kill 該 Service 所屬 App,Service 會被腰斬(沒有執行完),若使用 startForeground 則不會被腰斬,但不會執行 onDestroy。

EventBus

  • 注意 onEvent 的 Thread 問題

  • 想保留該 event 的話可以使用 postSticky

Realm

  • 在 Thread1 撈出來的 RealmObject 無法在 Thread2 存取(讀取也不行!)。

  • 只有在 Main Thread(UI Thread) 撈出來的物件會自動更新。

  • 在非 Main Thread 撈資料前,先使用 refresh,確保資料是最新的狀態。

其他 Lib

Written with StackEdit.

2015年12月10日 星期四

Android 在 gradle 中加入 RecyclerView dependency 的錯誤

Android 在 gradle 中加入 RecyclerView dependency 的錯誤

今天要來寫 Android 的 RecyclerView,我在 app.gradle 中的 dependencies 中加入了

compile 'com.android.support:recyclerview-v7:23.1.0'

也就順便把 appcompate-v7 改成一樣的版本

compile 'com.android.support:appcompat-v7:23.1.0'

結果出現了這兩個錯誤

Error retrieving parent for item: No resource found that matches the given name 'android:TextAppearance.Material.Widget.Button.Inverse'.
Error retrieving parent for item: No resource found that matches the given name 'android:Widget.Material.Button.Colored'.

而這兩個東西是在這個檔案裡的

{專案目錄}\app\build\intermediates\exploded-aar\com.android.support\appcompat-v7\23.1.0\res\values-v23\values-v23.xml

想想應該是還有哪裡的版本也要改,估狗一下馬上找到原來是 compileSdlVersion 也要設定一樣的版本,再把它改成 23 後就可以正常使用了。

整個 app.gradle 大概是長這樣

apply plugin: 'com.android.application'

android {
    compileSdkVersion 23

    .
    .
    .
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:23.1.0'
    compile 'com.android.support:recyclerview-v7:23.1.0'

    .
    .
    .
}

Written with StackEdit.

2015年12月7日 星期一

在 Android 中判斷該 Service 有無被註冊喚醒的方法

在 Android 中判斷該 Service 有無被註冊喚醒的方法

我的程式有些批次的事情要做,大概是每五分鐘要去檢查有沒有任務要做,有的話就做,沒的話就等下一個五分鐘,我的任務是有可能會失敗的(例如傳送資料),需要在下一次 Service 內再去嘗試執行,而且要在背景執行。講到這裡聰明的你可能會想到要用 Service 搭配 AlarmManager 來做,就給他設定每隔五分鐘呼叫一次,我也是這樣想的,但遇到一個問題,這樣做非常非常非常非常耗電,就算沒任務也要把 Service 叫起來這可不行。

所以我把程式改為在 ServiceonDestroy 時去判斷還有沒有任務沒完成的,如果有就設定五分鐘後再次執行,若沒有就不設定了,有新任務加入時再去把 Service 叫起來。

這次的重點就在這!

  • 假設上一次的 Service 結束時已經沒有任務要做了,就不會有下一次的自動執行,這時候有新的任務加入,我把 Service 叫起來然後執行,OK!沒問題。
     
  • 假設上一次的 Service 結束時還有任務要做,所以五分鐘後會自動執行,在執行之前有新的任務加入,這時候我該叫起 Service 嗎?叫起的話就破壞了我每五分鐘執行一次的規律生活了。

這樣說起來就是我需要知道目前這個 Service 有沒有被註冊自動執行囉?

拜請 Google 大神的結果是,沒辦法知道 AlarmManager 目前註冊了哪些 PendingIntent,所以我無法透過 AlarmManager 知道這個 Service 有沒有可以自起爬起來工作。

好吧從另一個目標下手,PendingIntent

他的 getService 第四個參數若設定為 PendingIntent.FLAG_NO_CREATE ,可以用來查詢這個 Intent 有沒有存在 PendingIntent,若存在會回傳該 PendingIntent ,反之會回傳 null

if (null == PendingIntent.getService(context, requestCode, intent, PendingIntent.FLAG_NO_CREATE)) {
    // register service
}

然後在 Service 執行時立馬把這個 PendingIntent 刪掉。

@Override
public void onCreate() {
    PendingIntent pi = PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_NO_CREATE);
    if (pi != null)
        pi.cancel();
}

如此便完成我的需求

「當該 Service 已經註冊下次喚醒時間時,不再重覆註冊或直接喚醒以避免破壞其規律的生理時鐘」

Written with StackEdit.

2015年11月23日 星期一

在 Android Studio 加入 assets 資料夾

在 Android Studio 加入 assets 資料夾

在 Android Stdudio 中開心的專案,預設是沒有 assets 這個資料夾的,想要就要自己來。

首先將專案目錄那邊切換到 Project 檢視模式,然後在 app/src/main 目錄下按右鍵 New > Directory,名稱打上 assets,完成!

假設 assets 目錄下有個 OOO 資料夾,裡面有個 QQQ.txt,想要讀取的話就是 …

getAssets().open(getString(OOO/QQQ.txt))

會以 InputStream 回傳

Reference
Where to place Assets folder in Android Studio

Written with StackEdit.

2015年11月14日 星期六

Android Studio 編譯錯誤 unmappable character for encoding MS950

Android Studio 編譯錯誤 unmappable character for encoding MS950

前陣子開始跳槽,把一些 project 從 Eclipse 改到 Android Studio 去做遇到了編碼的問題,明明就都用 UTF-8,Android Studio 的 File Encodings 中 IDE Encoding、Project Encoding、Default encoding for properties files 也是設定 UTF-8 但還是出現錯誤訊息。

Gradle: error: unmappable character for encoding MS950

沒辦法,實在是不會 gradle。上網爬了一下後找到答案,在該 module 的 build.gradle 中加入下面這一段就妥當了。

tasks.withType(JavaCompile) {
     options.encoding = "UTF-8"
} 

Reference:
Android开发常见问题

Written with StackEdit.

2015年5月26日 星期二

Ubuntu 中開發 Android 錯誤訊息: error while loading shared libraries: libstdc++.so.6: cannot open shared object file: No such file or directory

錯誤訊息


[2015-05-26 21:19:42 - tmp] /home/myubuntu/android-sdks/build-tools/22.0.1/aapt: error while loading shared libraries: libstdc++.so.6: cannot open shared object file: No such file or directory



輸入下列指令,安裝 lib32stdc++6、lib32z1、lib32z1-dev 這幾個 lib。
sudo apt-get install lib32stdc++6 lib32z1 lib32z1-dev


Reference


ADT - libstdc++.so.6: cannot open shared object file

2014年3月13日 星期四

Android 移除標題、狀態列

移除標題 (寫在 Activity.onCreate() 內,setContentView() 之前)

移除狀態列 (寫在 Activity.onCreate() 內,setContentView() 之前)

2014年2月28日 星期五

Android java.lang.RuntimeException: Unable to instantiate activity ComponentInfo 解決方法

今天寫 Android 的時候,改了一下 package name,移動了一些 class 到新的 package
可想而知的,程式就 run 不起來了
compile 可以過,但出現 runtime 例外

java.lang.RuntimeException: Unable to instantiate activity ComponentInfo

原因是更改了 activity 所在的 package 名稱
但 AndroidManifest.xml 內沒同步修改到

將標籤 manifest 的 package 屬性設定為 activity 所在的 package 即可

2014年2月12日 星期三

Eclipse Unhandled event loop exception No more handles 解決方法

『如果你有裝 Teamview 的話請直接拉到最下面看方法四』


小明有一天用 eclipse 寫 android 突然出現這樣的錯誤視窗
是一個例外,這個例外的詳細資訊長這樣

把這錯誤示窗關掉繼續 coding,沒幾下又彈出一樣的東西
幾次後發現好像點到 code 編輯器的地方就會出現
於是乎 google 了一下,找了一些解決方法

◎方法一
從中文的開始嘗試了這篇的方法
說是要刪掉 AppData\Local\Eclipse 目錄
不過我是用 Android ADT bundle 好像找不到這個目錄,不過還是列出來供大家參考

◎方法二
一樣是中文的
照著做發現我的 eclipse.ini 裡面已經有 -XX:MaxPermSize 了
另外加上 -XX:PermSize 也沒有用,一樣有例外跑出來

◎方法三
只好開始看英文的解決辦法了,找到了 stackoverflow 的這篇
按照一樓的說法是 Eclipse 預設的 Java 編輯器有 bug
改用 WindowBuilder 可以解決

於是乎從 Eclipse -> Help -> Install New Software 裡安裝 WindowBuilder
在 Work with 那欄填上 WindowBuilder 的網址即可下載安裝
Eclipse 4.2 的網址 http://download.eclipse.org/windowbuilder/WB/release/R201309271200/4.2/
Eclipse 4.3 的網址 http://download.eclipse.org/windowbuilder/WB/release/R201309271200/4.3/
安裝完之後到 Eclupse -> Window -> Preferences 內修改 Java Editor
選擇 *.java 然後在下方加入 WindowBuilder 並設為 Default 讓 WindowBuilder 爬到第一名

結果……問題依然存在

◎方法四
在 stackoverflow 中一個連結一個連結找,找到了 eclipse 的 bug 討論區
裡面什麼樣的可能解決辦法都有
有人說是雙顯示器的關係,有人說是ATI顯卡的關係……@#%^@#$
照著做把螢幕先切回只有一個,無效
更新顯卡驅動,無效

看到有人說把 Teamviewer 關掉,我就關掉,然後就好了  。:.゚ヽ(*´∀`)ノ゚.: 。:.゚ヽ(*´∀`)ノ゚.:。

本著實驗以及信任 Teamviewer 的精神,還是要來測試一下到底是哪裡出問題
直覺上第一個想到的就是會出現在視窗右上角的 "快速連線按鈕"
果然沒錯,把這個功能關掉就完全 OK 了
關掉的方法如下圖


2013年4月15日 星期一

Android Virtual Device 無法開啟

在 Android Virtual Device Manager 選擇虛擬機按下 Start 後出現以下錯誤,無法開啟虛擬機

Starting emulator for AVD 'AVDNAME'
PANIC: Could not open: AVDNAME

原因是因為 Android SDK 放置安裝在 C 碟以外的地方 以我來說,放在 D 碟就出現這樣的錯誤,這時候查看 D 碟目錄下,會發現有一個 .android,代表 SDK 是放在 D 碟以下路徑沒錯,只要在系統環境變數加入一個變數名稱 ANDROID_SDK_HOME,變數值 D:\ 即可。如下圖所示。

 

2013年3月14日 星期四

apktool - apk 反編譯 unpack 工具

簡介

apktool 是一款可以將包裝好的 apk 解開的 open source 工具,目前支援 windows 、 linux 、 osx

網站

Google code - apktool
https://code.google.com/p/android-apktool/

下載

https://code.google.com/p/android-apktool/downloads/list

需求

 JAVA JRE 1.6 (或以上?)

安裝

下載 apktool1.5.2.tar.bz2 (或更新版本) 、 apktool-install-windows-r05-ibot.tar.bz2 (或更新版本),各自解壓縮後得到 apktool.jar 、 aapt.exe 、 apktool.bat ,將這三個檔案放至 C:\Windows 目錄下即安裝完成。

使用

命令提示字元  cmd

  • 反編譯 unpack
    • apktool d test.apk testapkfolder
    • 將 test.apk 解開至 testapkfolder 資料夾
  • 編譯回 apk
    • apktool b testapkfolder
    • 將 testapkfolder 編譯回 apk
  • 說明
    • apktool
    • 直接輸入 apktool 即出現說明資訊