0

I want to start an ever running service in android that checks which application is in background. If the foreground application is in the database of my app then it opens a password screen to enter the password.

What I've achieved is that my service runs as long as the application is running but when I stop the application(remove it from previous apps) then my service stops. I can open the locked apps without entering password. I tried a lot of solutions in the internet but none seems to work. Please help me,

package services;

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

import com.antzion.salmanali.lockapp.FeedReaderContract;
import com.antzion.salmanali.lockapp.FeedReaderDBHelper;
import com.antzion.salmanali.lockapp.PasswordSet;
import com.antzion.salmanali.lockapp.Pattern;

/**
 * Created by Salman Majid Ali on 12/26/2016.
 */

public class TestService extends Service {
String [] names;
FeedReaderDBHelper helper;
private AppChecker appChecker;
private String currentLocked = "";
Detector detector;

public TestService()
{
    if(Utils.postLollipop())
        detector = new LollipopDetector();
    else
        detector = new PreLollipopDetector();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Toast.makeText(getApplicationContext(), "service Start", Toast.LENGTH_SHORT).show();
    System.out.println("StartRemove");
    helper = new FeedReaderDBHelper(this);
    names = helper.getNames();
    Thread t = new Thread(new Runnable() {
        @Override
        public void run() {
            if(!AppChecker.running)
            {
                startChecker();
            }
        }
    });
    t.start();

    return START_STICKY;
}

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

@Override
public void onTaskRemoved(Intent rootIntent) {
    System.out.println("Remove");
    Intent restart=new Intent(getApplicationContext(),this.getClass());
    restart.setPackage(getPackageName());
    startService(restart);
    super.onTaskRemoved(rootIntent);
}
@Override
public    void onDestroy()
{
    Intent restart=new Intent(getApplicationContext(),this.getClass());
    restart.setPackage(getPackageName());
    startService(restart);
    super.onDestroy();
}

private void startChecker()
{
    appChecker = new AppChecker();
    appChecker
            .when(getPackageName(), new AppChecker.Listener() {
                @Override
                public void onForeground(String packageName) {
                    //Toast.makeText(getBaseContext(), "Our app is in the foreground.", Toast.LENGTH_SHORT).show();
                }
            })
            .other(new AppChecker.Listener() {
                @Override
                public void onForeground(String packageName) {
                    //System.out.println("Foreground " + packageName);
                    //System.out.println("In Other " + setting.getBooleanValue(PrefVars.onlock) + " " +  setting.getBooleanValue(PrefVars.onLock3) +
                    //        " " + setting.getBooleanValue(PrefVars.lockImmediately));
                    try {

                        if(currentLocked != null && !packageName.equals(currentLocked)
                                && !helper.isLocked(currentLocked)
                                && helper.getValue(FeedReaderContract.FeedEntry.onexit).equals("YES"))
                        {
                            Log.i("Locking ", currentLocked);

                            helper.lock(currentLocked);
                        }
                        if(helper.getPackageName(packageName))
                        {
                            //System.out.println(packageName + "App is in the Database");
                            if(helper.isLocked(packageName))
                            {
                                System.out.println("UnLocking " + packageName);
                                getPassword(packageName);
                                currentLocked = packageName;

                            }
                        }
                    }catch(Exception e)
                    {

                    }

                    //Toast.makeText(getBaseContext(), "Foreground: " + packageName, Toast.LENGTH_SHORT).show();
                }
            })
            .start(this);
}

private void getPassword(String pack)
{
    int i = helper.getPassOrPat();
    boolean pass = false;
    if(i == 1)
        pass = true;
    else
        pass = false;

    if(pass)
    {
        Intent intent = new Intent(this, PasswordSet.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.putExtra("PASS", pack);
        intent.putExtra("CONFIRM", "YES");
        startActivity(intent);
    }
    else
    {
        Intent intent = new Intent(this, Pattern.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.putExtra("PASS", pack);
        intent.putExtra("CONFIRM", "YES");
        startActivity(intent);
    }

}

}

I can provide AppChecker class's code if you want. please let me know what should I do to achieve the desired results. I will be very grateful to you.

TejaDroid
  • 6,561
  • 4
  • 31
  • 38
Tech Labs
  • 101
  • 1
  • 2
  • 9
  • Have you tried to move your code in OnCreate of Service because when service is recreated, it always call OnCreate – Faraz Ahmed Dec 27 '16 at 13:15
  • What device are you testing on? – David Wasser Dec 27 '16 at 13:25
  • Hi, thank you David for you response. I am testing it on HUAWEI TAG-L21 running android 5.1. The service stops when the app is swiped from the recent apps. – Tech Labs Dec 27 '16 at 13:43
  • @DavidWasser can you help me out please? – Tech Labs Dec 27 '16 at 13:57
  • Some devices (including Huawei, LG, Xiaomi) have a special settings page which lists apps that are allowed to run in the background. If your app is not in this list, once Android kills the process it will NOT be restarted. On different devices the settings page is in a different place, but try looking in "battery" or "security". On Huawei I think it is called "protected apps". – David Wasser Dec 27 '16 at 13:59
  • @DavidWasser So, can i programatically add my app to protected apps? – Tech Labs Dec 27 '16 at 14:02
  • Nope. You need to tell the user that he has to do it. See http://stackoverflow.com/questions/31638986/protected-apps-setting-on-huawei-phones-and-how-to-handle-it – David Wasser Dec 27 '16 at 14:03
  • 1
    @DavidWasser thank you for your resonse. I am really thankfull to you. Really appreciate that. – Tech Labs Dec 27 '16 at 14:11

2 Answers2

0

If service is started by your app, it will run on your app process and as soon as app gets killed, so does service. What you can do is in the onTaskRemoved method of your service, put this

Intent intent = new Intent("com.whatever.restartservice");
 sendBroadcast(intent);

and set broadcast receiver in service itself and in the onReceive, restart the service. I have tested and it works everytime app gets killed.

Edit: Try this

 @Override public void onTaskRemoved(Intent rootIntent){
     Intent restartServiceIntent = new Intent(getApplicationContext(), this.getClass());

     PendingIntent restartServicePendingIntent = PendingIntent.getService(
         getApplicationContext(), 1, restartServiceIntent, PendingIntent.FLAG_ONE_SHOT);
     AlarmManager alarmService = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
     alarmService.set(ELAPSED_REALTIME, elapsedRealtime() + 1000,
         restartServicePendingIntent);

     super.onTaskRemoved(rootIntent); 
}

It will restart your service no matter how it gets killed

Amit Bhandari
  • 3,014
  • 6
  • 15
  • 33
  • what if i start the service in the onTaskRemoved itself rather than sending and receiving the broadcast? – Tech Labs Dec 26 '16 at 13:03
  • i have done what you said but the service does not start again. Broadcast is sent but nothing happens. – Tech Labs Dec 26 '16 at 15:29
  • thank you for responding back. I will check it and let you know. Till that i will tell you what i found. My service runs on devices below lollipop and does not stop when app is stopped but for lollipop or above it stops. – Tech Labs Dec 26 '16 at 16:55
  • Still the service stops and not restarted when app is closed. – Tech Labs Dec 26 '16 at 17:05
0

For start ever running service, you have to define your service in manifest like as

<service
        android:name=".service.youservice"
        android:exported="true"
        android:process=":ServiceProcess" />

By using this, your service will run on another process of ServiceProcess.

There few step for define long running service as

  • onStartCommand() return START_STICKY
  • self start in onDestroy() of service
  • create a deamon service
  • create native deamon process (jin)
TejaDroid
  • 6,561
  • 4
  • 31
  • 38
  • I have declare the same as you described in the manifest but nothing is helping. And the others if you could explain in more details. – Tech Labs Dec 26 '16 at 15:31
  • I have found something. The service keeps running on devices below Lollipop but on lollipop it stops no matter what i do. Please help me through this. – Tech Labs Dec 26 '16 at 16:45