我尝试在Android应用程序中执行一些后台计算任务。
我的主要课程:
public class CalculationService extends IntentService {
public CalculationService() {
super("Calculation Service");
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
int nb1 = intent.getIntExtra(NUMBER_1,0);
int nb2 = intent.getIntExtra(NUMBER_2,0);
doAddition(nb1,nb2);
CalculationReceiver.completeWakefulIntent(intent);
}
public void doAddition(int number1, int number2){
int result = number1+number2;
System.out.println("Result : " + result);
}
}
我的服务:
public class CalculationReceiver extends WakefulBroadcastReceiver {
public static final String NUMBER_1 = "NUMBER_1";
public static final String NUMBER_2 = "NUMBER_2";
@Override
public void onReceive(Context context, Intent intent) {
Intent service = new Intent(context, CalculationService.class);
int receiverNumber1 = intent.getIntExtra(NUMBER_1,0);
int receiverNumber2 = intent.getIntExtra(NUMBER_2,0);
service.putExtra(NUMBER_1,receiverNumber1);
service.putExtra(NUMBER_2,receiverNumber2);
startWakefulService(context, service);
}
public void doAddition (Context context, int number1, int number2){
Intent intent = new Intent(context, CalculationReceiver.class);
intent.putExtra(NUMBER_1,number1);
intent.putExtra(NUMBER_2,number2);
context.sendBroadcast(intent);
}
}
我的接收者:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.testservices">
<uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".ReductionService"
android:enabled="true" />
<receiver android:name=".ReductionReceiver"/>
<service android:name=".CalculationService"
android:enabled="true" />
<receiver android:name=".CalculationReceiver"/>
</application>
</manifest>
我的宣言:
context.sendBroadcast (intent);
应用程序的计算比这些添加更复杂,可能需要几分钟(平均15分钟)才能完成。
根据Google文档(https://developer.android.com/training/scheduling/wakelock.html),我决定实施此架构,以确保计算结束。
这个想法是用户开始计算,然后等待应用程序给出结果。与此同时,他可以启动其他应用程序或锁定他的手机,计算一定不能停止。
这种方法似乎有效。
让我困扰的是接收者对服务的要求:
{{1}}
是否有更多&#34;清洁&#34;启动服务的方式?
让我印象深刻的是它看起来并不是很干净#34;特别是相同参数(number1和number2)的几次通过
由于
答案 0 :(得分:1)
根据Google文档(https://developer.android.com/training/scheduling/wakelock.html),我决定实施此架构,以确保计算结束。
这不是文档使用WakefulBroadcastReceiver
显示的方式。另外,WakefulBroadcastReceiver
在支持库的版本26.0.0
中已弃用。
这个想法是用户开始计算,然后等待应用程序给出结果。
我对此的解释是,用户通过您的活动的UI请求开始计算。这意味着此时屏幕已打开,您在前台有活动。
是否有更“干净”的方式来启动服务?
致电startService()
。
步骤1:删除您对已弃用的WakefulBroadcastReceiver
步骤2:让您的活动致电startService()
以启动服务
第3步:让您的服务通过WakeLock
系统服务获取部分PowerManager
,服务的onCreate()
方法
第4步:在服务的WakeLock
方法中发布onDestroy()
服务
步骤#5:将服务修改为前台服务,使用合适的startForeground()
在onCreate()
中调用Notification
,以允许用户控制服务的行为
请注意:
如果您跳过步骤#5,您的服务将在Android 8.0 +上大约1分钟后停止运行。
如果设备进入打盹模式,这仍然无法在Android 6.0+上运行。这不应该发生大约1个小时,但你需要确保你的计算在那时完成。
考虑将计算工作卸载到服务器,而不是长时间烧毁用户的CPU(通过计算工作加上唤醒锁)
答案 1 :(得分:1)
按照这种方式,我按照@CommonsWare
的建议解决了这个问题主要活动:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.button);
final Context mContext = this;
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent service = new Intent(mContext, CalculationService.class);
service.putExtra(NUMBER_1,2);
service.putExtra(NUMBER_2,2);
startService(service);
}
});
}
}
计算服务:
public class CalculationService extends IntentService {
public static final String NUMBER_1 = "NUMBER_1";
public static final String NUMBER_2 = "NUMBER_2";
private static final int FOREGROUND_ID = 42;
PowerManager.WakeLock wakeLock;
public CalculationService() {
super("Calculation Service");
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
int nb1 = intent.getIntExtra(NUMBER_1,0);
int nb2 = intent.getIntExtra(NUMBER_2,0);
doAddition(nb1,nb2);
}
public void doAddition(int number1, int number2){
int result = number1+number2;
System.out.println("Result : " + result);
}
@Override
public void onCreate() {
super.onCreate();
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"CalculationServiceWakelockTag");
wakeLock.acquire();
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("Calculation App")
.setContentText("Calculation in progress")
.setContentIntent(pendingIntent).build();
startForeground(FOREGROUND_ID, notification);
}
@Override
public void onDestroy() {
super.onDestroy();
wakeLock.release();
}
}
这很有效:)
但我可以打电话吗
startForegroundService(service)
而不是
startService(service);
是不是?为什么?