我的Broadcast接收器无法在oreo上工作,但是在oreo之下却可以正常工作,我为此进行了很多搜索,但找不到合适的解决方案。是否有人面临相同的问题,这是我的有关已实现广播的服务的代码。请给我建议我如何在奥利奥工作。
这是班上
public int onStartCommand(Intent intent, int flags, int startId) {
mContext = this;
mAppPreferences = new AppPreferences(mContext);
if (intent.getExtras() != null) {
data = (String) intent.getExtras().get("showPopUp");
phoneNumber= (String) intent.getExtras().get("dialNumber");
}
final IntentFilter intentFilter = new IntentFilter();
if (data.equalsIgnoreCase("true")) {
showPopup(getApplicationContext());
Utils.ApiHit(phoneNumber,getApplicationContext());
}
intentFilter.setPriority(2147483647);
intentFilter.addAction("android.intent.action.PHONE_STATE");
callExplicitReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(TelephonyManager.ACTION_PHONE_STATE_CHANGED)) {
if (intent.getAction().equals("android.intent.action.NEW_OUTGOING_CALL")) {
savedNumber = intent.getExtras().getString("android.intent.extra.PHONE_NUMBER");
} else {
String stateStr = intent.getExtras().getString(TelephonyManager.EXTRA_STATE);
phoneNumber = intent.getExtras().getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
int state = 0;
if (stateStr.equals(TelephonyManager.EXTRA_STATE_IDLE)) {
state = TelephonyManager.CALL_STATE_IDLE;
} else if (stateStr.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) {
state = TelephonyManager.CALL_STATE_OFFHOOK;
} else if (stateStr.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
state = TelephonyManager.CALL_STATE_RINGING;
}
onCallStateChanged(context, state, phoneNumber);
}
}
}
};
mContext.registerReceiver(callExplicitReceiver, intentFilter);
return START_NOT_STICKY;
}
public void onIncomingCallReceived(Context ctx, String number, Date start) {
}
public void onIncomingCallAnswered(Context ctx, String number, Date start) {
if (popupView.getVisibility() == View.GONE) {
popupView.setVisibility(View.VISIBLE);
}
}
public void onIncomingCallEnded(Context ctx, String number, Date start, Date end) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
DeleteCallLogByNumber(number);
}
}, 2000);
if (popupView.getVisibility() == View.VISIBLE) {
popupView.setVisibility(View.GONE);
}
}
public void onOutgoingCallStarted(Context ctx, String number, Date start) {
// mAppPreferences.setPrefrenceString("busy", "yes");
// if (data.equalsIgnoreCase("true")) {
mediaPlayer = MediaPlayer.create(ctx, R.raw.speech_audio);
// } else {
// mediaPlayer = MediaPlayer.create(ctx, R.raw.speech_audio);
// }
mediaPlayer.start();
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
mediaPlayer.stop();
mediaPlayer.release();
}
}
}, 12000);
if (popupView.getVisibility() == View.GONE) {
popupView.setVisibility(View.VISIBLE);
}
}
public void onOutgoingCallEnded(Context ctx, String number, Date start, Date end) {
mAppPreferences.setPrefrenceString("busy", "no");
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
}
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
DeleteCallLogByNumber(phoneNumber);
}
}, 2000);
if (popupView.getVisibility() == View.VISIBLE) {
popupView.setVisibility(View.GONE);
}
}
public void onMissedCall(Context ctx, String number, Date start) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
DeleteCallLogByNumber(phoneNumber);
}
}, 2000);
if (popupView.getVisibility() == View.VISIBLE) {
popupView.setVisibility(View.GONE);
}
}
public void onCallStateChanged(Context context, int state, String number) {
if (lastState == state) {
return;
}
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
isIncoming = true;
callStartTime = new Date();
savedNumber = number;
onIncomingCallReceived(context, number, callStartTime);
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
if (lastState != TelephonyManager.CALL_STATE_RINGING) {
isIncoming = false;
callStartTime = new Date();
onOutgoingCallStarted(context, savedNumber, callStartTime);
} else {
isIncoming = true;
callStartTime = new Date();
onIncomingCallAnswered(context, savedNumber, callStartTime);
}
break;
case TelephonyManager.CALL_STATE_IDLE:
if (popupView.getVisibility() == View.VISIBLE) {
popupView.setVisibility(View.GONE);
}
if (lastState == TelephonyManager.CALL_STATE_RINGING) {
onMissedCall(context, savedNumber, callStartTime);
} else if (isIncoming) {
onIncomingCallEnded(context, savedNumber, callStartTime, new Date());
} else {
onOutgoingCallEnded(context, savedNumber, callStartTime, new Date());
}
break;
}
lastState = state;
}
@Override
public void onDestroy() {
mContext.unregisterReceiver(callExplicitReceiver);
}
注意到接收器进来了,有人可以帮我吗?
根据讨论的新添加内容
清单数据:-
已使用权限:-
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
收款人:-
<receiver android:name="com.example.dialer.AppUtils.StartUpBootReceiver" android:enabled="true" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
我的BroadCast接收器班:-
public class StartUpBootReceiver extends BroadcastReceiver {
private Context mContext;
@Override
public void onReceive(Context context, Intent intent) {
mContext= context;
String action = "START";
if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
context.startForegroundService(new Intent(context, PhoneStateService.class));
}
else
{
context.startService(new Intent(context, PhoneStateService.class));
}
}
}
private boolean isServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
}
其他服务将无法获得呼叫,但问题是我仍然无法在接收器中获得呼叫。并且主要要点是服务应该仅在用户点击按钮后才被调用,而不是自动,因为我必须传递一些服务中的值。
谢谢
答案 0 :(得分:11)
广播限制
如果某个应用程序注册接收广播,则每次发送广播时,该应用程序的接收器都会消耗资源。如果太多的应用程序注册为无法根据系统事件接收广播,则可能会导致问题。触发广播的系统事件可能导致所有这些应用快速连续消耗资源,从而损害用户体验。为了缓解此问题,Android 7.0(API级别25)对广播设置了限制,如背景优化中所述。 Android 8.0(API级别26)使这些限制更加严格。
面向Android 8.0或更高版本的应用无法再在其清单中为隐式广播注册广播接收器。隐式广播是不专门针对该应用的广播。例如,ACTION_PACKAGE_REPLACED是隐式广播,因为它已发送给所有注册的侦听器,让他们知道设备上的某些程序包已被替换。但是,ACTION_MY_PACKAGE_REPLACED并不是隐式广播,因为它仅发送到替换了包的应用程序,无论有多少其他应用程序已为该广播注册了侦听器。
应用程序可以继续在清单中注册显式广播。
应用程序可以在运行时使用Context.registerReceiver()为任何广播(无论是隐式的还是显式的)注册接收器。
需要签名许可的广播不受此限制,因为这些广播仅发送到使用相同证书签名的应用,而不发送到设备上的所有应用。
Check Official Documentation here
希望这会有所帮助。
答案 1 :(得分:4)
问题与您尝试运行的服务有关,服务或持久后台服务不允许长时间运行针对Oreo及更高版本的应用。
检查this guide和this as well,以迁移您的应用程序以支持Oreo。
答案 2 :(得分:3)
我也遇到过这种问题,但是我找到了一个更好的解决方案:
MyReceiver类
@BroadcastReceiverActions({
"android.intent.action.SCREEN_ON",
"android.intent.action.SCREEN_OFF",
"android.intent.action.DREAMING_STARTED",
"android.intent.action.DREAMING_STOPPED",
"android.intent.action.ACTION_POWER_DISCONNECTED",
"android.intent.action.ACTION_POWER_CONNECTED",
"android.net.conn.CONNECTIVITY_CHANGE"
})
public class MyReceiver extends BroadcastReceiver {
public MyReceiver() {
super();
}
@Override
public void onReceive(Context context, Intent intent) {
Session.getGlobalReceiverCallBack(context, intent);
//Log.e("dfd", "" + intent.getAction());
}
}
Class AppController
public class AppController extends Application {
private BroadcastReceiver receiver;
MyReceiver mR;
@Override
public void onCreate() {
super.onCreate();
mR = new MyReceiver();
receiver = DynamicReceiver.with(mR)
.register(this);
}
}
Class MainActivity
public class MainActivity extends AppCompatActivity implements GlobalReceiverCallBack {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Session.setmGlobalReceiverCallback(this);
}
@Override
public void onCallBackReceived(Context context, Intent intent) {
Toast.makeText(context, "" + intent.getAction(), Toast.LENGTH_LONG).show();
}
}
有关完整参考,您还可以参见https://github.com/devggaurav/BroadcastReceiver-For-Naught-and-Oreo-devices
答案 3 :(得分:1)
Android 8.0对JobScheduler进行了多项改进,使其可以更轻松地用计划的作业替换服务和广播接收器:
https://developer.android.com/about/versions/oreo/background
答案 4 :(得分:0)
在create方法(而不是清单)中的活动中注册您的广播接收器,并在destroy方法中将其注销。希望这可以在Android 9上使用。
答案 5 :(得分:0)
在实施通话记录应用程序时,我遇到了类似的问题,
我已在 AndroidManifest.xml 文件中添加了以下代码,然后该寄存器正常工作
<receiver android:name=".Services.Receiver"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE"/>
<action android:name="android.intent.action.ANSWER"/>
<action android:name="android.intent.action.CALL_BUTTON"/>
<action android:name= "android.intent.action.NEW_OUTGOING_CALL"/>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>