【问题标题】:Creating Background Service in Android在 Android 中创建后台服务
【发布时间】:2012-02-07 13:36:40
【问题描述】:

在我的项目中,我需要在 android 中创建一个服务。我可以像这样注册服务:

<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name" >

   <service   android:enabled="true"
    android:name=".ServiceTemplate"/>
      <activity
        android:name=".SampleServiceActivity"
        android:label="@string/app_name" >
        <intent-filter>
         <action android:name="android.intent.action.MAIN" />
         <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
     </activity>
</application>

我在如下活动中调用此服务:-

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    Intent service = new Intent(getApplicationContext(), ServiceTemplate.class);
    this.startService(service);
}

但是如果我杀死当前的活动,服务也会被破坏。我需要此服务始终在后台运行。 我需要做什么? 如何注册服务? 如何启动服务?

【问题讨论】:

  • 你能接受这个问题的答案吗?

标签: android service


【解决方案1】:

这是一种使服务永久运行的半不同方式。如果你愿意,有办法在代码中杀死它

后台服务:

package com.ex.ample;

import android.app.Service;
import android.content.*;
import android.os.*;
import android.widget.Toast;

public class BackgroundService extends Service {

    public Context context = this;
    public Handler handler = null;
    public static Runnable runnable = null;

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        Toast.makeText(this, "Service created!", Toast.LENGTH_LONG).show();

        handler = new Handler();
        runnable = new Runnable() {
            public void run() {
                Toast.makeText(context, "Service is still running", Toast.LENGTH_LONG).show();
                handler.postDelayed(runnable, 10000);
            }
        };

        handler.postDelayed(runnable, 15000);
    }

    @Override
    public void onDestroy() {
        /* IF YOU WANT THIS SERVICE KILLED WITH THE APP THEN UNCOMMENT THE FOLLOWING LINE */
        //handler.removeCallbacks(runnable);
        Toast.makeText(this, "Service stopped", Toast.LENGTH_LONG).show();
    }

    @Override
    public void onStart(Intent intent, int startid) {
        Toast.makeText(this, "Service started by user.", Toast.LENGTH_LONG).show();
    }
}

以下是您从主要活动或您希望的任何地方开始的方式:

startService(new Intent(this, BackgroundService.class));

onDestroy() 将在应用程序关闭或终止时被调用,但可运行对象只是重新启动它。您还需要删除处理程序回调。

我希望这对某人有所帮助。

有些人这样做的原因是因为企业应用程序在某些情况下用户/员工不能停止某些事情:)

http://i.imgur.com/1vCnYJW.png

【讨论】:

  • 是的,&lt;service android:name="com.ex.ample.BackgroundService" android:exported="false" /&gt; 但这个答案已经过时了。如需更新的解决方案,请查看github.com/evernote/android-job
  • 谢谢,这个答案对我来说已经足够了,在清单中声明服务后它可以工作!并停止服务我使用 onDestroy(){ super.onDestroy(); stopService(new Intent(BackgroundService.class)); } 在 Activity 上,它会在应用程序关闭时停止任何后台服务
  • @Pierre 如何从活动中停止/终止已启动的服务?我的意思是当 handler.removeCallbacks(runnable);在 onDestory() 中进行了注释 - 这意味着业务希望在启动服务时仍然存在,例如当应用程序被最小化或关闭时。那么,当 handler.removeCallbacks(runnable); 时,我怎么能停止/杀死这种服务?评论了吗?
  • @MishoZhghenti 在任何活动中尝试BackgroundService.runnable = null;。可运行是公共静态的。或者你必须在BackgroundService 中覆盖onHandleIntent,然后创建一个Intent i = new Intent(this, BackgroundService.class); 然后i.setAction("com.app.bgservice.kill") 并调用startService(intent);。在 onHandleIntent 检查if(intent.getAction() == "com.app.bgservice.kill") { handler.removeCallbacks(runnable);}
【解决方案2】:

但如果我终止当前活动,该服务也正在终止。我需要此服务始终在后台运行。我需要做什么?

如果“终止当前活动”是指您正在使用任务终止程序,或者从“设置”应用程序中强制停止,您的服务将被停止。你对此无能为力。用户已表明他们不希望您的应用程序再运行;请尊重用户的意愿。

如果“终止当前活动”是指按下 BACK 或 HOME 或其他键,那么服务应该至少运行一段时间,除非你调用 stopService()。它不会永远运行——Android 最终将摆脱该服务,因为太多开发人员编写的服务试图“始终在后台运行”。和。当然,用户可以随时终止服务。

只有当服务主动向用户提供价值时,它才能“运行”。这通常意味着服务不应“始终在后台运行”。相反,请使用AlarmManagerIntentService 定期执行工作。

