『壹』 android怎麼寫一個殺不死的service
1.在service中重寫下面的方法,這個方法有三個返回值, START_STICKY是service被kill掉後自動重寫創建
[代碼]java代碼:
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}----------------
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
Log.v("TrafficService","startCommand");
flags = START_STICKY;
return super.onStartCommand(intent, flags, startId);
// return START_REDELIVER_INTENT;
}
2.在Service的onDestroy()中重啟Service.
public void onDestroy() {
Intent localIntent = new Intent();
localIntent.setClass(this, MyService.class); //銷毀時重新啟動Service
this.startService(localIntent);
}
用qq管家殺掉進程的時候,調用的是系統自帶的強制kill功能(即settings里的),在kill時,會將應用的整個進程停掉,當然包括service在內,如果在running里將service強制kill掉,顯示進程還在。不管是kill整個進程還是只kill掉進應用的 service,都不會重新啟動service。不知道你是怎麼實現重啟的,實在是不解。 在eclipse中,用stop按鈕kill掉進程的時候,倒是會重啟service
KILL問題:
1. settings 中stop service
onDestroy方法中,調用startService進行Service的重啟。
2.settings中force stop 應用
捕捉系統進行廣播(action為android.intent.action.PACKAGE_RESTARTED)
3. 藉助第三方應用kill掉running task
提升service的優先順序
service開機啟動
今天我們主要來探討android怎麼讓一個service開機自動啟動功能的實現。Android手機在啟動的過程中會觸發一個Standard Broadcast Action,名字叫android.intent.action.BOOT_COMPLETED(記得只會觸發一次呀),在這里我們可以通過構建一個廣播接收者來接收這個這個action.下面我就來簡單寫以下實現的步驟:
第一步:首先創建一個廣播接收者,重構其抽象方法 onReceive(Context context, Intent intent),在其中啟動你想要啟動的Service或app。
[代碼]java代碼:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class BootBroadcastReceiver extends BroadcastReceiver {
//重寫onReceive方法
@Override
public void onReceive(Context context, Intent intent) {
//後邊的XXX.class就是要啟動的服務
Intent service = new Intent(context,XXXclass);
context.startService(service);
Log.v("TAG", "開機自動服務自動啟動.....");
//啟動應用,參數為需要自動啟動的應用的包名
Intent intent = getPackageManager().getLaunchIntentForPackage(packageName);
context.startActivity(intent );
}
}
第二步:配置xml文件,在re
ceiver接收這種添加intent-filter配置
[代碼]java代碼:
<receiver android:name="BootBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"></action>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</receiver>
第三步:添加許可權 <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
如何實現一個不會被殺死的進程
看Android的文檔知道,當進程長期不活動,或系統需要資源時,會自動清理門戶,殺死一些Service,和不可見的Activity等所在的進程。
但是如果某個進程不想被殺死(如數據緩存進程,或狀態監控進程,或遠程服務進程),應該怎麼做,才能使進程不被殺死。
add android:persistent="true" into the <application> section in your AndroidManifest.xml
切記,這個 不可濫用,系統中用這個的service,app一多,整個系統就完蛋了。
目前系統中有phone等非常有限的,必須一直活著的應用在試用。
提升service優先順序的方法
Android 系統對於內存管理有自己的一套方法,為了保障系統有序穩定的運信,系統內部會自動分配,控製程序的內存使用。當系統覺得當前的資源非常有限的時候,為了保 證一些優先順序高的程序能運行,就會殺掉一些他認為不重要的程序或者服務來釋放內存。這樣就能保證真正對用戶有用的程序仍然再運行。如果你的 Service 碰上了這種情況,多半會先被殺掉。但如果你增加 Service 的優先順序就能讓他多留一會,我們可以用 setForeground(true) 來設置 Service 的優先順序。
為什麼是 foreground ? 默認啟動的 Service 是被標記為 background,當前運行的 Activity 一般被標記為 foreground,也就是說你給 Service 設置了 foreground 那麼他就和正在運行的 Activity 類似優先順序得到了一定的提高。當讓這並不能保證你得 Service 永遠不被殺掉,只是提高了他的優先順序。
從Android 1.5開始,一個已啟動的service可以調用startForeground(int, Notification)將service置為foreground狀態,調用stopForeground(boolean)將service置為 background狀態。
我們會在調用startForeground(int, Notification)傳入參數notification,它會在狀態欄里顯示正在進行的foreground service。background service不會在狀態欄里顯示。
在Android 1.0中,將一個service置為foreground狀態:
setForeground(true);
mNM.notify(id, notification);
將一個service置為background狀態:
mNM.cancel(id);
setForeground(false);
對比看出,在1.0 API中調用setForeground(boolean)只是簡單的改變service的狀態,用戶不會有任何覺察。新API中強制將 notification和改變service狀態的動作綁定起來,foreground service會在狀態欄顯示,而background service不會。
Remote service controller & binding
跨進程調用Service。暫時不研究。
如何防止Android應用中的Service被系統回收? 很多朋友都在問,如何防止Android應用中的Service被系統回收?下面簡單解答一下。
對於Service被系統回收,一般做法是通過提高優先順序可以解決,在AndroidManifest.xml文件中對於intent-filter可以通過 android:priority = "1000"這個屬性設置最高優先順序,1000是最高值,如果數字越小則優先順序越低,同時實用於廣播,推薦大家如果你的應用很重要,可以考慮通過系統常用intent action來觸發。
『貳』 如何讓android的service一直在後台運行
1.把service和activity分開,讓service開機啟動。設置一個broadcastreceiver接受開機信號,使用RECEIVE_BOOT_COMPLETED的permission,然後啟動service。activity啟動後綁定到service上,通過ipc機制通信,acitivity結束後松綁。注意安裝後要手動啟動service,不會自動啟動,之後重啟手機後才會隨開機啟動。2.在內存低的時候系統會自動清理進程,這時候後台service可能會被殺掉。可以在onStartCommand中返回START_STICKY,這樣系統有足夠多資源的時候,就會重新開啟service。3.以上不需要NDK,直接用SDK開發就可以了。Android一直運行的後台服務是不存在的,而且也不是最佳實踐,因為一直運行的後台服務會耗費大量系統資源,影響其他程序的響應從而影響到用戶體驗。可以考慮使用如下幾種方案來達到一直運行的效果。1.調用startForeground方法,android:.使用AlarmManager發送定時任務:DiamondsAreForever.ServicesAreNot.我現在也遇到這個問題,我想樓主之所以出現這個問題的原因是,你在Activitiy中創建的Service運行在當前進程中,當你把這個Activitiy的進程殺掉之後,自然這個服務也就停止了。所以我的建議是在startService的時候,讓這個Service運行在與該Activity不同的進程中(可以startService或者開機時創建一個新的進程)。實際上就是Linux裡面的進程操作。可以使用NDK開發,用C或者C++新建一個進程來運行自己的服務,並提高進程優先順序,避免被清理掉(我猜測 和 的推送服務,或許是這么實現的)。有一種做法是開兩個進程來相互監督,一旦其中一個進程被停止,另一個檢測到後,立即或稍後重啟另一個進程。這里可以效仿這種做法。可以開兩個進程,一個用來做前台,另一個負責運行服務,後者沒有activity,由前者初始化並啟動,這樣,當前台進程被關閉時,服務並不被關閉
『叄』 Android中如何啟用Service,如何停用Service
• Context.startService()
• Context.bindService()
1. 在同一個應用任何地方調用 startService() 方法就能啟動 Service 了,然後系統會回調 Service 類的
onCreate() 以及 onStart() 方法。這樣啟動的 Service 會一直運行在後台,直到
Context.stopService() 或者 selfStop() 方法被調用。另外如果一個 Service 已經被啟動,其他代碼再試圖調用
startService() 方法,是不會執行 onCreate() 的,但會重新執行一次 onStart() 。
2. 另外一種 bindService() 方法的意思是,把這個 Service 和調用 Service
的客戶類綁起來,如果調用這個客戶類被銷毀,Service 也會被銷毀。用這個方法的一個好處是,bindService() 方法執行後
Service 會回調上邊提到的 onBind() 方發,你可以從這里返回一個實現了 IBind
介面的類,在客戶端操作這個類就能和這個服務通信了,比如得到 Service 運行的狀態或其他操作。如果 Service
還沒有運行,使用這個方法啟動 Service 就會 onCreate() 方法而不會調用 onStart()。
總結:
1.
startService()的目的是回調onStart()方法,onCreate()
方法是在Service不存在的時候調用的,如果Service存在(例如之前調用了bindService,那麼Service的onCreate方法
已經調用了)那麼startService()將跳過onCreate() 方法。
2.
bindService()目的是回調onBind()方法,它的作用是在Service和調用者之間建立一個橋梁,並不負責更多的工作(例如一個
Service需要連接伺服器的操作),一般使用bindService來綁定到一個現有的Service(即通過StartService啟動的服
務)。
由於Service 的onStart()方法只有在startService()啟動Service的情況下才調用,故使用onStart()的時候要注意這點。
『肆』 Android中怎麼啟動關閉Service及功能解釋
1、 Service不是分離開的進程,除非其他特殊情況,它不會運行在自己的進程,而是作為啟動運行它的進程的一部分。
2、 Service不是線程,這意味著它將在主線程里勞作。
啟動service有兩種方法:
1、 Context.startService()
調用者與服務之間沒有關聯,即使調用者退出,服務仍可運行
2、 Context.bindService()
調用者與服務綁定在一起,調用者一旦退出,服務也就終止
Service的生命周期
如果使用startService()啟動service,系統將通過傳入的Intent在底層搜索相關符合Intent裡面信息的service。如果服務沒有啟動則先運行onCreate,然後運行onStartCommand (可在裡面處理啟動時傳過來的Intent和其他參數),直到明顯調用stopService或者stopSelf才將停止Service。無論運行startService多少次,只要調用一次stopService或者stopSelf,Service都會停止。使用stopSelf(int)方法可以保證在處理好intent後再停止。
控制service運行的主要方式有兩種,主要是根據onStartCommand方法返回的數值。方法:
1、START_STICKY
2、START_NOT_STICKY or START_REDELIVER_INTENT
這里主要解釋這三個變數的意義:
1、 START_STICKY
在運行onStartCommand後service進程被kill後,那將保留在開始狀態,但是不保留那些傳入的intent。不久後service就會再次嘗試重新創建,因為保留在開始狀態,在創建 service後將保證調用onstartCommand。如果沒有傳遞任何開始命令給service,那將獲取到null的intent
2、 START_NOT_STICKY
在運行onStartCommand後service進程被kill後,並且沒有新的intent傳遞給它。Service將移出開始狀態,並且直到新的明顯的方法(startService)調用才重新創建。因為如果沒有傳遞任何未決定的intent那麼service是不會啟動,也就是期間onstartCommand不會接收到任何null的intent。
『伍』 android怎麼實現開機自動啟動Service或app
Android手機在啟動的過程中會觸發一個Standard Broadcast Action,名字叫android.intent.action.BOOT_COMPLETED。
在這里我們可以通過構建一個廣播接收者來接收這個這個action
(1).
public class TextBroadcastReceiver extends BroadcastReceiver {
//重寫onReceive方法
@Override
public void onReceive(Context context, Intent intent) {
//後邊的XXX.class就是要啟動的服務
Intent service = new Intent(context,XXXclass);
context.startService(service);
Log.v("TAG", "開機自動服務自動啟動.....");
//啟動應用,參數為需要自動啟動的應用的包名
Intent intent = getPackageManager().getLaunchIntentForPackage(packageName);
context.startActivity(intent );
}
}
(2):配置xml文件,在receiver接收這種添加intent-filter配置
<receiver android:name="TextBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"></action>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</receiver>
(3):添加許可權 <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
『陸』 android中service的實現方法是
非同步執行
android中,activity、service都是在主線程,service與activity的主要區別就是service沒有前台界面,不能直接與用戶交互,另外可以相對保證不會被系統隨便的kill掉。所以service適用於一些無需交互的後台操作,但如果你直接在service中進行耗時操作的話,因為在主線程所以依然會出現和activity主線程一樣的超時的問題,所以好的方式是在service中啟動其他的線程去執行耗時操作。
『柒』 android如何實現開機自動啟動Service或app
import
android.content.BroadcastReceiver;
import
android.content.Context;
import
android.content.Intent;
import
android.util.Log;
public
class
BootBroadcastReceiver
extends
BroadcastReceiver
{
//重寫onReceive方法@Overridepublic
void
onReceive(Context
context,
Intent
intent)
{
//後邊的XXX.class就是要啟動的服務
Intent
service
=
new
Intent(context,XXXclass);
context.startService(service);
Log.v("TAG",
"開機自動服務自動啟動.....");
//啟動應用,參數為需要自動啟動的應用的包名
『捌』 android在service中怎麼實現
在Activity中可以通過再次startService,來給Service發送消息,而service里的onStartCommand方法也有一個參數,是個int類型的,第一次給service發消息時為1,第二次為2,不斷累加。onStartCommand方法還有一個intent類型的參數,你可以將相應的標志位保存在intent中,這些標志位可以用來控制播放,停止,暫停等。
『玖』 android servicemanager 怎麼實現service管理
ServiceManager是android中比較重要的一個進程,它是在init進程啟動之後啟動,從名字上就可以看出來它是用來管理系統中的service。比如:InputMethodService、ActivityManagerService等。在ServiceManager中有兩個比較重要的方法:add_service、check_service。系統的service需要通過add_service把自己的信息注冊到ServiceManager中,當需要使用時,通過check_service檢查該service是否存在。
主函數(anrdroid4.0/frameworks/base/cmds/servicemanager/service_manager.c)
從它的主函數代碼開始:
int main(int argc, char **argv)
{
struct binder_state *bs;
void *svcmgr = BINDER_SERVICE_MANAGER;
bs = binder_open(128*1024);
if (binder_become_context_manager(bs)) {
LOGE("cannot become context manager (%s) ", strerror(errno));
return -1;
}
svcmgr_handle = svcmgr;
binder_loop(bs, svcmgr_handler);
return 0;
}
從main函數中可以看出,它主要做了三件事情:
打開/dev/binder設備,並在內存中映射128K的空間。
通知Binder設備,把自己變成context_manager
進入循環,不停的去讀Binder設備,看是否有對service的請求,如果有的話,就去調用svcmgr_handler函數回調處理請求。
服務注冊
再來看看ServiceManager中是怎麼樣去注冊服務的。先來看先,當有對service的請求時,調用的回調函數svcmgr_handler:
int svcmgr_handler(struct binder_state *bs,
struct binder_txn *txn,
struct binder_io *msg,
struct binder_io *reply)
{
struct svcinfo *si;
uint16_t *s;
unsigned len;
void *ptr;
uint32_t strict_policy;
// LOGI("target=%p code=%d pid=%d uid=%d ",
// txn->target, txn->code, txn->sender_pid, txn->sender_euid);
if (txn->target != svcmgr_handle)
return -1;
// Equivalent to Parcel::enforceInterface(), reading the RPC
// header with the strict mode policy mask and the interface name.
// Note that we ignore the strict_policy and don't propagate it
// further (since we do no outbound RPCs anyway).
strict_policy = bio_get_uint32(msg);
s = bio_get_string16(msg, &len);
if ((len != (sizeof(svcmgr_id) / 2)) ||
memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
fprintf(stderr,"invalid id %s ", str8(s));
return -1;
}
switch(txn->code) {
case SVC_MGR_GET_SERVICE:
case SVC_MGR_CHECK_SERVICE:
s = bio_get_string16(msg, &len);
ptr = do_find_service(bs, s, len);
if (!ptr)
break;
bio_put_ref(reply, ptr);
return 0;
case SVC_MGR_ADD_SERVICE:
s = bio_get_string16(msg, &len);
ptr = bio_get_ref(msg);
if (do_add_service(bs, s, len, ptr, txn->sender_euid))
return -1;
break;
case SVC_MGR_LIST_SERVICES: {
unsigned n = bio_get_uint32(msg);
si = svclist;
while ((n-- > 0) && si)
si = si->next;
if (si) {
bio_put_string16(reply, si->name);
return 0;
}
return -1;
}
default:
LOGE("unknown code %d ", txn->code);
return -1;
}
bio_put_uint32(reply, 0);
return 0;
}
在該回調函數中會判斷Service有什麼需要,如果是請求注冊service,那麼久執行:
case SVC_MGR_ADD_SERVICE:
s = bio_get_string16(msg, &len);
ptr = bio_get_ref(msg);
if (do_add_service(bs, s, len, ptr, txn->sender_euid))
return -1;
break;
我們再來看看do_add_service中做了什麼事情:
int do_add_service(struct binder_state *bs,
uint16_t *s, unsigned len,
void *ptr, unsigned uid)
{
struct svcinfo *si;
// LOGI("add_service('%s',%p) uid=%d ", str8(s), ptr, uid);
if (!ptr || (len == 0) || (len > 127))
return -1;
if (!svc_can_register(uid, s)) {
LOGE("add_service('%s',%p) uid=%d - PERMISSION DENIED ",
str8(s), ptr, uid);
return -1;
}
si = find_svc(s, len);
if (si) {
if (si->ptr) {
LOGE("add_service('%s',%p) uid=%d - ALREADY REGISTERED ",
str8(s), ptr, uid);
return -1;
}
si->ptr = ptr;
} else {
si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
if (!si) {
LOGE("add_service('%s',%p) uid=%d - OUT OF MEMORY ",
str8(s), ptr, uid);
return -1;
}
si->ptr = ptr;
si->len = len;
memcpy(si->name, s, (len + 1) * sizeof(uint16_t));
si->name[len] = '