簡體   English   中英

Android服務沒有在棒棒糖中重新啟動

[英]Android service not restarting in lollipop

在我的應用程序中,我在后台使用基於位置的服務。 因此我需要在銷毀時重新啟動我的服務。

但是我在logcat中收到了這條消息

ProcessRecord的虛假死亡{320afaf6 20614:com.odoo.crm:my_odoo_gps_service / u0a391},curProc for 20614:null

我的服務onTaskRemoved

@Override
public void onTaskRemoved(Intent rootIntent) {
    System.out.println("onTaskRemoved called");
    Intent restartServiceIntent = new Intent(App.getAppContext(), this.getClass());
    restartServiceIntent.setPackage(getPackageName());

    PendingIntent restartServicePendingIntent = 
       PendingIntent.getService(App.getAppContext(), 1, restartServiceIntent, 
       PendingIntent.FLAG_ONE_SHOT);

    AlarmManager alarmService = 
        (AlarmManager) App.getAppContext().getSystemService(Context.ALARM_SERVICE);
    alarmService.set(
            AlarmManager.ELAPSED_REALTIME,
            SystemClock.elapsedRealtime() + 1000,
            restartServicePendingIntent);
 }

我的服務onDestroy

@Override
public void onDestroy() {
    System.out.println("destroy service");
    super.onDestroy();
    wakeLock.release();
}

我的服務onStartCommand

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
        return Service.START_STICKY;
}

我不知道錯誤是什么。 我在google和stackoverflow中都進行了搜索。 所有這些都引用了Service.START_STICKY 但我已經用過了。

相同的服務重啟在KitKat中有效,但有一些延遲(約5分鍾)。

任何幫助表示贊賞。

您可以使用BroadcasteReceiver重新啟動它, BroadcasteReceiver處理從您的服務的onDestroy()發送的廣播。

這個怎么做:

StickyService.java

public class StickyService extends Service
{

    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return START_STICKY;
    }


    @Override
    public void onTaskRemoved(Intent rootIntent) {
         super.onTaskRemoved(rootIntent);
         sendBroadcast(new Intent("IWillStartAuto"));
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        sendBroadcast(new Intent("IWillStartAuto"));
    }

}

RestartServiceReceiver.java

public class RestartServiceReceiver extends BroadcastReceiver
{

    @Override
    public void onReceive(Context context, Intent intent) {
    context.startService(new Intent(context.getApplicationContext(), StickyService.class));

    }

}

聲明清單文件中的組件

    <service android:name=".StickyService" >
    </service>

    <receiver android:name=".RestartServiceReceiver" >
        <intent-filter>
            <action android:name="IWillStartAuto" >
            </action>
        </intent-filter>
    </receiver>

希望這會幫助你。

onTaskRemoved代碼阻止系統運行killProcess命令。 該延遲Kitkat通過使用引起alarmService.set ,這是不精確的從API 19. setExact代替。

如果您有一個要保持活動的service ,建議您向其附加notification並使其成為foreground 這樣,被殺的可能性就會降低。

import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Environment;
import android.os.IBinder;
import android.support.v7.app.NotificationCompat;

import java.io.File;
import java.io.IOException;

import activity.MainActivity;
import activity.R;
import fragment.MainFragment;

public class MyService extends Service {
    public static final int NOTIFICATION_CODE = 1;


    @Override
    public void onCreate() {
        super.onCreate();


    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        startForeground(NOTIFICATION_CODE, getNotification());
        return START_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onDestroy() {
        stopForeground(true);
        super.onDestroy();
    }

    @Override
    public boolean stopService(Intent name) {
        return super.stopService(name);
    }


    /**
     * Create and return a simple notification.
     */
    private Notification getNotification() {    
        Notification notification;
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
        builder.setColor(getResources()
                        .getColor(R.color.material_deep_teal_500))
                .setAutoCancel(true);

        notification = builder.build();
        notification.flags = Notification.FLAG_FOREGROUND_SERVICE | Notification.FLAG_AUTO_CANCEL;

        return notification;
    }


}

您可以修改此代碼以滿足您的需求,但這是啟動前台服務的基本結構。 如果被殺,會重新啟動。

你如何檢查套接字是否連接的issocketalive? 如果生成了sockettimeoutexception,則嘗試設置getinputstream和getoutputstream。 其他問題可能是套接字未正確關閉。 所以,如果可能的話,請將套接字代碼放在這

這對我有用

在應用程序標記的清單文件中的android:allowBackup =“false”中添加此屬性。

 <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<application
    android:allowBackup="false"
    tools:replace="android:allowBackup">

</application>
</manifest>

在Android中讓服務始終在后台運行的想法在99%的時候都是錯誤的。

系統需要“關閉” CPU,並切換到低電池使用情況。

您說您有基於位置的服務。 我假設您正在使用Google Play服務FusedLocationProvider ,如果不是, 您應該使用

FusedLocationProvider允許您使用PendingIntent注冊位置更改。 這意味着您的服務不需要一直運行,只需要注冊位置更改,然后在新位置進行時做出反應並執行其操作。

請參閱FusedLocationProviderApi 官方文檔

開始偵聽位置更新

