如何保持android服务在后台运行?

如何保持android服务在后台运行?,android,service,background,Android,Service,Background,我是为我大学最后一年的项目开发Android应用程序的新手。最近,我尝试创建一个android应用程序,它可以在后台运行服务,即使我的活动已被清除或关闭,例如通过最近的活动 我已经做了但仍然失败了: 试图返回START_粘性 尝试使用AlamManager重新安排服务的重新启动 我注意到这个问题只发生在新设备中。我的服务在emulator中运行良好,但在真实设备中运行不好。我使用的是Xiomi Redmi Note 3(Lolipop),我非常了解它的内置任务管理器。然而,即使我为我的应用程

我是为我大学最后一年的项目开发Android应用程序的新手。最近,我尝试创建一个android应用程序,它可以在后台运行服务,即使我的活动已被清除或关闭,例如通过最近的活动

我已经做了但仍然失败了:

  • 试图返回START_粘性
  • 尝试使用AlamManager重新安排服务的重新启动
我注意到这个问题只发生在新设备中。我的服务在emulator中运行良好,但在真实设备中运行不好。我使用的是Xiomi Redmi Note 3(Lolipop),我非常了解它的内置任务管理器。然而,即使我为我的应用程序启用/允许autostart,android仍然会杀死我的后台服务

我测试了其他几个应用程序,例如whatssup,甚至playstore中的几个不受欢迎的应用程序(我已经允许autostart),它们可以像往常一样自动“重启”服务

我已经对此做了很多研究,到目前为止还没有找到真正的解决办法

这是我目前的服务代码:

package com.muzaffar.myApps.App;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.IBinder;
import android.os.SystemClock;
import android.widget.Toast;

import com.muzaffar.myApps.Lib.PhoneInfo;

import java.util.concurrent.TimeUnit;

public class myAppsServices extends Service {

    private static final int FIRST_RUN_TIMEOUT_MILISEC = 5 * 1000;
    private static final int SERVICE_STARTER_INTERVAL_MILISEC = 1 * 1000;
    private static final int SERVICE_TASK_TIMEOUT_SEC = 10;
    private final int REQUEST_CODE = 1;

    private AlarmManager serviceReStarterAlarmManager = null;
    private MyTask asyncTask = null;

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

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

        // Start of timeout-autostarter for our service (watchdog)
        startServiceReStarter();

        // Start performing service task
        serviceTask();