【讨论】:

  • 我正在通过 adb shell kill 命令终止当前活动。只是我喜欢创建警报,短信通知之类的服务......
  • @Sathish:我不知道“adb shell kill 命令”有文档记录,所以我不知道它的特点是什么。
  • 但是如果应用程序被关闭,AlarmManager 是否能够触发 AlarmReceiver 内部触发 IntentService 执行实际任务?
  • @Naga:我不确定你所说的“关闭”是什么意思。如果您的意思是“用户导航到另一个应用程序,并且您的进程在一段时间后终止”,那是完全正常的,不会损害您的 AlarmManager 设置。如果您的意思是“用户将应用程序从概览屏幕上滑出”,那也不应该损害您的 AlarmManager 设置。我在 Stack Overflow 上看到了一堆抱怨,说从概览屏幕滑动任务确实会导致问题,但我一直无法重现这种行为。
  • @CommonsWare 我的混合应用程序在一段时间后被 Android 操作系统关闭,在我的应用程序中还有一些本机 Java 代码创建警报并通过接收器类处理它,只要这个场景完美运行应用程序在前台或后台,但是一旦应用程序被操作系统杀死,即使在 AndroidManifeast.xml 中有 process:remote 属性设置此接收器,接收器也不会被触发,请建议
【解决方案3】:

您可以创建后台服务并通过 AlarmManager 调用它

1- 你必须创建一个 BroadcastReceiver 类来调用 报警管理器

public class AlarmReceiver extends BroadcastReceiver

{
    /**

     * Triggered by the Alarm periodically (starts the service to run task)

     * @param context

     * @param intent

     */

    @Override

    public void onReceive(Context context, Intent intent)

    {

        Intent i = new Intent(context, AlmasService.class);

        i.putExtra("foo", "AlarmReceiver");

        context.startService(i);

    }

}

2-你必须创建一个 IntentService 类来调用 报警接收器

public class AlmasService extends IntentService

{

    public Context context=null;

    // Must create a default constructor
    public AlmasService() {

        // Used to name the worker thread, important only for debugging.
        super("test-service");

    }

    @Override

    public void onCreate() {

        super.onCreate(); // if you override onCreate(), make sure to call super().

    }


    @Override
    protected void onHandleIntent(Intent intent) {

        context=this;
        try

        {

            Thread.sleep(5000);

        }

        catch (InterruptedException e)

        {

            e.printStackTrace();

        }



        String val = intent.getStringExtra("foo");

        // Do the task here
        Log.i("MyTestService", val);

    }

}

3- 您必须将 AlarmReceiver 添加为接收器,并将 AlmasService 添加为清单上的服务

    <service
        android:name=".ServicesManagers.AlmasService"
        android:exported="false"/>

    <receiver
        android:name=".ServicesManagers.AlmasAlarmReceiver"
        android:process=":remote" >
    </receiver>

4-现在您可以在 MainActivity 上启动服务并调用 AlarmManager

public class MainActivity extends AppCompatActivity
{
    public static final int REQUEST_CODE = (int) new Date().getTime();

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        scheduleAlarm();
    }

    public void scheduleAlarm()
    {
        // Construct an intent that will execute the AlarmReceiver
        Intent intent = new Intent(getApplicationContext(), AlmasAlarmReceiver.class);
        // Create a PendingIntent to be triggered when the alarm goes off
        final PendingIntent pIntent = PendingIntent.getBroadcast(
                this, REQUEST_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        // Setup periodic alarm every every half hour from this point onwards
        long firstMillis = System.currentTimeMillis(); // alarm is set right away
        AlarmManager alarm = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
        // First parameter is the type: ELAPSED_REALTIME, ELAPSED_REALTIME_WAKEUP, RTC_WAKEUP
        // Interval can be INTERVAL_FIFTEEN_MINUTES, INTERVAL_HALF_HOUR, INTERVAL_HOUR, INTERVAL_DAY
        alarm.setRepeating(AlarmManager.RTC_WAKEUP, firstMillis, (long) (1000 * 60), pIntent);



    }
}

【讨论】:

  • 该服务由AlarmReceiver触发,AlarmManager调用该服务,如果应用程序终止,AlarmManager无法调用AlarmReceiver,此方案依赖于Application
【解决方案4】:

尝试在单独的线程中启动服务,这样当你销毁你的活动时,服务不会受到影响。它将不间断地运行。此外,在服务中从onStartCommand(intent, flags, startId) 返回Service.START_STICKY 以确保如果服务被系统(Android OS)杀死,则重新创建服务。

【讨论】:

    【解决方案5】:

    覆盖此方法:

    public int onStartCommand(Intent intent, int flags, int startId) {
        return Service.START_STICKY;
    }
    

    【讨论】:

    • 那么它会永远在后台运行吗?
    【解决方案6】:

    完成@abhinav 所说的内容:如果您使用 onBind(),则不需要使用 onStartCommand(),反之亦然:

    事实上,如果一个组件调用了bindService()来创建服务并且没有调用onStartCommand(),那么服务只会在组件绑定到它的时候运行。在服务与其所有客户端解除绑定后,系统将其销毁。为了显示: onStartCommand() 方法在您的 Service 开始工作时被调用。 onCreate() 已经完成,它可以开始做需要做的事情了。如果您使用 onBind() 方法,您会将 Service 与例如 Activity 的生命周期联系起来。如果 Activity 完成,则允许释放 Service 并可以自行完成。只要有绑定的东西,服务就会一直存在。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-09-23
      相关资源
      最近更新 更多