在Android上运行永久服务的最佳方法

7

我有一个服务,如果用户更改了位置,就会发出通知。 我希望这个服务一直运行,直到用户在应用程序管理器中明确强制停止我的应用程序。 我已经使用了以下方法:

        Intent intent1 = new Intent(context, LocationService2.class);
        PendingIntent contentIntent = PendingIntent.getService(context, 0, intent1, 0);
        AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(),2*60000, contentIntent);

服务类:

public class LocationService2 extends Service implements GoogleApiClient.ConnectionCallbacks,GoogleApiClient.OnConnectionFailedListener {
private GoogleApiClient mGoogleApiClient;

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Log.v("TAG", "STARTLS");
    mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();

    mGoogleApiClient.connect();
    return START_STICKY;
}

@Override
public void onConnected(Bundle bundle) {
    Log.i(TAG, "Location services connected.");

    Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
    // Use this location to give notification if required.
}

@Override
public void onConnectionSuspended(int i) {
    Log.i(TAG, "Location services suspended. Please reconnect.");
}

@Override
public void onConnectionFailed(ConnectionResult connectionResult) {

}

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

@Override
public void onDestroy() {
    super.onDestroy();
    mGoogleApiClient.disconnect();
}
}

这种方法并不适用于所有手机。如果使用AlarmManager是最好的方式,那么我该如何改进代码以使其在所有手机上都能正常运行?


你能发布你的服务类吗? - santoXme
6个回答

3

您应该将服务设置为前台服务。您可以在这里找到一个教程。


1
清单条目

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

<receiver android:name="YourPackagename.AlarmReceiver" >
</receiver>

当手机重新启动时需要重新初始化闹钟管理器 RestartReceiver.java

public class RestartReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
            AlarmManager alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
            Intent intentReciever = new Intent(context, AlarmReceiver.class);
            PendingIntent alarmIntent = PendingIntent.getBroadcast(context, 0, intentReciever, 0);
            alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, (System.currentTimeMillis() + GlobalContext.PUSH_NOTIFICATION_INTERVAL),
                    GlobalContext.PUSH_NOTIFICATION_INTERVAL, alarmIntent);
        }
    }

}

AlarmReceiver.java

public class AlarmReceiver extends BroadcastReceiver{

    @Override
    public void onReceive(Context context, Intent intent) {
        //you can put your logic over here
    }
}

将以下代码放入您的启动画面中。
private void initService() {
        if(!app_preferences.getBoolean("isServiceRunning", false))
        {
            AlarmManager alarmMgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
            Intent intentReciever = new Intent(LoadingScreen.this, AlarmReceiver.class);
            PendingIntent alarmIntent = PendingIntent.getBroadcast(LoadingScreen.this, 0, intentReciever, 0);
            alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, (System.currentTimeMillis()+GlobalContext.PUSH_NOTIFICATION_INTERVAL),
                    GlobalContext.PUSH_NOTIFICATION_INTERVAL, alarmIntent);
            app_preferences.edit().putBoolean("isServiceRunning", true).commit();
        }
    }

//注意:使用共享偏好来检查您的闹钟服务是否正在运行并不是一个好的方式。


我已经处理了bootcomlete接收器,但在我的情况下,问题是即使用户从某些手机的应用程序切换器中删除应用程序,服务仍会停止运行。 - Tushar Kathuria
我已经发布了我的服务类。正如你所看到的,在onStartCommand中我返回了'START_STICKY'。 - Tushar Kathuria
服务仍会在四到五个小时后停止。 - Ruchir Baronia
@RuchirBaronia 请查看 https://developer.android.com/about/versions/oreo/background - Bhavesh Jethani

0
随时重新启动服务,无论何时它被终止。
@Override
public void onDestroy() {
    super.onDestroy();
    mGoogleApiClient.disconnect();
    startService(new Intent(this, LocationService2.class));
}

0
制作一个永不停止的服务的步骤如下:
1.) Start service using alarmManager.
2.) Check in onResume if service is running & restart if not.
3.) Return START_STICKY from onStartCommand().
4.) In OnStartCommand() , create a thread and do the needful from that thread .All the logical stuff should be there in while(true). 

这样,您的服务就永远不会被终止。


0
在给定的代码中,我加入了一些好的东西,比如你可以通过监听器使用绑定服务与活动进行通信。你可以编写代码在服务中通知你的活动你失去了互联网连接...
创建一个永远不会结束的粘性服务。如果用户杀死应用程序,它将自动重新启动。
与闹钟管理器相比,您可能会遇到重复/多个服务启动的问题。例如,我们需要识别并防止重复启动服务,如果已经创建了闹钟管理器,则不要根据我在同一问题中编写的另一个答案再次启动。

Manifest.xml

<receiver android:name=".BootCompleteReceiver"><intent-filter><action android:name="android.intent.action.BOOT_COMPLETED"/></intent-filter></receiver>
<service android:name=".MyService" android:enabled="true" android:exported="false"/>

MyService.java

public class MyService extends Service {

        CommunicationListner listener;
        public class LocalBinder extends Binder {
            public MyService getService() {
                // Return this instance of LocalService so clients can call public methods
                return MyService.this;
            }
        }


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

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

        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            try {
                unregisterReceiver(internetConnectionReceiver);
            } catch (Exception e) {
            }
            registerReceiver(internetConnectionReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
            return START_STICKY;
        }

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

        //communication with activity
        public void registerChatReceivedListener(CommunicationListner listener) {
            this.listener = listener;
        }

        public void removeChatReceivedListener() {
            chatListener = null;
        }


        private BroadcastReceiver internetConnectionReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {

            }
        };

        public MyService() {
        }

    }

为了在手机重启时重新启动您的服务 BootCompleteReceiver.Java

public class BootCompleteReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
            context.startService(new Intent(context, MyService.class));
        }
    }
}

在您的启动画面中放置代码,以便启动我的服务。如果服务已经启动,则无需担心。
startService(new Intent(getApplicationContext(), MyService.class));

0

Android 5及以上版本的解决方案是使用AlarmManager和Broadcast Receiver。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接