android service crashed (restart)
如果你有支APP有個SERVICE是可能每隔一段時間去做一次的!
那麼我建議你改用AlarmManager。
最近發現自己寫的某支APP裡面的service會被android os restart!
大概知道是因為是background service的關係,
想要讓一個service keep alive。
當然有解決方法,在2.0以前的device,
可以使用setForeground(true);
但是2.0以上,這個method,失效了。
改成startForeground(id, notification)。
但我改用了AlarmManager
原因當然有很多,像是其實啟動一個service,就是啟動一個process。
想必就消耗掉一點memory...
當然還有其他原因,大家可以去Google一下。
實作方法如下:
public void onUpdate(Context context, AppWidgetManager appWidgetManager,int[] appWidgetIds) {
Intent intent = new Intent(context, receiverChange.class); //放入你每隔一段時間要執行的class
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
//接著就是set一個repeat,這裡是設定每隔一分鐘去執行
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() , (60*1000), pendingIntent);
}
然後您每隔一段時間要做的事情就寫在一個BroadcastReceiver裡面
public class receiverChangePicture extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.d("main","hi I receive message every minutes..");
}
}
這樣就完成了,但是注意此實作方法只限定於有週期性要執行的code才適用!!!!
如果今天你是要偵測sd card的狀態,那麼建議你還是用service!(就如同我上篇文章所說的)
以alarmManager來實作,只是節省一點成本罷了!
最近在寫一些有關檔案的操作,
要把檔案寫到sdcard裡去
至於怎麼寫,這裡就不多說
在寫檔之前,好的programmer一定要注意到防呆!
就是detect sdcard的狀態
是否有被mount上去?
之前都直接寫一個function去取得目前sdcard的狀態,如下
private static final boolean fnIsSDcard(){
return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
}
但是在我的需求中,這種寫法會有問題,
因為我的檔案較大,在寫的過程中會耗費比較久的時間,
如果在寫檔的過程中,sdcard被unmounted了! 很好,這個process會被killed掉!
因為這是process中有參照到sdcard裡的位置,所以android os會強制kill掉!
所以我就在想...sdcard有沒有event listener啊??
但是沒有,所以我透過Service和BroadcastReceiver去實作
首先先新增一個class,然後要extends Service,如下
public class serviceSDcard extends Service {
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onStart(Intent intent, int startId) {
//新增一個IntentFilter
IntentFilter intentFilter = new IntentFilter();
//並且新增兩個action,告知此 service什麼時候的動作才要通知你
intentFilter.addAction(Intent.ACTION_MEDIA_MOUNTED); //如果sdcard被掛載上去時通知
intentFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED); //如果sdcard被卸載時通知
intentFilter.addDataScheme("file");
intentFilter.addDataAuthority("*", null);
registerReceiver(receiver, intentFilter); //註冊一個BroadcastReceiver
super.onStart(intent, startId);
}
private BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
try {
if (intent.getAction().equals(Intent.ACTION_MEDIA_UNMOUNTED)){
//sdcard被卸載時的動作
}else{
//sdcard被掛載時的動作
}
} catch (Exception e) {
Log.d("main", e.toString());
}
}
};
}
一個Service就完成了,現在就要把Service啟動!
在主要執行的activity中去startService();,如下
public class main extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Intent intent = new Intent(this,serviceSDcard.class);
startService(intent);
}
}
這樣就完成啦! 記得要在manifest.xml中新增一個service喔!!如下:
<service android:name=".serviceSDcard"></service>
android ProgressBar in AppWidget
會產生一些問題!
基本上在顯示,或者設定目前progress都是沒問題的!!
但是當你要把ProgressBar 設為Invisible的時候就會產生BUG!
目前看來似乎是android本身的bug...
至少找資料找到現在...蠻多人都說這樣的!
Views.setViewVisibility(R.id.TextView01, View.VISIBLE);
以往只要打這行code就能把某個元件Invisible或者GONE掉
但是如果元件是Progress Bar的話!
會無法動作!!
所以在這建議大家使用兩個layout
一個是有progress bar,一個沒有!
如下!
RemoteViews withProgressViews= new RemoteViews(this.getPackageName(),R.layout.progress_layout);//這個是有Progress的
RemoteViews withoutProgressViews= new RemoteViews(this.getPackageName(),R.layout.init_layout);//這沒有Progress的
app_manager.updateAppWidget(appWidgetId, withProgressViews/withoutProgressViews);//在透過app_manager去更新妳widget的layout樣式