1. 程式人生 > >Android 開發之Service 探索如何保證Service不被殺死或被kill之後自動重啟

Android 開發之Service 探索如何保證Service不被殺死或被kill之後自動重啟

前言:

在我司專案1.0版本的時候訊息是使用的環信、用了之後發現各種bug,各種機型不支援導致app崩潰,於是在2.0版本果斷去掉環信,使用了公眾號用的那套訊息系統(老大自己寫的)並做了擴充套件升級。搞了近半個月終於是搞完了,專案也順利上線......

再見你無法想象,檢測未讀訊息/新訊息我寫了個執行緒,每隔30s去請求一個,好low的,app退出後你就拜拜了吧,肯定要改啊!用什麼?service唄,於是開始service之旅...

廢話連篇,開始我們的Service之旅吧!

1.我們要知道什麼是Service?

A Service is an application component representing either an application's desire to perform a longer-running operation while not interacting with the user or to supply functionality for other applications to use. Each service class must have a corresponding 

 declaration in its package'sAndroidManifest.xml. Services can be started with  and .

呵呵,你看得懂?

廢話...

簡單解釋下就是:Service是一個應用程式元件,它能夠在後臺執行一些耗時較長的操作,並且不提供使用者介面。服務能被其它應用程式的元件啟動,即使使用者切換到另外的應用時還能保持後臺執行。此外,應用程式元件還能與服務繫結,並與服務進行互動,甚至能進行程序間通訊(IPC)。 比如,服務可以處理網路傳輸、音樂播放、執行檔案I/O、或者與content provider進行互動,所有這些都是後臺進行的(抱歉,我抄的...)

附:Service官方介紹:傳送門

  Android中文API:傳送門

2.Service生命週期


一會我們通過程式碼看結果,先了解...

3.Service基本型別(啟動方式):

Started :通過應用程式元件(例如Activity)呼叫startService()啟動服務:StartService(intent)系統通通過傳入的intent搜尋相關符合intent的Service,

依次執行其相關生命週期,service一旦啟動就會一直在後臺執行,直到呼叫stopService或stopSelf停止服務。

注:public void onStart(Intent intent, int startId) {}已過時,在2.0之後引入public int onStartCommand(Intent intent, int flags, int startId) {},flags,Service啟動函式,後面介紹。

Bind:通過bindService()繫結服務,該提供了一個客戶端/伺服器介面,允許組建與服務進行互動、傳送請求、返回結果,設定可以利用程序間通訊誇程序執行這些操作;多個元件

可以同時與一個服務繫結,通過onUnbind()方法解綁服務,當所有元件解綁後,服務也被銷燬。

接下來正式進入我們今天的話題:如何保證Service不被殺死或被kill之後自動重啟!

1). onStartCommand() 返回常量Flag介紹:

  • START_STICKY 表示你希望系統可用的時候自動重啟你的服務,但你不關心是否能獲得最後一次的 Intent (例如,你可以重建自己的狀態或者控制自己的 start/stop 生命週期)。
  • START_REDELIVER_INTENT 是為那些在被殺死之後重啟時重新獲得 Intent 的服務的,直到你用傳遞給 onStartCommand() 方法的 startId 引數呼叫 stopSelf() 為止。這裡你會使用 Intent 和 startId 作為佇列完成工作。
  • START_NOT_STICKY 用於那些殺掉也沒關係的服務。這適合那些管理週期性任務的服務,它們只是等待下一個時間視窗工作。(摘自掘金
so,在記憶體不足服務被kill時,我們手動返回flag為START_STICKY / START_REDELIVER_INTENT(取決於重啟是否需要重新獲得intent),當記憶體足夠時,服務會被重新建立.此方法然並卵,並不能使服務常駐...
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Log.i("TAG", "Services onStartCommand");
    return START_REDELIVER_INTENT;
}

2).配置android:persistent="true"  ,persistent根據字面意思理解是持久...持久要持久!也就是常駐。但是通過測試發現被kill掉之後並不能重啟...

Make this service run in the foreground, supplying the ongoing notification to be shown to the user while in this state.

