我正在编写一个应用程序,它可以检测来自耳机插孔的音频,并在满足某些音频条件时广播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;
}
}
}
您将无法限制用户从运行服务的设置中手动终止您的服务。即使作为设备管理员。
您可以添加启动接收器,屏幕锁和任何事件,这将重新启动已终止的服务,如果是,您也可以使用标志设置重新启动服务,如果应用程序被杀死高级任务杀手。