sendWakefulWork 并不总是用 cwac-wakeful-1.1.0 调用
sendWakefulWork not always called with cwac-wakeful-1.1.0
困扰我很久的问题,我发现了cwac-wakeful,它可以解决我所有的问题。我想... :'(
简而言之,为了解决这个问题,我实现了一个最简单的应用程序,它每 60 秒安排一次警报并每次记录一次。
这是我的代码:
主要活动:
package com.par.hasard.mysimpleapplication;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
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.myExportButton);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
MyLogManager.copyLogToClipboard(view.getContext());
MyLogManager.emptyLogFile(view.getContext());
}
});
try {
MyLogManager.createLogFile(this);
MyLogManager.write(this, "Application launched\n");
MyAlarmPlanner.planAlarm_v2(this);
} catch (Exception e) {
e.printStackTrace();
}
}
}
我的警报计划器:
package com.par.hasard.mysimpleapplication;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.SystemClock;
import android.widget.Toast;
import com.commonsware.cwac.wakeful.WakefulIntentService;
import java.io.IOException;
public class MyAlarmPlanner {
public static void planAlarm_v2(Context context) throws IOException {
MyLogManager.write(context, "Beginning of planAlarm_v2\n");
WakefulIntentService.scheduleAlarms(new MyAppListener(), context, true);
MyLogManager.write(context, "End of planAlarm_v2\n");
}
}
我的应用程序监听器:
package com.par.hasard.mysimpleapplication;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.os.SystemClock;
import com.commonsware.cwac.wakeful.AlarmReceiver;
import com.commonsware.cwac.wakeful.WakefulIntentService;
import java.io.IOException;
public class MyAppListener implements WakefulIntentService.AlarmListener {
@Override
public void scheduleAlarms(AlarmManager alarmManager, PendingIntent pendingIntent, Context context) {
try {
MyLogManager.write(context, "Beginning of scheduleAlarms\n");
alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime()+60000, pendingIntent);
MyLogManager.write(context, "End of scheduleAlarms\n");
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void sendWakefulWork(Context context) {
try {
MyLogManager.write(context, "Beginning of sendWakefulWork\n");
WakefulIntentService.sendWakefulWork(context, MyAppService.class);
MyLogManager.write(context, "End of sendWakefulWork\n");
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public long getMaxAge(Context context) {
return (AlarmManager.INTERVAL_FIFTEEN_MINUTES * 2);
}
}
我的应用服务:
package com.par.hasard.mysimpleapplication;
import android.content.Intent;
import com.commonsware.cwac.wakeful.WakefulIntentService;
import java.io.IOException;
public class MyAppService extends WakefulIntentService {
public MyAppService(){
super("MyAppService");
}
@Override
protected void doWakefulWork(Intent intent) {
try {
MyLogManager.write(this, "Beginning of doWakefulWork\n");
MyAlarmPlanner.planAlarm_v2(this);
MyLogManager.write(this, "End of doWakefulWork\n");
} catch (IOException e) {
e.printStackTrace();
}
}
}
清单:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.par.hasard.mysimpleapplication">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
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>
<receiver android:name="com.par.hasard.mysimpleapplication.MySimpleWakefulReceiver">
<intent-filter android:priority="1">
<action android:name="com.par.hasard.mysimpleapplication.REGULAR_ALARM" />
</intent-filter>
</receiver>
<receiver android:name="com.commonsware.cwac.wakeful.AlarmReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
<meta-data
android:name="com.commonsware.cwac.wakeful"
android:resource="@xml/wakeful"/>
</receiver>
<service android:enabled="true" android:name="com.par.hasard.mysimpleapplication.MySimpleWakefulService" />
<service android:enabled="true" android:name="com.par.hasard.mysimpleapplication.MyAppService" />
</application>
</manifest>
wakeful.xml :
<WakefulIntentService
listener="com.par.hasard.mysimpleapplication.MyAppListener"
/>
所有这一切都很完美,但有时,它不会记录任何内容。我认为这是由于我的 phone (Sony Xperia) 的睡眠模式所致。但它似乎在其他 phone 上有相同的行为。
这是日志示例:
18/12 2h47m37s304 => Beginning of sendWakefulWork
18/12 2h47m37s311 => End of sendWakefulWork
18/12 2h47m37s316 => Beginning of doWakefulWork
18/12 2h47m37s317 => Beginning of planAlarm_v2
18/12 2h47m37s320 => Beginning of scheduleAlarms
18/12 2h47m37s322 => End of scheduleAlarms
18/12 2h47m37s323 => End of planAlarm_v2
18/12 2h47m37s324 => End of doWakefulWork
18/12 2h48m37s332 => Beginning of sendWakefulWork
18/12 2h48m37s338 => End of sendWakefulWork
18/12 2h48m37s347 => Beginning of doWakefulWork
18/12 2h48m37s348 => Beginning of planAlarm_v2
18/12 2h48m37s350 => Beginning of scheduleAlarms
18/12 2h48m37s351 => End of scheduleAlarms
18/12 2h48m37s352 => End of planAlarm_v2
18/12 2h48m37s353 => End of doWakefulWork
18/12 3h35m6s293 => Beginning of sendWakefulWork //nothing before ??
18/12 3h35m6s298 => End of sendWakefulWork
18/12 3h35m6s319 => Beginning of doWakefulWork
18/12 3h35m6s327 => Beginning of planAlarm_v2
18/12 3h35m6s331 => Beginning of scheduleAlarms
18/12 3h35m6s338 => End of scheduleAlarms
18/12 3h35m6s340 => End of planAlarm_v2
18/12 3h35m6s345 => End of doWakefulWork
18/12 3h36m7s307 => Beginning of sendWakefulWork
18/12 3h36m7s313 => End of sendWakefulWork
18/12 3h36m7s319 => Beginning of doWakefulWork
18/12 3h36m7s320 => Beginning of planAlarm_v2
18/12 3h36m7s322 => Beginning of scheduleAlarms
18/12 3h36m7s323 => End of scheduleAlarms
18/12 3h36m7s324 => End of planAlarm_v2
18/12 3h36m7s325 => End of doWakefulWork
有人可以帮助我吗?
就时间差距而言,很可能您正在 Android 6.0+ 设备上体验打瞌睡模式,或者某些制造商在旧设备上提供的等效模式(例如,SONY 的 STAMINA 模式)。除了将您的应用程序添加到适当的白名单(例如,对于 Doze,设置 > 应用程序 >(齿轮图标)> 特殊访问 > 电池优化),您几乎无能为力。
欢迎您在 API 级 23+ 设备上切换到 setExactAndAllowWhileIdle()
,但是:
你不会每分钟都得到控制(我觉得是限制在每9分钟)
当你获得控制权时你将无法访问互联网(这可能是你真正想要做的任何事情所必需的)
这对制造商特定的 6.0 之前的设备没有帮助(因为该方法不存在)
总的来说,将您的应用设计为处理打瞌睡模式,而不是假设它会在后台获得太多控制,是一种更可靠的方法。
困扰我很久的问题,我发现了cwac-wakeful,它可以解决我所有的问题。我想... :'( 简而言之,为了解决这个问题,我实现了一个最简单的应用程序,它每 60 秒安排一次警报并每次记录一次。 这是我的代码:
主要活动:
package com.par.hasard.mysimpleapplication;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
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.myExportButton);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
MyLogManager.copyLogToClipboard(view.getContext());
MyLogManager.emptyLogFile(view.getContext());
}
});
try {
MyLogManager.createLogFile(this);
MyLogManager.write(this, "Application launched\n");
MyAlarmPlanner.planAlarm_v2(this);
} catch (Exception e) {
e.printStackTrace();
}
}
}
我的警报计划器:
package com.par.hasard.mysimpleapplication;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.SystemClock;
import android.widget.Toast;
import com.commonsware.cwac.wakeful.WakefulIntentService;
import java.io.IOException;
public class MyAlarmPlanner {
public static void planAlarm_v2(Context context) throws IOException {
MyLogManager.write(context, "Beginning of planAlarm_v2\n");
WakefulIntentService.scheduleAlarms(new MyAppListener(), context, true);
MyLogManager.write(context, "End of planAlarm_v2\n");
}
}
我的应用程序监听器:
package com.par.hasard.mysimpleapplication;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.os.SystemClock;
import com.commonsware.cwac.wakeful.AlarmReceiver;
import com.commonsware.cwac.wakeful.WakefulIntentService;
import java.io.IOException;
public class MyAppListener implements WakefulIntentService.AlarmListener {
@Override
public void scheduleAlarms(AlarmManager alarmManager, PendingIntent pendingIntent, Context context) {
try {
MyLogManager.write(context, "Beginning of scheduleAlarms\n");
alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime()+60000, pendingIntent);
MyLogManager.write(context, "End of scheduleAlarms\n");
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void sendWakefulWork(Context context) {
try {
MyLogManager.write(context, "Beginning of sendWakefulWork\n");
WakefulIntentService.sendWakefulWork(context, MyAppService.class);
MyLogManager.write(context, "End of sendWakefulWork\n");
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public long getMaxAge(Context context) {
return (AlarmManager.INTERVAL_FIFTEEN_MINUTES * 2);
}
}
我的应用服务:
package com.par.hasard.mysimpleapplication;
import android.content.Intent;
import com.commonsware.cwac.wakeful.WakefulIntentService;
import java.io.IOException;
public class MyAppService extends WakefulIntentService {
public MyAppService(){
super("MyAppService");
}
@Override
protected void doWakefulWork(Intent intent) {
try {
MyLogManager.write(this, "Beginning of doWakefulWork\n");
MyAlarmPlanner.planAlarm_v2(this);
MyLogManager.write(this, "End of doWakefulWork\n");
} catch (IOException e) {
e.printStackTrace();
}
}
}
清单:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.par.hasard.mysimpleapplication">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
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>
<receiver android:name="com.par.hasard.mysimpleapplication.MySimpleWakefulReceiver">
<intent-filter android:priority="1">
<action android:name="com.par.hasard.mysimpleapplication.REGULAR_ALARM" />
</intent-filter>
</receiver>
<receiver android:name="com.commonsware.cwac.wakeful.AlarmReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
<meta-data
android:name="com.commonsware.cwac.wakeful"
android:resource="@xml/wakeful"/>
</receiver>
<service android:enabled="true" android:name="com.par.hasard.mysimpleapplication.MySimpleWakefulService" />
<service android:enabled="true" android:name="com.par.hasard.mysimpleapplication.MyAppService" />
</application>
</manifest>
wakeful.xml :
<WakefulIntentService
listener="com.par.hasard.mysimpleapplication.MyAppListener"
/>
所有这一切都很完美,但有时,它不会记录任何内容。我认为这是由于我的 phone (Sony Xperia) 的睡眠模式所致。但它似乎在其他 phone 上有相同的行为。 这是日志示例:
18/12 2h47m37s304 => Beginning of sendWakefulWork
18/12 2h47m37s311 => End of sendWakefulWork
18/12 2h47m37s316 => Beginning of doWakefulWork
18/12 2h47m37s317 => Beginning of planAlarm_v2
18/12 2h47m37s320 => Beginning of scheduleAlarms
18/12 2h47m37s322 => End of scheduleAlarms
18/12 2h47m37s323 => End of planAlarm_v2
18/12 2h47m37s324 => End of doWakefulWork
18/12 2h48m37s332 => Beginning of sendWakefulWork
18/12 2h48m37s338 => End of sendWakefulWork
18/12 2h48m37s347 => Beginning of doWakefulWork
18/12 2h48m37s348 => Beginning of planAlarm_v2
18/12 2h48m37s350 => Beginning of scheduleAlarms
18/12 2h48m37s351 => End of scheduleAlarms
18/12 2h48m37s352 => End of planAlarm_v2
18/12 2h48m37s353 => End of doWakefulWork
18/12 3h35m6s293 => Beginning of sendWakefulWork //nothing before ??
18/12 3h35m6s298 => End of sendWakefulWork
18/12 3h35m6s319 => Beginning of doWakefulWork
18/12 3h35m6s327 => Beginning of planAlarm_v2
18/12 3h35m6s331 => Beginning of scheduleAlarms
18/12 3h35m6s338 => End of scheduleAlarms
18/12 3h35m6s340 => End of planAlarm_v2
18/12 3h35m6s345 => End of doWakefulWork
18/12 3h36m7s307 => Beginning of sendWakefulWork
18/12 3h36m7s313 => End of sendWakefulWork
18/12 3h36m7s319 => Beginning of doWakefulWork
18/12 3h36m7s320 => Beginning of planAlarm_v2
18/12 3h36m7s322 => Beginning of scheduleAlarms
18/12 3h36m7s323 => End of scheduleAlarms
18/12 3h36m7s324 => End of planAlarm_v2
18/12 3h36m7s325 => End of doWakefulWork
有人可以帮助我吗?
就时间差距而言,很可能您正在 Android 6.0+ 设备上体验打瞌睡模式,或者某些制造商在旧设备上提供的等效模式(例如,SONY 的 STAMINA 模式)。除了将您的应用程序添加到适当的白名单(例如,对于 Doze,设置 > 应用程序 >(齿轮图标)> 特殊访问 > 电池优化),您几乎无能为力。
欢迎您在 API 级 23+ 设备上切换到 setExactAndAllowWhileIdle()
,但是:
你不会每分钟都得到控制(我觉得是限制在每9分钟)
当你获得控制权时你将无法访问互联网(这可能是你真正想要做的任何事情所必需的)
这对制造商特定的 6.0 之前的设备没有帮助(因为该方法不存在)
总的来说,将您的应用设计为处理打瞌睡模式,而不是假设它会在后台获得太多控制,是一种更可靠的方法。