其意思就是使服務在前臺執行,傳送一個通知給處於此狀態的使用者,前臺必須提供一個狀態列通知 這裡就涉及到service的程序優先順序:當系統記憶體不足需要釋放時,會按照優先順序對程序回收,而android將程序分為六個等級 前臺程序( FOREGROUND_APP)、可視程序(VISIBLE_APP )、次要服務程序(SECONDARY_SERVER ) 後臺程序 (HIDDEN_APP)、內容供應節點(CONTENT_PROVIDER)、空程序(EMPTY_APP) 可在service onStartCommand()方法中如此操作:
NotificationCompat.Builder builder = new NotificationCompat.Builder(G.applicationContext);
Notification notification = builder.build();
notification.flags = Notification.FLAG_FOREGROUND_SERVICE;
startForeground(0, notification);
Log.i("Service", "UnreadMessageServices onStartCommand");
return START_STICKY;
寫一個狀態通知欄大家都會吧,這裡就不詳說了,不會的自行google...
執行後效果為 如圖:
這樣做只是在低記憶體是降低該service被kill掉的機率,並不能真正使service常駐。 4).還有方法是說讓其成為系統應用...  好吧這個我確實沒測試,也不想..聽說apk無法解除安裝; 設定該service為獨立程序,貌似提升了優先順序,但是照樣被kill...  pass ; 在onDestory()方法中重啟service,能不能不用這麼low的方法...我沒做測試 這幾種方法只能提升service優先順序/存活率,但是還不能解決其被防毒軟體強行kill的命運... 我的解決方案: 1.首先設定服務為開機自啟
public class BootBroadcastReceiver extends BroadcastReceiver {
    @Override
public void onReceive(Context context, Intent intent) {
        Intent unreadCountService = new Intent(context, UnreadCountService.class);
Intent checkService = new Intent(context, CheckService.class);
context.startService(unreadCountService);
context.startService(checkService);
Log.v("TAG", "開機自動服務自動啟動.....");
}
}
同時需要配置其許可權AndroidManifest.xml
<!-- 開機自啟動 -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<!-- 開機自啟動 -->
<receiver
android:name=".help.BootBroadcastReceiver"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</receiver>

2.利用系統廣播 Intent.ACTION_TIME_TICK 每隔一分鐘檢測一次Service的執行狀態
private class CheckBroadCastReceiver extends BroadcastReceiver {
    @Override
public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals("Intent.ACTION_TIME_TICK")) {
            //檢查Service狀態
if (isServiceRunning(context, "rain.myapp.help.UnreadCountService") == false) {
                //重啟服務
Intent i = new Intent(context,UnCountService.class);
context.startService(i);
}
        }
    }
}

/**
 * 判斷服務是否正在執行中
*
 * @param context     Context物件
* @param serviceName Service全名
* @return
*/
private boolean isServiceRunning(Context context, String serviceName) {
    if (!TextUtils.isEmpty(serviceName) && context != null) {
        ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
ArrayList<ActivityManager.RunningServiceInfo> runningServiceInfoList
                = (ArrayList<ActivityManager.RunningServiceInfo>) activityManager.getRunningServices(100);
        for (Iterator<ActivityManager.RunningServiceInfo> iterator = runningServiceInfoList.iterator(); iterator.hasNext(); ) {
            ActivityManager.RunningServiceInfo runningServiceInfo = iterator.next();
            if (serviceName.equals(runningServiceInfo.service.getClassName().toString()))
                return true;
}
    } else return false;
    return false;
}

公司專案該功能做到這一步就已經足夠了,暫時也不打算深入研究了。作為Android開發者,我們本身是有必要去維護Android的生態環境而不是一昧的去破壞... 到此為止!菜鳥寫部落格,諸多不合之處歡迎指出,還望無噴...

相關推薦

Android 開發Service 探索如何保證Service殺死kill之後自動

前言: 在我司專案1.0版本的時候訊息是使用的環信、用了之後發現各種bug,各種機型不支援導致app崩潰,於是在2.0版本果斷去掉環信,使用了公眾號用的那套訊息系統(老大自己寫的)並做了擴充套件升級。

Android開發魅族手機收到極光推送JPush通知

情景 收不到通知,狀態列沒有、聲音沒有、控制檯不列印log 如果是控制檯不列印log,那就找MyReceiver找到推送的程式碼部分,檢視編譯是否有問題,有問題的話是肯定不通過的。而且日誌也顯示不出來。 正常的收到推送的話會出來兩條訊息,一條是系統通知,一

[轉] Android開發如何保證Service殺掉(broadcast+system/app)

轉發:原文連結http://blog.csdn.net/mad1989/article/details/22492519 序言 最近專案要實現這樣一個效果:執行後,要有一個service始終保持在後臺執行,不管使用者作出什麼操作,都要保證service不被kill,這可真是一個難題。參考了現今各種定製版的系

Android開發如何保證Service殺掉(broadcast+system/app)

序言 最近專案要實現這樣一個效果:執行後,要有一個service始終保持在後臺執行,不管使用者作出什麼操作,都要保證service不被kill,這可真是一個難題。參考了現今各種定製版的系統和安全廠商牛虻軟體,如何能保證自己的Service不被殺死呢?

Android開發Service與IntentService的區別與使用場景

