我正在编写一个应用程序来检测来自耳机插孔的音频并在满足某些音频条件时广播Intents(特别是当它检测到通过辅助音频设备读取卡片时)。
我的应用没有活动,它只是一个应用程序和服务。
除了在相对较短的时间段(约一分钟)后由Android清理服务外,一切都运行良好。
我很好奇我需要做些什么来告诉Android这是一个有用的服务,它应该不管它,除非它真的需要它的内存。我意识到我可以创建一个警报,每隔几秒唤醒一次,如果它注意到它不在那里就会启动服务,但这看起来像是一个混乱。是否有更多Android(y)方式让它保持活力?
答案 0 :(得分:8)
我的应用没有活动,它只是一个应用程序和服务。
这意味着您的应用永远无法在任何Android 3.1+设备上运行,除非您与其他手动启动服务的应用程序有某些联系。
我正在编写一个应用程序来检测来自耳机插孔的音频并在满足某些音频条件时广播Intents(特别是当它检测到通过辅助音频设备读取卡片时)。
不要在几何形状之后命名您的公司 - 它已经完成。 : - )
我很好奇我需要做些什么来告诉Android这是一个有用的服务,它应该不管它,除非它真的需要它的回忆。
欢迎您使用startForeground()
将其声明为前台服务。权衡是您需要显示Notification
,理想情况是允许用户停止服务。请注意,用户可能不会感谢Notification
,而是you are stuck with it, particularly on Android 4.3+。通过从服务切换到活动可以更好地服务,因此用户可以启动它,刷卡,并处理交易。
答案 1 :(得分:4)
使用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
答案 2 :(得分:1)
我试过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;
}
}
}
答案 3 :(得分:0)
您无法限制用户从设置,运行服务手动终止服务。即使是设备管理员。
你可以添加启动接收器,屏幕锁定器和任何事件,这将重新启动被杀死的服务,以及应用程序是否也可以重新启动服务并使用标记设置如果被杀死的应用程序已杀死高级任务杀手。