        /*Toast.makeText(this, "Service Started!", Toast.LENGTH_LONG).show();*/
    }

    /***
     *       _____                     _
     *      / ____|                   (_)
     *     | (___    ___  _ __ __   __ _   ___  ___  ___
     *      \___ \  / _ \| '__|\ \ / /| | / __|/ _ \/ __|
     *      ____) ||  __/| |    \ V / | || (__|  __/\__ \
     *     |_____/  \___||_|     \_/  |_| \___|\___||___/
     *
     *      http://patorjk.com/software/taag/#p=display&h=1&v=0&c=c&f=Big&t=Shared%20Pref
     */

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Toast.makeText(getApplicationContext(), "Services Has Been Started!", Toast.LENGTH_SHORT).show();


        return START_STICKY;
    }

    /***
     *      _____                 _     _  __ _  _  _  __  __
     *     |  __ \               | |   | |/ /(_)| || ||  \/  |
     *     | |  | |  ___   _ __  | |_  | ' /  _ | || || \  / |  ___
     *     | |  | | / _ \ | '_ \ | __| |  <  | || || || |\/| | / _ \
     *     | |__| || (_) || | | || |_  | . \ | || || || |  | ||  __/
     *     |_____/  \___/ |_| |_| \__| |_|\_\|_||_||_||_|  |_| \___|
     *
     *
     */

    private void StopPerformingServiceTask() {
        asyncTask.cancel(true);
    }

    @Override
    public void onDestroy() {
        // performs when user or system kill our service
        /*Toast.makeText(getApplicationContext(),"Services Has Been Destroyed!",Toast.LENGTH_SHORT).show();*/
        StopPerformingServiceTask();
    }

    private void serviceTask() {
        asyncTask = new MyTask();
        asyncTask.execute();
    }

    class MyTask extends AsyncTask<Void, Void, Void> {
        @Override
        protected Void doInBackground(Void... params) {
            try {
                for (;;) {
                    TimeUnit.SECONDS.sleep(SERVICE_TASK_TIMEOUT_SEC);

                    // check does performing of the task need
                    if(isCancelled()) {
                        break;
                    }

                    // Initiating of onProgressUpdate callback that has access to UI
                    publishProgress();
                }

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onProgressUpdate(Void... progress) {
            super.onProgressUpdate(progress);
            //Toast.makeText(getApplicationContext(), "Please dont kill me, Im tired dying...T.T", Toast.LENGTH_LONG).show();
        }
    }

    // We should to register our service in AlarmManager service
    // for performing periodical starting of our service by the system
    private void startServiceReStarter() {
        Intent intent = new Intent(this, ServiceStarter.class);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(this, this.REQUEST_CODE, intent, 0);

        if (pendingIntent == null) {
            /*Toast.makeText(this, "Some problems with creating of PendingIntent", Toast.LENGTH_LONG).show();*/
        } else {
            if (serviceReStarterAlarmManager == null) {
                serviceReStarterAlarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
                serviceReStarterAlarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME,
                        SystemClock.elapsedRealtime() + FIRST_RUN_TIMEOUT_MILISEC,
                        SERVICE_STARTER_INTERVAL_MILISEC, pendingIntent);
            }
        }
    }
}
package com.muzaffar.myApps.App;
导入android.app.AlarmManager;
导入android.app.pendingent;
导入android.app.Service;
导入android.content.Context;
导入android.content.Intent;
导入android.os.AsyncTask;
导入android.os.IBinder;
导入android.os.SystemClock;
导入android.widget.Toast;
导入com.muzaffar.myApps.Lib.PhoneInfo;
导入java.util.concurrent.TimeUnit;
公共类myAppsServices扩展服务{
私有静态最终整数首次运行超时毫秒=5*1000;
专用静态最终整备服务\u启动器\u间隔\u毫秒=1*1000;
专用静态最终整型服务任务超时秒=10;
私人最终int请求_代码=1;
专用AlarmManager服务重新启动ArmManager=null;
私有MyTask asyncTask=null;
@凌驾
公共IBinder onBind(意向){
返回null;
}
@凌驾
public void onCreate(){
super.onCreate();
//启动我们服务的超时自动启动程序(看门狗)
startServiceReStarter();
//开始执行服务任务
serviceTask();
/*Toast.makeText(此“服务已启动!”,Toast.LENGTH_LONG.show()*/
}
/***
*       _____                     _
*      / ____|                   (_)
*     | (___    ___  _ __ __   __ _   ___  ___  ___
*      \___ \  / _ \| '__|\ \ / /| | / __|/ _ \/ __|
*| | | | | | | | | | | | | | | | | | | | | | | | | | |\
*     |_____/  \___||_|     \_/  |_| \___|\___||___/
*
*      http://patorjk.com/software/taag/#p=display&h=1&v=0&c=c&f=Big&t=Shared%20Pref
*/
@凌驾
公共int onStartCommand(Intent Intent、int标志、int startId){
Toast.makeText(getApplicationContext(),“服务已启动!”,Toast.LENGTH\u SHORT.show();
返回开始时间;
}
/***
*      _____                 _     _  __ _  _  _  __  __
*     |  __ \               | |   | |/ /(_)| || ||  \/  |
*     | |  | |  ___   _ __  | |_  | ' /  _ | || || \  / |  ___
*     | |  | | / _ \ | '_ \ | __| |  <  | || || || |\/| | / _ \
*     | |__| || (_) || | | || |_  | . \ | || || || |  | ||  __/
*     |_____/  \___/ |_| |_| \__| |_|\_\|_||_||_||_|  |_| \___|
*
*
*/
私有无效停止执行服务任务(){
asyncTask.cancel(true);
}
@凌驾
公共空间{
//当用户或系统终止我们的服务时执行
/*Toast.makeText(getApplicationContext(),“服务已被销毁!”,Toast.LENGTH\u SHORT.show()*/
停止执行ServiceTask();
}
私有void serviceTask(){
asyncTask=新建MyTask();
asyncTask.execute();
}
类MyTask扩展了AsyncTask{
@凌驾
受保护的Void doInBackground(Void…参数){
试一试{
对于(;;){
时间单位。秒。睡眠(服务任务超时秒);
//检查是否需要执行任务
如果(isCancelled()){
打破
}
//启动有权访问UI的onProgressUpdate回调
出版进度();
}
}捕捉(中断异常e){
e、 printStackTrace();
}
返回null;
}
@凌驾
受保护的void onProgressUpdate(void…progress){
super.onProgressUpdate(进度);
//Toast.makeText(getApplicationContext(),“请不要杀我,我累得要死了…T.T”,Toast.LENGTH\u LONG.show();
}
}
//我们应该在AlarmManager服务中注册我们的服务
//通过系统定期启动我们的服务
私有void startServiceReStarter(){
Intent Intent=新的Intent(这是ServiceStarter.class);
PendingIntent PendingIntent=PendingIntent.getBroadcast(this,this.REQUEST_代码,intent,0);
if(pendingIntent==null){
/*Toast.makeText(这是“创建PendingEvent的一些问题”,Toast.LENGTH_LONG.show()*/
}否则{
如果(ServiceRestartArmManager==null){
serviceReStarterAlarmManager=(AlarmManager)getSystemService(报警服务);
serviceReStarterAlarmManager.setRepeating(AlarmManager.Alarm\u REALTIME,
SystemClock.elapsedRealtime()+第一次运行超时毫秒,
服务_启动器_间隔_毫秒,待定);
}
}
}
}
我的活动代码
package com.muzaffar.myApps.App;
导入android.app.ActivityManager;
导入android.app.admin.DevicePolicyManager;
导入android.content.ComponentName;
导入android.content.Context;
导入android.content.Intent;
导入android.content.pm.ActivityInfo;
导入android.graphi
package com.muzaffar.myApps.App;

import android.app.ActivityManager;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.muzaffar.spycare.App.SpycareServices;
import com.muzaffar.spycare.App.Util;
import com.muzaffar.spycare.R;
import com.muzaffar.spycare.Receiver.DeviceAdmin;

/**
 * Created by OligoCoco on 11/2/2016.
 */

public class Main_Activity extends AppCompatActivity implements View.OnClickListener {

    //Default PIN
    public static final String DEFAULT_PIN = "1234";

    //Import Instance Shared Pref
    Util myPref=new Util(Main_Activity.this);

    //ImportButton
    Button btn_setting, btn_Stealth, btn_Test_Page;
    public static Button btn_device_manager;
    TextView txt_Start_Stop;

    private boolean isRunning = false;
    private EditText SecretCode;
    String device_admin;

    //Enable Device Admin
    private ComponentName deviceAdmin;
    private DevicePolicyManager devicePolicyManager;
    private static final int REQUEST_CODE_ENABLE_ADMIN = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        /*Initialize*/
        deviceAdmin = new ComponentName(getApplicationContext(), DeviceAdmin.class);
        devicePolicyManager = (DevicePolicyManager) getSystemService(DEVICE_POLICY_SERVICE);

        /*Initialize Button*/
        txt_Start_Stop = (TextView) findViewById(R.id.app_start_stop);
            /*Return default status of txt_Start_Stop*/
            showServiceStatus();
        btn_setting = (Button) findViewById(R.id.app_setting);
        btn_setting.setOnClickListener(this);
        btn_device_manager = (Button) findViewById(R.id.app_device_manager);
            device_admin = myPref.getSavedShared("device_admin");
            if(device_admin==null || device_admin.equals("false") || device_admin.equals("")){
                btn_device_manager.setText(R.string.app_device_manager);
                btn_device_manager.setClickable(true);
                btn_device_manager.setEnabled(true);
            }else{
                btn_device_manager.setText(R.string.app_device_manager_activated);
                btn_device_manager.setClickable(false);
                btn_device_manager.setEnabled(false);
            }
        btn_device_manager.setOnClickListener(this);
        btn_Stealth = (Button) findViewById(R.id.app_start_stealth);
        btn_Stealth.setOnClickListener(this);
        SecretCode = (EditText) findViewById(R.id.app_secret_code);
        SecretCode.setTextColor(Color.LTGRAY);
        SecretCode.setText(myPref.getSavedShared("Secret_Code"));

        //Start Services
        startMonitoring();

        //Request on potret
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    }

    @Override
    public void onStop(){
        super.onStop();
        myPref.saveToPref("Secret_Code",SecretCode.getText().toString());
        final int flags = DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY;
        if (devicePolicyManager.isAdminActive(deviceAdmin)) {
            devicePolicyManager.resetPassword(myPref.getSavedShared("Secret_Code"), flags);
        }
    }


    /***
     *      _____                _              __  __
     *     |  __ \              (_)            |  \/  |
     *     | |  | |  ___ __   __ _   ___  ___  | \  / |  __ _  _ __    __ _   __ _   ___  _ __
     *     | |  | | / _ \\ \ / /| | / __|/ _ \ | |\/| | / _` || '_ \  / _` | / _` | / _ \| '__|
     *     | |__| ||  __/ \ V / | || (__|  __/ | |  | || (_| || | | || (_| || (_| ||  __/| |
     *     |_____/  \___|  \_/  |_| \___|\___| |_|  |_| \__,_||_| |_| \__,_| \__, | \___||_|
     *                                                                        __/ |
     *                                                                       |___/
     */


    /*Device Manager*/
    private void lock() {
        devicePolicyManager.setPasswordQuality(deviceAdmin, DevicePolicyManager.PASSWORD_QUALITY_NUMERIC);
        devicePolicyManager.setPasswordMinimumLength(deviceAdmin, 4);
        final int flags = DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY;
        devicePolicyManager.resetPassword(myPref.getSavedShared("Secret_Code"), flags);

    }

    @Override
    protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == REQUEST_CODE_ENABLE_ADMIN && resultCode == RESULT_OK) {
            btn_device_manager.setText(this.getString(R.string.app_device_manager_activated));
            btn_device_manager.setClickable(false);
            btn_device_manager.setEnabled(false);
            lock();
        }else{
            btn_device_manager.setText(this.getString(R.string.app_device_manager));
            btn_device_manager.setClickable(true);
            btn_device_manager.setEnabled(true);
        }
    }

    /***
     *       _____             _                      __  __        _    _                 _
     *      / ____|           | |                    |  \/  |      | |  | |               | |
     *     | |     _   _  ___ | |_  ___   _ __ ___   | \  / |  ___ | |_ | |__    ___    __| |
     *     | |    | | | |/ __|| __|/ _ \ | '_ ` _ \  | |\/| | / _ \| __|| '_ \  / _ \  / _` |
     *     | |____| |_| |\__ \| |_| (_) || | | | | | | |  | ||  __/| |_ | | | || (_) || (_| |
     *      \_____|\__,_||___/ \__|\___/ |_| |_| |_| |_|  |_| \___| \__||_| |_| \___/  \__,_|
     *
     *
     */

    /*Function to listen which button has been clicked and response correspondingly*/
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.app_device_manager:
                defaultPIN();
                if (devicePolicyManager.isAdminActive(deviceAdmin)) {
                    //If device admin is active

                } else {
                    // Launch the activity to have the user enable our admin.
                    Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
                    intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, deviceAdmin);
                    startActivityForResult(intent, REQUEST_CODE_ENABLE_ADMIN);
                    myPref.saveToPref("device_admin", "true");
                }
                break;
            case R.id.app_setting:
                defaultPIN();
                Intent a = new Intent(getApplicationContext(), Setting_Activity.class);
                startActivity(a);
                break;
            case R.id.app_start_stealth:
                defaultPIN();
                Intent b = new Intent(Intent.ACTION_MAIN);
                b.addCategory(Intent.CATEGORY_HOME);
                b.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                startActivity(b);
                break;
        }
    }

    /*Function used to start the monitoring process*/
    private void startMonitoring() {
        //startService(new Intent(this, SpycareServices.class));
        startService(new Intent(this, SpycareServices.class));
    }

    /*Function used to stop the monitoring process*/
    private void stopMonitoring() {
        //stopService(new Intent(this, SpycareServices.class));
        stopService(new Intent(this, SpycareServices.class));
    }

    /*Function to change button status*/
    private void showServiceStatus(){
        // Show the current service state
        /*if(isMyServiceRunning(SpycareServices.class,getApplicationContext())){*/
        if(isMyServiceRunning(SpycareServices.class,getApplicationContext())){
            txt_Start_Stop.setText(this.getString(R.string.stop_label));
            txt_Start_Stop.setTextColor(Color.BLUE);
            isRunning = true;
        }else{
            txt_Start_Stop.setText(this.getString(R.string.start_label));
            txt_Start_Stop.setTextColor(Color.RED);
            isRunning = false;
            //If service not running
            startMonitoring();
            //Return
            Intent a = new Intent(getApplicationContext(), Main_Activity.class);
            startActivity(a);
        }
    }

    /*Function to check if certain services is running*/
    private boolean isMyServiceRunning(Class<?> serviceClass,Context context) {
        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;
    }

    /*Function to place default PIN*/
    public void defaultPIN(){
        String compA = myPref.getSavedShared("Secret_Code");
        if(compA.isEmpty()){
            Toast.makeText(getApplicationContext(), "PIN Cannot be empty, Applying default PIN "+DEFAULT_PIN, Toast.LENGTH_SHORT).show();
            myPref.saveToPref("Secret_Code",DEFAULT_PIN);

            //Set DMP Pass
            final int flags = DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY;
            if (devicePolicyManager.isAdminActive(deviceAdmin)) {
                devicePolicyManager.resetPassword(DEFAULT_PIN, flags);
            }

            SecretCode.setText(myPref.getSavedShared("Secret_Code"));

        }
    }

}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Toast.makeText(getApplicationContext(), "Services Has Been Started!", Toast.LENGTH_SHORT).show();


    return START_STICKY;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("LocalService", "Received start id " + startId + ": " + intent);
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}
<service ...
         android:process=":separate" >
    ...
</service>