Service Service 是長期執行在後臺的應用程式元件。 Service 不是一個單獨的程序,它和應用程式在同一個程序中,Service 也不是一個執行緒,它和執行緒沒有任何關係,所以它不能直接處理耗時操作。如果直接把耗時操作放在 Service 的 onStartCommand() 中,

Corba開發基於Java實現Service與Client

1      概述 CORBA(Common Object Request Broker Architecture,公共物件請求代理體系結構)是由OMG組織制訂的一種標準的面向物件應用程 序體系規範。或者說 CORBA體系結構是OMG為解決分散式處理環境(DCE)中,硬

Android開發getX,getRawX,getWidth,getTranslationX等的區別

save string hlist getwidth sta 是我 touch 項目 寬度 轉載請註明出處:http://blog.csdn.net/dmk877/article/details/51550031 好久沒寫博客了,最近工作確實挺忙的,剛剛結束了一個

Android 開發Windows環境下Android Studio安裝和使用教程(圖文詳細步驟)

9.png 虛擬機 jdk版本 編寫 clip 開發平臺 集成開發 arc 電腦安裝 鑒於谷歌最新推出的Android Studio備受開發者的推崇,所以也跟著體驗一下。 一、介紹Android Studio Android Studio 是一個Android

Android開發AudioManager(音頻管理器)具體解釋

應該 數量 service eth out 開發 要求 type 路由 AudioManager簡單介紹: AudioManager類提供了訪問音量和振鈴器mode控制。使用Context.getSystemService(Context.AUDIO_SERVICE)

【入門篇】ANDROID開發BUG專講

world 自然 執行 類型 效率 str 積累 全部 href 話說諸葛亮是一個優秀的程序員,每個錦囊都是應對不同的case而編寫的。可是優秀的程序員也敵只是更優秀的bug。六出祈山。七進中原,鞠躬盡瘁,死而後已的諸葛亮僅僅由於有一

android開發merge結合include優化布局

ted com match clas you title example ews 文件的 merge結合include優化android布局,效果不知道。個人感覺使用上也有非常大的局限。只是還是了解一下。記錄下來。 布局文件都要有根節點,但androi

Android開發增量更新

avt exp chm 這一 font ams extern city ron 一、使用場景 apk升級,節省服務器和用戶的流量 二、原理 自從 Android 4.1 開始, Google Play 引入了應用程序的增量更新功能,App使用該升級方式,可節省約2/3

Android開發布局文件裏實現OnClick事件關聯處理方法

intent dsm nbsp ext 關聯 you vertica findview 時間 一般監聽OnClickListener事件,我們都是通過Button button = (Button)findViewById(....); button.se

Android 開發 ---- bootloader (LK)

ttl tab 不同的 opera 指定 isa system void mem LK是什麽 LK 是 Little Kernel 它是 appsbl (Applications ARM Boot Loader)流程代碼 ,little kernel

Android開發藍牙連接打印機

cep sdi tco disable ner gis util receiver count 代碼很簡單,直接一個布局文件和一個activity。需要的朋友可以直接將這兩部分粘貼復制到項目中即可。 Activity部分: package com.anhua.bluet

Android開發新建項目報錯的問題

instr rul txt gin 通過 ini .com org top 通過android studio新建一個空項目。在新建完項目之後,gradle編譯會報錯。 發生問題的原因是build.gradle(Project:TopDialog)中: allproject

Android開發CriminalIntent項目開發(其一)

開發項目 1.0 enc 增加 委派 其他 date 應用 module 前言   這次的開發項目是一個叫做CriminalIntent的應用,該應用可以詳細記錄各種辦公室陋習。這個應用記載的陋習記錄包括標題、日期和圖片,支持在聯系人中查找當事人,通過E-mail、Twit

Android開發旅3:android架構

通過 圖集 例如 sqlit 組件 mil 大小 簡化 .html 引言 通過前面兩篇: Android 開發之旅:環境搭建及HelloWorld Android 開發之旅:HelloWorld項目的目錄結構 我們對android有了個大

Android開發旅1:環境搭建及HelloWorld

lan 及其 其它 ply 新項目 bsp 驗證 for 對話框 ——工欲善其事必先利其器 引言 本系列適合0基礎的人員,因為我就是從0開始的,此系列記錄我步入Android開發的一些經驗分享,望與君共勉!作為Android隊伍中的一個新人的

Android開發漫漫長途 番外篇——自定義View的各種姿勢2

是個 pub water 常用 getchild mod one 它的 sdn 該文章是一個系列文章,是本人在Android開發的漫漫長途上的一點感想和記錄,我會盡量按照先易後難的順序進行編寫該系列。該系列引用了《Android開發藝術探索》以及《深入理解Android 卷