我从我的主要Android活动开始提供服务,如下所示:
final Context context = base.getApplicationContext();
final Intent intent = new Intent(context, MyService.class);
startService(intent);
当我通过从最近的应用列表中滑出来关闭活动页面时,服务会停止运行并在一段时间后重新启动。由于我的应用程序要求,我无法将持久服务与通知一起使用。如何使服务不重启或关闭,并继续在应用程序退出时运行?
答案 0 :(得分:39)
我处于相同的情况,到目前为止,我知道应用程序关闭时服务也因为它们在一个线程中而关闭,所以服务应该在另一个线程上,以便它不被关闭,仔细研究一下,然后通过警报管理器查看服务的活动情况http://www.vogella.com/articles/AndroidServices/article.html,这样您的服务就不会显示在通知中。
最后,经过我所做的所有研究后,我逐渐意识到长期服务的最佳选择是startForeground()
,因为它是为此而制定的,系统实际上可以很好地处理您的服务
答案 1 :(得分:12)
This可能会对您有所帮助。我可能会弄错,但在我看来,这与您在START_STICKY
方法中返回onStartCommand()
有关。您可以通过返回START_NOT_STICKY
来避免再次调用服务。
答案 2 :(得分:12)
让你在Mainifest中以这样的方式服务
<service
android:name=".sys.service.youservice"
android:exported="true"
android:process=":ServiceProcess" />
然后您的服务将在名为ServiceProcess的其他进程
上运行如果你想让你的服务永不消亡:
onStartCommand()返回START_STICKY
onDestroy() - &gt; startself
创建Deamon服务
jin - &gt;创建一个Native Deamon进程,你可以在github上找到一些开源项目
startForeground(),有一种方法可以在没有通知的情况下启动地面,google it
答案 3 :(得分:3)
应用程序关闭时无法启动服务的主要问题,Android OS(在某些操作系统中)将终止资源优化服务,如果您无法重新启动该服务,请调用警报管理器像这样启动reciver,这是整个代码,这段代码将保持你的服务。
清单是,
<service
android:name=".BackgroundService"
android:description="@string/app_name"
android:enabled="true"
android:label="Notification" />
<receiver android:name="AlarmReceiver">
<intent-filter>
<action android:name="REFRESH_THIS" />
</intent-filter>
</receiver>
IN Main Activty以这种方式启动报警管理器,
String alarm = Context.ALARM_SERVICE;
AlarmManager am = (AlarmManager) getSystemService(alarm);
Intent intent = new Intent("REFRESH_THIS");
PendingIntent pi = PendingIntent.getBroadcast(this, 123456789, intent, 0);
int type = AlarmManager.RTC_WAKEUP;
long interval = 1000 * 50;
am.setInexactRepeating(type, System.currentTimeMillis(), interval, pi);
这将调用reciver和reciver,
public class AlarmReceiver extends BroadcastReceiver {
Context context;
@Override
public void onReceive(Context context, Intent intent) {
this.context = context;
System.out.println("Alarma Reciver Called");
if (isMyServiceRunning(this.context, BackgroundService.class)) {
System.out.println("alredy running no need to start again");
} else {
Intent background = new Intent(context, BackgroundService.class);
context.startService(background);
}
}
public static boolean isMyServiceRunning(Context context, Class<?> serviceClass) {
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningServiceInfo> services = activityManager.getRunningServices(Integer.MAX_VALUE);
if (services != null) {
for (int i = 0; i < services.size(); i++) {
if ((serviceClass.getName()).equals(services.get(i).service.getClassName()) && services.get(i).pid != 0) {
return true;
}
}
}
return false;
}
}
当打开Android应用程序并关闭应用程序时,这个Alaram会调用一次。服务是这样的,
public class BackgroundService extends Service {
private String LOG_TAG = null;
@Override
public void onCreate() {
super.onCreate();
LOG_TAG = "app_name";
Log.i(LOG_TAG, "service created");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(LOG_TAG, "In onStartCommand");
//ur actual code
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
// Wont be called as service is not bound
Log.i(LOG_TAG, "In onBind");
return null;
}
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
@Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
Log.i(LOG_TAG, "In onTaskRemoved");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i(LOG_TAG, "In onDestroyed");
}
}
答案 4 :(得分:3)
服务有时非常复杂。
当您从活动(或您的流程)启动服务时,该服务基本上处于相同的流程中。
引用开发者说明
关于Service类的大多数混淆实际上都围绕着它不是:
服务不是一个单独的过程。 Service对象本身并不意味着它在自己的进程中运行;除非另有说明,否则它与其所属的应用程序运行的过程相同。
服务不是线程。它不是从主线程开始工作的手段(以避免应用程序无响应错误)。
所以,这意味着,如果用户将应用程序从最近的任务中移开,它将删除您的进程(这包括您的所有活动等)。 现在,我们来看三个场景。
首先 服务没有前景通知。
在这种情况下,您的流程会与您的服务一起被杀死。
第二 服务 前景通知
在这种情况下,服务不会被杀死,进程也不会被杀死
第三次 方案 如果该服务没有前台通知,则在应用关闭时它仍然可以继续运行。我们可以通过使服务在不同的进程中运行来实现。 (但是,我听说有人说这可能不起作用。留给你自己尝试)
您可以通过包含以下属性在单独的流程中创建服务 在你的清单中。
<强>机器人:过程=&#34;:yourService&#34; 强>
或
android:process =&#34; yourService&#34; 进程名称必须以小写字母开头。
引用开发者说明
如果分配给此属性的名称以冒号(&#39;:&#39;)开头,则在需要时创建一个专用于应用程序的新进程,并且该服务在该进程中运行处理。如果进程名称以小写字符开头,则该服务将在该名称的全局进程中运行,前提是它具有执行此操作的权限。这允许不同应用程序中的组件共享进程,从而减少资源使用。
这是我收集的内容,如果有人是专家,如果我错了,请纠正我:)
答案 5 :(得分:2)
试试这个,它会让服务在后台运行。
<强> BackServices.class 强>
public class BackServices extends Service{
@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Let it continue running until it is stopped.
Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "Service Destroyed", Toast.LENGTH_LONG).show();
}
}
MainActivity onCreate
中的删除此行代码
startService(new Intent(getBaseContext(), BackServices.class));
现在该服务将继续在后台运行。
答案 6 :(得分:1)
最佳解决方案是在android中使用同步适配器来启动服务。创建一个同步适配器并在onPerformSync方法中调用启动服务..要创建同步帐户,请参阅此链接https://developer.android.com/training/sync-adapters/index.html
为何选择SyncAdapter? Ans:因为之前您曾经使用App上下文启动服务。因此,每当您的应用程序进程被杀死时(当您从任务管理器中移除它或操作系统因为缺乏资源而将其杀死时),您的服务也将被删除。 SyncAdapter将无法在应用程序线程中工作..所以,如果你在里面调用..服务将不再被删除..除非你写代码删除它。
答案 7 :(得分:1)
对服务和活动使用相同的过程以及服务中的START_STICKY或START_REDELIVER_INTENT是在应用程序重新启动时能够重新启动服务的唯一方法,例如,当用户关闭应用程序时,以及何时由于优化原因,系统决定关闭它。您无法拥有永久运行且不会中断的服务。这是设计,智能手机不能长时间运行连续过程。这是因为电池寿命是最高优先级。您需要设计服务,以便随时处理停止服务。
答案 8 :(得分:1)
您必须在Service类中添加此代码,以便在处理您的进程时处理该案例
@Override
public void onTaskRemoved(Intent rootIntent) {
Intent restartServiceIntent = new Intent(getApplicationContext(), this.getClass());
restartServiceIntent.setPackage(getPackageName());
PendingIntent restartServicePendingIntent = PendingIntent.getService(getApplicationContext(), 1, restartServiceIntent, PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmService = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
alarmService.set(
AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime() + 1000,
restartServicePendingIntent);
super.onTaskRemoved(rootIntent);
}
答案 9 :(得分:1)
由于https://developer.android.com/about/versions/oreo/background,您无法在Android O中将服务用于长时间运行的后台操作。 Jobservice将是Jobscheduler实施的更好选择。
答案 10 :(得分:0)
为什么不使用IntentService?
IntentService在主线程之外打开一个新线程并在那里工作,这样关闭应用程序就不会影响它
建议IntentService运行onHandleIntent(),当它完成服务关闭时,看看它是否符合您的需求。 http://developer.android.com/reference/android/app/IntentService.html
答案 11 :(得分:0)
<service android:name=".Service2"
android:process="@string/app_name"
android:exported="true"
android:isolatedProcess="true"
/>
在清单中声明此内容。为您的流程提供自定义名称,并将该流程隔离并导出。
答案 12 :(得分:0)
运行意向服务会更容易。在应用程序中创建线程但仍在应用程序中的服务。
答案 13 :(得分:-5)
在你的第一个可见活动中覆盖onDestroy方法,比如在你拥有主页之后,从splash到主页重定向你已经完成了启动。所以在主页上放毁。并停止该方法的服务。