  1. 使用LocationServices.API API連接到GoogleClient
  2. 根據您的需求構建您的LocationRequest (請參閱文檔
  3. 使用PendingIntent版本調用requestLocationUpdates()

停止聽

  1. 使用LocationServices.API API連接到GoogleClient
  2. 使用相同的PendingIntent調用removeLocationUpdates()

您的PendingIntent可以啟動另一個服務來處理新位置。

例如,從服務中執行此操作:

public void startMonitoringLocation(Context context) {
    GoogleApiClient client = new GoogleApiClient.Builder(context)
                 .addApi(LocationServices.API)
                 .build()
    ConnectionResult connectionResult = mApiClient.blockingConnect();
    if (connectionResult.isSuccess()) {
        LocationServices.FusedLocationApi
                .requestLocationUpdates(client, buildLocationRequest(), buildPendingIntent(context));
    } else {
        handleConnectionFailed(context);
    }
}

然后服務可以立即停止。

第一次運行此代碼將失敗。 與谷歌客戶端的連接通常要求用戶采取一些行動。 如果是這種情況, ConnectionResult.hasResolution()方法將返回true。 否則原因是別的,你無法從中恢復。 這意味着您唯一能做的就是通知用戶該功能不起作用或有一個很好的后備。

ConnectionResult.getResolution()給你PendingIntent ,你需要使用一個ActivitystartIntentSenderForResult()方法的Activity ,以解決這一意圖。 因此,您將創建一個Notification啟動您的Activity以解決該問題,並最終再次調用您的Service

我通常只是開始一項致力於完成所有工作的Activity 它更容易,但你不想在其中調用connectBlocking() 看看這個怎么做。

您可能會問為什么不直接在Activity請求位置更新。 這實際上非常好,除非你需要位置監視器自動啟動設備,即使用戶沒有明確打開應用程序。

<receiver android:name=".BootCompletedBroadcastReceiver">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>

這樣,您可以在重新啟動設備時運行服務以連接並請求位置更新。

有關如何構建位置請求的示例:

    public LocationRequest buildLocationRequest() {
        LocationRequest locRequest = LocationRequest.create();
        // Use high accuracy
        locRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        // how often do you need to check for the location
        // (this is an indication, it's not exact)
        locRequest.setInterval(REQUIRED_INTERVAL_SEC * 1000);
        // if others services requires the location more often
        // you can still receive those updates, if you do not want
        // too many consider setting this lower limit
        locRequest.setFastestInterval(FASTEST_INTERVAL_SEC * 1000);
        // do you care if the user moved 1 meter? or if he move 50? 1000?
        // this is, again, an indication
        locRequest.setSmallestDisplacement(SMALLEST_DISPLACEMENT_METERS);
        return locRequest;
    }

你未決的意圖:

public PendingIntent buildPendingIntent(Context context) {
    Intent intent = new Intent(context, LocationUpdateHandlerService.class);
    intent.setAction(ACTION_LOCATION_UPDATE);
    intent.setPackage(context.getPackageName());
    return PendingIntent.getService(context, REQUEST_CODE, intent, PendingIntent.FLAG_CANCEL_CURRENT);
}

如果您需要在后台工作,您的LocationUpdateHandlerService可以是IntentService

@Override
protected void onHandleIntent(Intent intent) {
    if (intent != null) {
        Bundle extras = intent.getExtras();
        if (extras != null && extras.containsKey(FusedLocationProviderApi.KEY_LOCATION_CHANGED)) {
            Location location = extras.getParcelable(FusedLocationProviderApi.KEY_LOCATION_CHANGED);
            handleLocationChanged(location);
        } else {
            Log.w(TAG, "Didn't receive any location update in the receiver");
        }

    }
}

但也可以是廣播或任何適合你的東西。

最后,我在Evernote JobService的幫助下完成了

Github鏈接 - https://github.com/evernote/android-job

第1步:添加evernote jobservice依賴項

implementation 'com.evernote:android-job:1.3.0-alpha03'

第2步:創建DemoJobCreator.java類

public class DemoJobCreator implements JobCreator {

@Override
@Nullable
public Job create(@NonNull String tag) {
    switch (tag) {
        case DemoSyncJob.TAG:
            return new DemoSyncJob();
        default:
            return null;
    }
}
}

第3步:創建DemoSyncJob.java類

public class DemoSyncJob extends Job {

public static final String TAG = ">>>> job_demo_tag";

@Override
@NonNull
protected Result onRunJob(Params params) {
    // run your job here
    Log.d(TAG, "onRunJob: ");
    if(!isMyServiceRunning(this.getContext(), TestService.class)){
        Intent intent=new Intent(context,TestService.class);
        context.startService(intent);
    }
    scheduleJob();
    return Job.Result.SUCCESS;
}

public static void scheduleJob() {
    new JobRequest.Builder(DemoSyncJob.TAG)
            .setExecutionWindow(2_000L, 2_000L)
            //.setPeriodic(900000) -> recommended. but it will work after 15 min (if you used this no need scheduleJob(); inside onRunJob();)
            .build()
            .schedule();
 }

 public static boolean isMyServiceRunning(Context context, Class<?> serviceClass) {
    try {
        ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
            if (serviceClass.getName().equals(service.service.getClassName())) {
                return true;
            }
        }
    }catch (Exception e){
        Log.e(TAG, "isMyServiceRunning: ",e );
    }
    return false;
  }
  }

第4步:在您的應用程序文件中(如果不可用,創建它)在onCreate()中添加以下行

 JobManager.create(this).addJobCreator(new DemoJobCreator());

第5步:最后在您的Activity中啟動JobService

DemoSyncJob.scheduleJob();

此JobService將檢查服務是否運行(每2秒)如果服務未運行,它將重新啟動該服務。

免責聲明:這可能不是正確的解決方案。 但它將100%工作。

我希望將來至少可以幫助任何人。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM