4

I have stuck with an issue of running a service when force stop is clicked and when i restart my mobile the service should be invoked.I have followed some examples but i cant able to achieve the task.Can any one guide me to achieve the task.

Required:

1.Service should run when force stop has been clicked from settings
2.Service should run when mobile has been restarted. 

TestActivity.java

package com.testsearching;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;

public class TestActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_search);
        startService(new Intent(this, ServiceTest.class));
    }
}

ServiceTest.java

package com.testsearching;

import java.util.Timer;
import java.util.TimerTask;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;

public class ServiceTest extends Service {

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

    @Override
    public void onCreate() {
        super.onCreate();
        mTimer = new Timer();
        mTimer.schedule(timerTask, 2000, 2 * 1000);

    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        try {

        } catch (Exception e) {
            e.printStackTrace();
        }
        return super.onStartCommand(intent, flags, startId);
    }

    private Timer mTimer;

    TimerTask timerTask = new TimerTask() {

        @Override
        public void run() {
            Log.e("Log", "Running");

        }
    };

    public void onDestroy() {
        try {
            mTimer.cancel();
            timerTask.cancel();
        } catch (Exception e) {
            e.printStackTrace();
        }
        Intent intent = new Intent("com.android.techtrainner");
        intent.putExtra("yourvalue", "torestore");
        sendBroadcast(intent);
    }
}

ReceiverCall.java

    package com.testsearching;

    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    import android.util.Log;
    import android.widget.Toast;

    public class ReceiverCall extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {

            if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
            Log.i("Service Stops", "Ohhhhhhh");
            context.startService(new Intent(context, ServiceTest.class));;
            Toast.makeText(context, "My start", Toast.LENGTH_LONG).show();
            }
        }

}

Manifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.testsearching"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="14"
        android:targetSdkVersion="16" />

    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
    <uses-permission android:name="android.permission.SEND_SMS" />
    <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

    <application
        android:allowBackup="true"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.testsearching.TestActivity"
            android:label="@string/app_name"
            android:theme="@android:style/Theme.NoTitleBar" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />


                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service android:name=".ServiceTest" >
            <intent-filter>
        <action android:name="com.testsearching.ServiceTest" />
    </intent-filter>

        </service>

        <receiver
            android:name="ReceiverCall"
            android:enabled="true"
            android:exported="true"
            android:permission="android.permission.RECEIVE_BOOT_COMPLETED" >
            <intent-filter>
                <action android:name="com.android.techtrainner" />
                <action android:name="android.intent.action.SCREEN_ON" />
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>
    </application>

</manifest>
Giridharan
  • 4,402
  • 5
  • 27
  • 30

2 Answers2

1

In theory, this is not possible; according to the Android security model.

As Panaj Kumar points out in the comments:

When user does force stop, means he does not want to run this application (any component). he is not interested anymore, and this is rights of user. SO android does not gives a way to keep running your service, even after forced close your app.

Android will prevent the app from restarting using the START_STICKY flag, and will disable the RECEIVE_BOOT_COMPLETED receiver. The system will also disable all Alarms that have been set for this app.

Before the system will allow the app to run again, the user must run an Activity of the app themselves.


That said, it seems that certain apps are still able to break the rules in this way. This should be considered incorrect and would be taking advantage of a security hole, however it shows that it is still possible, even on KitKat.

The Discovery Insure driving app seems to be able to restart itself when it has been force stopped, and will restart on boot:

However, this functionality should not be relied on - hopefully this security flaw will be fixed in future system updates.

Richard Le Mesurier
  • 29,432
  • 22
  • 140
  • 255
  • Le Mesurie: In some of the application force stop has been disabled .. Can i know how it can be achieved – Giridharan Aug 08 '14 at 06:18
  • 1
    @Giridharan AFAIK this is possible for System apps only, which means most of us will not be able to do this. Read more about that on this question: [How to sign Android app with system signature?](http://stackoverflow.com/questions/3635101/how-to-sign-android-app-with-system-signature) – Richard Le Mesurier Aug 08 '14 at 06:19
  • @jaimin Google does not review apps the way Apple reviews apps. It is possible to submit an app like this. If Google detects malware, or has an app reported to them, then they will remove it. There is a difference between what Google allows on the app store, and what the security model of the Android system allows. – Richard Le Mesurier Aug 08 '14 at 06:29
  • @RichardLeMesurier:suppose if am going to publish on my internal sever. not publishing in Google play can we able to achieve of force stop – Giridharan Aug 08 '14 at 06:35
  • 1
    It does not matter where you publish it. But if you have ROOT on the device, you can install to the system folder. There's some more info on that [over here...](http://www.addictivetips.com/mobile/how-to-install-any-app-as-system-app-on-android/) – Richard Le Mesurier Aug 08 '14 at 06:46
0

Write this on in your OnCreate of the main launching activity

if(!isMyServiceRunning(ServiceClass.class))
    context.startService(new Intent(context.getApplicationContext(),ServiceClass.class));

here is the running service check function

private boolean isMyServiceRunning(Class<?> serviceClass) {
    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;
        }
    }
    return false;
}

and Create your service with this architecture.Observe the return START_STICKY

public class ServiceClass extends IntentService {
    public ServiceClass()
    {
        super("null");
    }
    public Context context;
    public Intent intent;
    public Date currentTime;

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

    @Override
    protected void onHandleIntent(@Nullable Intent intnt) {

        currentTime = Calendar.getInstance().getTime();
        context = getApplicationContext();
        this.intent = intnt;
        Log.d("ServiceClass","Service class running "+ currentTime);

    }
}
Wajdan Ali
  • 179
  • 13
  • You are messing with factory methods of service, As per the documentation by using IntentService we cannot override onStartCommand the OS handles it by its own, the only method which do the work for intent service is onHandleIntent – Umar Ata Mar 05 '19 at 09:00
  • correct your answer or simply delete it to prevent it from downvotes. – Umar Ata Mar 05 '19 at 09:01
  • I agree that its a bad practice to override onStartCommand for IntentService because it haults the onHandleIntent and therefore it has to be handled manually which is done above. But as suggested by Richard Le Mesurier, let the user quit the service in first place. – Wajdan Ali Mar 06 '19 at 17:08