【发布时间】:2018-08-04 16:29:09
【问题描述】:
我正在开发在通话结束时发送短信的应用程序。
Manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="xxx.xxxx.xxxx.xxxx">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.WRITE_SMS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<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"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".MonitorService"
android:enabled="true"
android:exported="true" />
<service
android:name=".SendText"
android:exported="false" />
<receiver
android:name=".BootReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
</manifest>
我已经从MainActivity 获取了所有运行时权限(如果它高于 Marshmallow)。
我的接收者:
public class BootReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
Log.d("BootTest : ", "\nOnBootReceiver - Received a broadcast!");
Toast.makeText(context, "InstaPromo Is Ready !!", Toast.LENGTH_LONG).show();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
context.startForegroundService(new Intent(context, MonitorService.class));
}
else
{
context.startService(new Intent(context, MonitorService.class));
}
}
}
实现接收器运行时为:
public class MonitorService extends Service
{
// Notification variables
private BroadcastReceiver mCallBroadcastReceiver = new BroadcastReceiver()
{
@Override
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
if (action.equalsIgnoreCase("android.intent.action.PHONE_STATE"))
{
if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_RINGING))
{
Log.d("RECEIVER X: ", "INCOMING CALL...");
}
if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_IDLE))
{
Log.d("RECEIVER X: ", "CALL ENDS HERE...");
Intent Dispatcher = new Intent(context, SendText.class);
startService(Dispatcher);
}
if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_OFFHOOK))
{
Log.d("RECEIVER X: ", "ACTIVE CALL GOING ON...");
}
}
}
};
public MonitorService() { }
@Override
public void onCreate()
{
super.onCreate();
// created notification here
// also registered broadcast receiver here
mBuilder.setChannelId(NOTIFICATION_CHANNEL_ID);
startForeground(17, mBuilder.build());
}
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Log.d("WatchMan : ", "\nmCallBroadcastReceiver Listening....");
//return super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
@Override
public void onDestroy()
{
this.unregisterReceiver(mCallBroadcastReceiver);
Log.d("WatchMan : ", "\nDestroyed....");
Log.d("WatchMan : ", "\nWill be created again....");
}
@Override
public IBinder onBind(Intent intent)
{
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
}
-
Broadcastreceiver在服务类中工作正常;即使应用程序从最近的应用程序列表中删除,但如果从最近的应用程序列表中删除,那么在下一个boot_complete它永远不会再次调用接收器。如果 App 没有从最近删除...那么在每次 boot_complete / quick boot 它都会被触发并且广播接收器可以正常工作。我试过android:exclude_from_recents...,但这不是实现它的方法。
谁能帮我解决这个问题。谢谢
更新 2
我在 github 上研究了 Firebase JobDispatcher 文档并使用如下:
- 在 gradle 项目文件中实现依赖
- 之后同步成功
- 创建了一个 JobService
- 创建了一个作业并安排了它。
- 它也在 boot_completed 上被触发..
public class MyJobService extends JobService
{
@Override
public boolean onStartJob(JobParameters job)
{
// Do some work here
Log.d("MY_JOB :", "STARTED HERE... \n");
return false;
// Answers the question: "Is there still work going on?"
}
@Override
public boolean onStopJob(JobParameters job)
{
Log.d("MY_JOB :", "STOPPED HERE... \n");
return true;
// Answers the question: "Should this job be retried?"
}
}
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(MainActivity.this));
Bundle myExtrasBundle = new Bundle();
myExtrasBundle.putString("some_key", "some_value");
Job myJob = dispatcher.newJobBuilder()
// the JobService that will be called
.setService(MyJobService.class)
// uniquely identifies the job
.setTag("my-unique-tag")
// one-off job
.setRecurring(false)
// don't persist past a device reboot
.setLifetime(Lifetime.FOREVER)
// start between 0 and 60 seconds from now
.setTrigger(Trigger.executionWindow(10, 10+2))
// don't overwrite an existing job with the same tag
.setReplaceCurrent(false)
// retry with exponential backoff
.setRetryStrategy(RetryStrategy.DEFAULT_EXPONENTIAL)
// constraints that need to be satisfied for the job to run
.setConstraints(
// only run when device is idle
Constraint.DEVICE_IDLE
)
.setExtras(myExtrasBundle)
.build();
dispatcher.mustSchedule(myJob);
我应该如何安排它只在重新启动/启动完成时运行一次
- 我只想在停止后重复.. : setRecurring(false), IS IT OKAY to false or true it should be true?
- setLifetime(Lifetime.UNTIL_NEXT_BOOT) 将其设置为 FOREVER THIS OKAY
- setTrigger(Trigger.executionWindow(0, 60)) 没有得到这个
- setReplaceCurrent(false) 是的,没关系。
- 使用指数退避重试这是什么?
如何设置这些标签在BOOT/REBOOT上启动且只启动一次,启动失败试试,不要再启动..?
【问题讨论】:
-
你的目标sdk版本是什么
-
@RohitSharma, min sdk = 21, 编译 sdk 26, 目标 sdk 26;
-
您能否尝试将 targetSdkVersion 保持在 25 或更低,并检查反馈,Hack of CommonsWare 是否有类似情况。
-
它也在重新启动时运行..(即使从最近删除)在奥利奥下方和之上,只有在奥利奥中如果从最近删除然后它永远不会在重新启动时被调用,直到应用程序再次打开.. . GOOGLE MADE COMPULSORY TARGET SDK 26 ... 现在需要两周时间才能上传到 Play 商店
-
你试过我的answer提到的
JobIntentService
标签: java android broadcastreceiver