如何使服务无限期地保持活动状态



我正在编写一个应用程序,它可以检测来自耳机插孔的音频,并在满足某些音频条件时广播Intents(特别是当它检测到通过辅助音频设备刷卡的读数时(。

我的应用程序没有活动,它只是一个应用程序和服务。

一切都运行良好,除了该服务在相对较短的时间内(~一分钟(后被Android清理。

我很好奇我需要做什么来告诉Android这是一个有用的服务,除非它真的需要它的内存,否则它应该不管它。 我意识到我可以创建一个警报,每隔几秒钟唤醒一次,如果它注意到它不存在,就会启动服务,但这似乎是一个笨拙。有没有比这更Android(y(的方式来保持它的活力?

我的应用程序没有活动,它只是一个应用程序和服务。

这意味着您的应用程序永远不会在任何Android 3.1 +设备上运行,除非您与将手动启动您的服务的其他应用程序有一些联系。

我正在编写一个应用程序,用于检测来自耳机插孔的音频并在满足某些音频条件时广播 Intents(特别是当它检测到通过辅助音频设备刷卡的读数时(。

不要用几何形状来命名你的公司 - 它已经完成了。

我很好奇我需要做什么来告诉Android这是一个有用的服务,除非它真的需要它的内存,否则它应该不管它。

欢迎您使用startForeground()将其声明为前台服务。权衡是您需要显示一个 Notification ,理想情况下允许用户停止服务。请记住,用户可能不喜欢这个Notification ,但您坚持使用它,尤其是在 Android 4.3+ 上。从服务切换到活动可能会更好地为您服务,因此用户可以启动它,刷卡并处理任何交易。

使用 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;
}

使用示例:

http://developer.android.com/reference/android/app/Service.html#LocalServiceSample

更多信息:

http://developer.android.com/reference/android/app/Service.html#START_STICKY

我尝试了AlarmManager。它有效。我在 AlarmReceiver 中使用了 Contex.startService((。我可以检查我的服务是否正在运行,以便决定是否再次启动该服务。因此,即使我的服务被用户在设置中手动停止或被某些清洁应用程序终止,该服务也可以再次启动。这是下面的主要代码。

    package com.example.androidnetwork;
    import android.app.ActivityManager;
    import android.app.ActivityManager.RunningServiceInfo;
    import android.app.AlarmManager;
    import android.app.PendingIntent;
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    import android.os.Bundle;
    import android.support.v7.app.ActionBarActivity;
    import android.util.Log;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
public class MainActivity extends ActionBarActivity {
    private static final long INTERVAL = 5 * 1000; // unit: ms
    private Button mRegisterReceiverBtn;
    private Button mCheckNetStatusBtn;
    private Button mStopButton;
    private AlarmManager mAlarmManager;
    private PendingIntent mPendingIntent;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initData();
        initView();
    }
    private void initData() {
        mAlarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    }
    private void initView() {
        mRegisterReceiverBtn = (Button) findViewById(R.id.activity_main_start_btn);
        mCheckNetStatusBtn = (Button) findViewById(R.id.activity_main_start_check_net_status_bnt);
        mStopButton = (Button) findViewById(R.id.activity_main_stop);
        mRegisterReceiverBtn.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                MainActivity.this.createServiceControllerPendIntent();
                mAlarmManager.setInexactRepeating(
                        AlarmManager.ELAPSED_REALTIME_WAKEUP, 0, INTERVAL,
                        mPendingIntent);
            }
        });
        mCheckNetStatusBtn.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                MainActivity.this.startActivity(new Intent(MainActivity.this,
                        NetStatusActivity.class));
            }
        });
        mStopButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mPendingIntent != null) {
                    mAlarmManager.cancel(mPendingIntent);
                } else {
                    createServiceControllerPendIntent();
                    mAlarmManager.cancel(mPendingIntent);
                }
                // MainActivity.this.stopService(ServiceController
                // .getServiceIntent());
                Intent intent = new Intent();
                intent.setClass(getApplicationContext(),
                        NetStatusMonitorService.class);
                stopService(intent);
            }
        });
    }
    private void createServiceControllerPendIntent() {
        Intent intent = new Intent(MainActivity.this,
                ServiceController.class);
        mPendingIntent = PendingIntent.getBroadcast(MainActivity.this,
                0, intent, 0);
    }
    @Override
    protected void onDestroy() {
        deInitView();
        super.onDestroy();
    }
    private void deInitView() {
    }

    public static class ServiceController extends BroadcastReceiver {
        private static Intent sMonitorServiceIntent = null;
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.d("Service Controller", "onReceiver");
            if (isServiceRunning(context, NetStatusMonitorService.class) == false) {
                String info = "starting service by AlarmManager";
                Log.d("Service Controller", info);
                sMonitorServiceIntent = new Intent(context,
                        NetStatusMonitorService.class);
                context.startService(sMonitorServiceIntent);
            }
        }
            // this method is very important
        private boolean isServiceRunning(Context context, Class<?> serviceClass) {
            ActivityManager am = (ActivityManager) context
                    .getSystemService(Context.ACTIVITY_SERVICE);
            for (RunningServiceInfo serviceInfo : am
                    .getRunningServices(Integer.MAX_VALUE)) {
                String className1 = serviceInfo.service.getClassName();
                String className2 = serviceClass.getName();
                if (className1.equals(className2)) {
                    return true;
                }
            }
            return false;
        }
        public static Intent getServiceIntent() {
            return sMonitorServiceIntent;
        }
    }
}

您将无法限制用户从运行服务的设置中手动终止您的服务。即使作为设备管理员。

您可以添加启动接收器,屏幕锁和任何事件,这将重新启动已终止的服务,如果是,您也可以使用标志设置重新启动服务,如果应用程序被杀死高级任务杀手。

最新更新