简体   繁体   中英

Start my Android service with accepted user permissions

I have a little specific issue and I want some tips for that. I need to start just one time an Android service, and I can use these 2 options:

  1. Start the service from the onCreate() method of the MainActivity . The problem with this way is when the device is rotated with my app running, the onCreate() method is called again, because the MainActivity is restarted and I don't want that my service restarted because of this.
  2. Start it from the Android Application class . The problem is that before start the service, I need to check if some permissions was accepted by the user. So the first time that my application is started in the Application class the permissions are not accepted yet.

Reading this article Handle configuration changes I can see that is possible avoid the restart of my MainActivity but I don't know if this is a good practice. So maybe exist some way to request user permissions from the Application

  1. onCreate with be called once during Service lifecycle, but onStartCommand will be called every time you call startService

  2. You can't request user permission outside Activity context. So, you can run service but you are unable to do something that requires permission. You may register BroadcastReceiver inside your service for catching some "permission granted" intents. But this intent should be created and sended to service via broadcast in Activity context at the moment when user grants permission. Or you may use service commands instead

To prevent restarting your service just check in your MainActivity onCreate method is your service running

Function for checking service running:

private boolean isMyServiceRunning(Class<?> serviceClass) {
    ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
    for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
        if (serviceClass.getName().equals(service.service.getClassName())) {
            return true;
        }
    }
    return false;
}

And after that you just need to call it in your onCreate method:

@Override
public void onCreate(Bundle savedInstanceState) {
if(!isMyServiceRunning(MyService.class)) {
   //start your service
}
}

I am not sure the reason why you would like to start the service only once but I am gonna try to suggest an alternative to achieve this.

  1. Since you would like to ask for a user's permissions, the service cannot be started in the application class. So the only place you can start it is in the activity class. The key to solve this will be the onCreate and onStartCommand methods. If you define the service in the manifest file and then call Context.startService(context) multiple times, onCreate will be called only once as long as the system has not killed the service yet. onStartCommand will be called every time you call Context.startService(context) .

Hence in this approach, write the block of code that you need to be executed once in the onCreate method. For all updates, execute them in the onStartCommand method.

  1. Another option would be to dig deeper into android architecture components (LiveData, LifeCycle and observers)

I think the best way to deal with android's infamous rotation is to use ViewModel . As ViewModel survives device's rotation you can store a liveData of boolean initially set to true and observe it in onCreate() . Start the service only if the observed value is true and set it to false once you have started the service. Please see the following example,

In ViewModel

val startService = MutableLiveData<Boolean>(true)

In Activity 's onCreate()

viewModel.startService.observe(this, Observer {
        if (it) {
            startService()
            viewModel.startService.value = false
        }
})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM