[英]Service crashing and restarting
關於它有幾個問題,但我總是讀同樣的事情:“如果系統需要資源,服務就會被殺死”或“你不能建立一個永遠運行的服務,因為它在后台運行的越多,就越容易受到影響系統殺死它“等等
我面臨的問題是:我的服務運行良好並且正如預期的那樣,如果我運行我的應用程序然后退出它我的服務仍在運行,但是當我殺了我的應用程序時(通過轉到“最近的應用程序”並轉換它離開)服務停止。 在這一刻,如果我轉到設置>> aplications >>運行,我會看到該服務正在重啟。 過了一會兒,它回來了,我的服務運行沒有問題。
我谷歌它,我找到了一些我能做的事情,但讓我們先看看我的代碼:
我通過這種方式啟動我的服務(點擊一下按鈕后):
Intent intent = new Intent (MainActivity.this, MyService.class);
startService(intent);
我還有3個額外的整數,所以我有這樣的東西:
final Integer i, i2, i3;
i = 5; //for example
i2 = 10; //for example
i3 = 15; //for example
final Intent intent = new Intent (MainActivity.this, MyService.class);
intent.putExtra("INTEGER1", i);
intent.putExtra("INTEGER2", i2);
intent.putExtra("INTEGER3", i3);
startService(intent);
在MyService中,我有以下方面:
public class MyService extends Service
{
AlarmManager am;
BroadcastReceiver br;
PendingIntent pi;
Integer i, i2, i3;
@Override
public void onCreate()
{
super.onCreate();
am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
pi = PendingIntent.getBroadcast(this, 0, new Intent("anyany"); 0) //Why those zeros?
br = new BroadcastReceiver ()
{
public void onReceive (Context context, Intent i) {
new thread(new Runnable()
{
public void run()
{
//do something
}
}).start();
}
};
}
@Override
public void onStartCommand(Intent intent, int flags, int startId)
{
super.onStartCommand(intent, flags, startId);
try
{
i = intent.getIntExtra("INTENT1", 0) // I don't understant yet why this zero are here
i2 = intent.getIntExtra("INTENT2", 0)
i3 = intent.getIntExtra("INTENT3", 0);
}
catch(NullPointerException e) {}
this.registerReceiver(br, new IntentFilter("anyany"));
new thread(new Runnable()
{
public void run()
{
am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock. elapsedRealtime() + i*1000, i2*1000, pi);
}
}).start();
return START_REDELIVER_INTENT; //so I can get my Extra even with my Activity closed
}
我的onDestroy:
@Override
public void onDestroy()
{
unregisterReceiver(br);
super.onDestroy();
}
我也有onBind()方法(沒有@Override),但它返回null。 我谷歌很多,我試圖在前台運行該服務,所以我這樣做(在de onStartCommand內):
Notification n = new Notification(R.drawable.ic_laucher), getText(R.string.app_name), System.currentTimeMillis());
PendingIntent npi = PendingIntent.getActivity(this, MainActivity.class);
n.setLatestEventInfo(this, getText(R.string.notification_title), getText(R.string.notification_message), npi);
startForeground(3563, n);
我的通知出現了,當我點擊它我的應用程序運行,但我的服務問題沒有修復(我相信它仍然不在前台運行)。 通知也重新啟動。
我還刪除了Try catch,並為整數定義了一個值(所以我沒有使用getIntExtra()方法),但沒有改變
經過幾次測試后,我試圖查看日志,當我殺死我的應用程序時,我有以下消息:調度崩潰服務的重新啟動。
因此,由於某些原因,當我的MainActivity死亡時我的服務崩潰,為什么? 這里的目的不是要改變一個無法殺死的神的服務(我不認為這根本不可能,WhatsApp運行了105個小時!)但是在我的應用程序死后我的服務沒有被破壞。
我不知道這是否有幫助,但這是我在Manifest.xml上添加的內容
<Activity android:name = ".MyService"/>
<service android:name ="Myservice" android:enabled="true" android: exported="false"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
最小API = 9,目標API = 17.運行時服務的大小:大約3MB。
希望我很清楚並抱歉我的英語。
PS:整個代碼都按預期運行,所以如果你看到任何sintax錯誤可以隨意編輯它。
編輯
如果我在AndroidManifest.xml的<service>
中添加android:isolatedProcess="true"
,我在logCat中收到此錯誤: java.lang.RuntimeException: Unable to create a service in com.mycompany.myapp.myservice: java.lang.SecurityException: Isolated process not allow ed to call getIntentSender
當我使用它啟動我的服務時,MainActivity不會顯示任何錯誤,只有服務崩潰。
我終於找到了解決方案! 我從服務中刪除了AlarmManager,服務不再兌現,但我必須使用它
問題是用戶從最近的應用程序中刪除應用程序后服務崩潰,所以我所做的是阻止應用程序出現在該窗口中。 將以下內容作為<activity>
的子項添加到AndroidManifest.xml中
android:excludeFromRecents="true"
現在,當用戶從您的應用程序退出時,它不會出現在最近的應用程序窗口中,這意味着系統在您退出后立即終止該活動,因此它不會浪費任何資源。
PS:不要忘記將服務設置為在單獨的進程中運行,將以下內容添加到AndroidManifest.xml中,作為<service>
的子進程
android:process=":remote"
編輯 - 找到真正的解決方案
經過大量的研究和研究(幾個月的研究),我深入研究了android API,這是一個發現,這是僅在API 16+發生的預期行為,android arquiteture的變化改變了PendingIntents的方式由系統廣播,所以Google添加了標志FLAG_RECEIVER_FOREGROUND
,你必須將這個標志傳遞給你在PendingIntent.getBroadcast()
上用作參數的意圖,這里是例子:
if(Build.VERSION.SDK_INT >= 16) //The flag we used here was only added at API 16
myIntent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
//use myIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); if you want to add more than one flag to this intent;
PendingIntent pi = PendingIntent.getBroadcast(context, 1, myIntent, 0); // the requestCode must be different from 0, in this case I used 1;
早於API 16的Android版本將按預期工作,如果您從“最近的應用”頁面中刪除該應用,該服務將不會崩潰。
正如文檔所說, Service
在其被調用者的主線程中運行,通常是UI線程。 所以發生的事情是,當你殺死你的應用程序時,你會殺死你的應用程序進程,因此服務也會被殺死。
您可以通過在Manifest.xml
文件的<service>
標記中使用android:process在不同的進程中創建Service
來解決此問題。
但是,通常,如果Service
需要獨立於被調用者並且可能由不同的應用程序使用,則在其自己的進程中啟動Service
。 如果您的Service
僅供您自己的應用程序使用,那么請堅持使用默認行為,並且不要殺死您的應用程序。
編輯1:
android:isolatedProcess的文檔說:
如果設置為true,則此服務將在與系統其余部分隔離的特殊進程下運行,並且沒有自己的權限。 與它的唯一通信是通過Service API(綁定和啟動)。
從另一個SO答案(鏈接) ,這是預期的行為。 但可以肯定的是,這里有人會有解決方法或解決方案。
您的代碼問題:
pi = PendingIntent.getBroadcast(this,0,new Intent(“anyany”); 0)//為什么那些零?
你看到的第一個零被稱為requesCode
並被描述為目前沒有被使用:
requestCode:發件人的私有請求代碼(當前未使用)。
第二個零實際上應該是給定的標志之一(這里) 。
i = intent.getIntExtra(“INTENT1”,0)//我不明白為什么這個零在這里
getIntExtra(String, int)
方法不需要將0
作為其第二個參數:它可以是任何整數。 getIntExtra(String, int)
返回與您提供的String鍵對應的整數。 如果此鍵不存在(或從未執行過),則getIntExtra(String, int)
將返回作為第二個參數傳遞的整數。 密鑰失敗時的默認值。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.