9

我最近将我的所有服务替换为前台服务和 JobIntentService,因为在 oreo 及更高版本中存在一些后台执行限制(https://developer.android.com/about/versions/oreo/background)。根据文档,JobIntentService 的作用类似于 Android 7 及更低版本的 Intent Service,并且类似于 Android 8 及更高版本的 JobScheduler。我注意到 Google 提供的新 JobIntentService 存在问题。

安卓8及以上:

在 android 8 及更高版本中不断发生崩溃。这里提出了一张票,提到了同样的问题https://issuetracker.google.com/issues/63622293,我添加了一些极客建议的临时修复。

Android 7 及更低版本: 工作完成后,其行为类似于 Intent Service 的 JobIntentService 不会停止。

我已经在服务中实现了 JobIntentService,只要用户执行某些操作就会触发。

代码

public class SampleJobIntentService extends FixedJobIntentService {

public static void postData(Context context, String data) {
    Intent intent = new Intent(context, SampleJobIntentService.class);
            intent.setAction(INITIAL_ACTION);
            intent.putExtra(SAMPLE_ID, data);
            SampleJobIntentService.enqueueWork(context,intent);
}

public static void enqueueWork(Context context, Intent work) {
    SampleJobIntentService.enqueueWork(context, SampleJobIntentService.class, JOB_ID, work);

 @Override
    protected void onHandleWork(@NonNull Intent intent) {
        if (intent != null) {
            SampleRequest sampleRequest = requests.get(intent.getAction());
            if (sampleRequest != null) {
                try {
                   // perform some networking operations
                } catch (Exception ex) {
                    Log.d("Error for intent ");
                }
                Log.i("send action ");
            } else
                Log.e("action not found for ");
        }
    }
    }

为了避免 JobIntentService 崩溃,我从https://issuetracker.google.com/issues/63622293中引用了一些参考资料

public abstract class FixedJobIntentService extends JobIntentService {

    @Override
    GenericWorkItem dequeueWork() {
        try {
            return new FixedGenericWorkItem(super.dequeueWork());
        } catch (SecurityException ignored) {
            doStopCurrentWork();
        }
        return null;
    }

    private class FixedGenericWorkItem implements GenericWorkItem {
        final GenericWorkItem mGenericWorkItem;

        FixedGenericWorkItem(GenericWorkItem genericWorkItem) {
            mGenericWorkItem = genericWorkItem;
        }

        @Override
        public Intent getIntent() {
            if (mGenericWorkItem != null) {
                return mGenericWorkItem.getIntent();
            }
            return null;
        }

        @Override
        public void complete() {
            try {
                if (mGenericWorkItem != null) {
                    mGenericWorkItem.complete();
                }
            } catch (IllegalArgumentException ignored) {
                doStopCurrentWork();
            }
        }
    }
}
4

3 回答 3

19

嗯......,这是一个很大的理论......!它不能把它全部放在这里。我会尽力让你的一些概念清晰。


我已经在阅读谷歌文档方面失去了整整 2 年的时间......这是use-less......有no proper documentationno proper sample codes for its developers......!所以我在我的每一篇文章中都提到了这一点stack-overflow,因为这将有助于节省其他人的时间..!!


看起来你是一个优秀的程序员;只需要一些hints to your posted question

提示 1:

你 :- 我最近将所有服务替换为前台服务和 JobIntentService

前台服务:

如果您需要ALL THE TIME RUNNING PROCESS; WHICH WILL NEVER END... ONCE IT IS STARTED,它将用于START_STICKY从其返回的服务中OnStartCommand。再次不建议使用它,就好像你想不惜一切代价实现它一样......那么你将不得不使用一个通知,setOngoing(true)最终用户将无法刷掉你的通知,它将永远保留在那里...... .

前台服务的使用:

对接收者也有限制;从上面Oreo开始,您不能通过在清单中声明它并仅创建一个接收器来使用所有接收器和意图操作...我建议仅使用BootComplete权限并使用一个receiver接收boot_completed意图并调用 a serviceif 低于 O 并调用 a O 上方的前台服务。现在,您可以从该前台服务中为所有人实现运行时接收器,并在 Ondestroy 方法中取消注册它。我从来没有找到实现运行时接收器的官方示例代码,最后我通过几个月的努力成功实现了它......是的,由于谷歌,这不是一个聪明的工作

何时使用前台服务:

仅当您想实现广播接收器时......如果您不想实现任何广播接收器;远离.......

提示 2:

你 :- 我最近将我所有的服务替换为前台服务和 JobIntentService

** 服务质量:**

只是做一个非常小的工作......然后退出......它必须由S退出topSelf()......再次,Services can cause data-loss如果多次调用......因为同一个服务线程可以运行多次......如果你再次想要一个服务来做很多工作......使用START_STICKY......但同样不推荐,我已经建议,何时在提示 1 中使用它。

** Intentservice 的质量为:**

做一个运行时间比较长的任务,property of execution serially only如果你一遍又一遍的调用同一个intentService,那么所有的调用都会被保存在一个a中,完成后queue会被执行。如上所述,在服务中并非如此。它自行结束......无需开发人员结束......!one by oneone by one

** 独一无二的品质:**

一旦他们是crashedandroid 就可以阻止他们在未来调用而不通知您,因为它会使应用程序崩溃。try-catch-exception需要用to来处理它们avoid crash。再一次……如果you are implementing threads within services那么try-catch-exception will not save your application from being crashing……

** 那到底是什么以及如何实现它:**

使用FireBaseJobScedular:-

  1. 便于使用
  2. 使用简单的 JobService
  3. 可以运行更长或更短时间的任务...EVEN ALL THE TIME RUNNING TASK
  4. EVEN SUPPORTED BY NON STANDARD COMPANIES像vivo、mi、oppo、one+3, ...它需要stock-android对其进行更改并给出诸如FunTouchOs、ColorOs、OxygenOs之类的名称
  5. 只需要将电池设置更改为“不优化此应用”
  6. 是的 google 官方支持它并建议使用它
  7. 它创建实例GooglePlyService并在其中运行,显然非标准公司也不会限制谷歌应用程序执行其任务。
  8. 适用于Oreo..,即使我已经对其进行了测试,Android P并且在 Android 5.0 版以下作为AlarmManager任务工作。
  9. 我仍然建议使用minsdk above 16target sdk 26好像如果您想将您的应用程序上传到google play它现在是强制性的,并且您会听到这个消息。和compile sdk 26
  10. 只需在清单中绑定您JobService并使用单行权限receive_boot_complete
  11. 只需安排它......它将在每个制造商的市场上每台设备上启动......甚至在cold boothot boot
  12. 它最小化了很多很多的代码和you can focus on actual tasks.
  13. 任务完成后,您可以return false指示任务已完成,它将结束 JobService。

为什么我建议,因为我是CTO一家很好的UNKNOwn公司,并且经历foreground service过许多类型的安卓手机制造商造成的问题……这不是Apple and ios我们必须经历的。自过去 18 年以来一直是开发人员,我今天也主要编写代码……在所有开发项目中,其开发策略仅由我考虑。

纠正我...太...因为您没有提到what your tasks并且 project与...有关...以及您到底想在 foreground service and intent-service...中完成什么让我知道...,我很乐意为您提供帮助。这是一个一般的理论答案,而不是你想要的......但是为了给你实际的答案,我需要准确的项目范围......

于 2018-08-08T12:31:16.390 回答
1

一旦工作完成,JobIntentService 就像 Intent Service 一样不会停止

问题出在您的扩展类 FixedJobIntentService dequeueWork 方法中。

尝试将其更改为如下所示

GenericWorkItem superValue = super.dequeueWork();
if (superValue != null) {
    return new FixedGenericWorkItem(superValue);
}
return null;

查看 JobIntentSerivce 代码,Work Items 处理器逻辑如下所示,即直到队列中没有工作项为止,所有项目都被处理(即为每个项目调用 onHandleWork)

    while ((work = dequeueWork()) != null) {
        if (DEBUG) Log.d(TAG, "Processing next work: " + work);
        onHandleWork(work.getIntent());
        if (DEBUG) Log.d(TAG, "Completing work: " + work);
        work.complete();
    }

您的实现中的问题是在处理第一个工作项后,super.dequeueWork() 返回 null,您没有处理它,只是发送一个新的 FixedGenericWorkItem 对象传递 null 值。您可能会观察到在后续调用中将空值传递给您的 onHandleWork。

希望这有助于解决您的问题。

于 2018-12-04T17:52:40.050 回答
0

我认为你只需要这么多的代码。创建一个新的 MyJobIntentService 类并编写这么多代码并调用 postData() 来启动您的服务。

public class MyJobIntentService extends JobIntentService {

public static void postData(Context context, String data) {
    final Intent intent = new Intent(context, MyJobIntentService.class);
    intent.setAction(INITIAL_ACTION);
    intent.putExtra(SAMPLE_ID, data);
    enqueueWork(context, MyJobIntentService.class, 1000, intent);
}

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

@Override
public void onDestroy() {
    Ln.d("Cancelled service");
    super.onDestroy();
}

@Override
    protected void onHandleWork(@NonNull Intent intent) {
        if (intent != null) {
            final SampleRequest sampleRequest = requests.get(intent.getAction());
            if (sampleRequest != null) {
                try {
                   // perform some networking operations
                } catch (Exception ex) {
                    Log.d("Error for intent ");
                }
                Log.i("send action ");
            } else {                
               Log.e("action not found for ");
            }
        }
    }
}

并确保在清单文件中添加您的服务

<service
            android:name="service.MyJobIntentService"
            android:exported="false"
            android:permission="android.permission.BIND_JOB_SERVICE" />
于 2018-08-06T14:42:03.830 回答