11

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

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

除了服务在相对较短的时间段(约一分钟)后由 Android 清理之外,一切都运行良好。

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

4

4 回答 4

8

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

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

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

不要以几何形状命名你的公司——它已经完成了。:-)

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

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

于 2013-08-13T22:02:52.120 回答
5

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

于 2013-08-13T21:55:33.300 回答
1

我试过报警管理器。有用。我在 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;
        }
    }

}
于 2014-06-25T07:20:53.300 回答
0

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

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

于 2013-08-13T21:42:47.233 回答