简体   繁体   English

奥利奥:广播接收器不工作

[英]Oreo: Broadcast receiver Not working

I was trying to get notification trigger on my application whenever the user makes a new call.每当用户拨打新电话时,我都试图在我的应用程序上获取通知触发器。 I'm registering receiver in my activity and destroying it in onDestroy() method.我正在我的活动中注册接收器并在 onDestroy() 方法中销毁它。 Following is the code snippets for registering以下是注册的代码片段

registerReceiver(inComingCall = new IncomingCall(),new IntentFilter("android.intent.action.PHONE_STATE"));

The issue I'm facing is I'm not getting any trigger in override onReceive() method for the Broadcast receiver.我面临的问题是我没有在广播接收器的覆盖 onReceive() 方法中获得任何触发器。 Kindly let me know whether any new implementations or the separate way I should do for receiving the broadcast especially for Oreo.请让我知道是否有任何新的实现或单独的方式来接收广播,尤其是奥利奥。

Thanks in Advance.提前致谢。

I faced this issue for a long time.我面对这个问题很长时间了。 And every one will provide you a link to google developers site, which describes nothing than how they are having limits on background services;每个人都会为您提供一个指向 google 开发者站点的链接,该链接仅描述了他们如何限制后台服务; with no proper documentation and no sample code showing developers, how to implement it on Oreo or Higher.没有适当的文档,也没有向开发人员展示如何在 Oreo 或更高版本上实现它的示例代码。 Even on stack-Overflow you will find only links to the google developers site on limitations.即使在 stack-Overflow 上,您也只能找到有关限制的 google 开发人员站点的链接。


I hope you or some other developer will find this very helpful.我希望您或其他一些开发人员会发现这非常有帮助。


There are still some exclusions like NEW_OUTGOING_CALL OR BOOT_COMPLETED which you can still use in manifest.仍然有一些排除项,例如NEW_OUTGOING_CALL OR BOOT_COMPLETED ,您仍然可以在清单中使用它们。 But its a good practise to implement runtime at application context.但是在应用程序上下文中实现运行时是一个很好的做法。 I wanted my PHONE_STATE ready always for getting incoming and outgoing calls;我希望我的PHONE_STATE随时准备接听来电; On every reboot too...在每次重新启动时...


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.rushi.boottest">

<uses-sdk
    android:minSdkVersion="16"
    android:targetSdkVersion="26" />

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

<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>

    <receiver
        android:name=".MyReceiver"
        android:enabled="true"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>

    <service
        android:name=".CatchNumbers"
        android:enabled="true"
        android:exported="true" />
    <service
        android:name=".WatchMan"
        android:enabled="true"
        android:exported="true"></service>
</application>

</manifest>

In above manifest.xml i have not placed WRITE_EXTERNAL_STORAGE and READ_EXTERNAL_STORAGE .在上面 manifest.xml 我没有放置WRITE_EXTERNAL_STORAGEREAD_EXTERNAL_STORAGE It has automatically inserted by android studio as i implemented it runtime.当我在运行时实现它时,它已由 android studio 自动插入。


Here is my OnBoot Receiver :这是我的 OnBoot 接收器:

package com.example.rushi.boottest;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.util.Log;
import android.widget.Toast;

public class MyReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
    Log.d("BootTest : ", "\nOnBootReceiver - Received a broadcast!");
    Toast.makeText(context, "OnBootReceiver Received a broadcast!!", Toast.LENGTH_LONG).show();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
    {
        context.startForegroundService(new Intent(context, WatchMan.class));
    }
    else
    {
        context.startService(new Intent(context, WatchMan.class));
    }
}
}

Here is WatchMan.java a foreground service that implements receivers runtime这是 WatchMan.java 一个实现接收器运行时的前台服务

public class WatchMan extends Service
{
NotificationManager mNotifyManager;
NotificationCompat.Builder mBuilder;
NotificationChannel notificationChannel;
String NOTIFICATION_CHANNEL_ID = "17";

private BroadcastReceiver mCallBroadcastReceiver = new BroadcastReceiver()
{
    @Override
    public void onReceive(Context context, Intent intent)
    {
        String PhoneNumber = "UNKNOWN";
        Log.d("RECEIVER :  ","IS UP AGAIN....");

        try
        {
            String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
            if(state == null)
            {
                PhoneNumber = "UNKNOWN";
            }
            else if (state.equals(TelephonyManager.EXTRA_STATE_RINGING))
            {
                PhoneNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
                Log.d("RECEIVER : ","Incoming number : "+PhoneNumber);
            }
            if(intent.getAction().equals("android.intent.action.NEW_OUTGOING_CALL"))
            {
                PhoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
                Log.d("RECEIVER : ","Outgoing number : "+PhoneNumber);
            }
            if(!PhoneNumber.contentEquals("UNKNOWN"))
            {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
                {
                    context.startForegroundService(new Intent(context, CatchNumbers.class));
                }
                else
                {
                    context.startService(new Intent(context, CatchNumbers.class));
                }
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
            Log.e("RECEIVER : ", "Exception is : ", e);
        }
    }
};

public WatchMan() { }

@Override
public void onCreate()
{
    super.onCreate();
    Log.d("WatchMan : ", "\nOnCreate...");

    IntentFilter CallFilter = new IntentFilter();
    CallFilter.addAction("android.intent.action.NEW_OUTGOING_CALL");
    CallFilter.addAction("android.intent.action.PHONE_STATE");
    this.registerReceiver(mCallBroadcastReceiver, CallFilter);

    Log.d("WatchMan : ", "\nmCallBroadcastReceiver Created....");

    mNotifyManager = (NotificationManager) getApplicationContext().getSystemService(NOTIFICATION_SERVICE);
    mBuilder = new NotificationCompat.Builder(this, null);
    mBuilder.setContentTitle("Insta Promo")
            .setContentText("Checking New Numbers")
            .setTicker("Checking New Numbers")
            .setSmallIcon(R.drawable.ic_launcher_background)
            .setPriority(Notification.PRIORITY_LOW)
            .setDefaults(Notification.DEFAULT_ALL)
            .setVisibility(Notification.VISIBILITY_PUBLIC)
            .setOngoing(true)
            .setAutoCancel(false);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
    {
        notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "My Notifications", NotificationManager.IMPORTANCE_HIGH);

        // Configure the notification channel.
        notificationChannel.setDescription("Channel description");
        notificationChannel.enableLights(true);
        notificationChannel.setLightColor(Color.RED);
        notificationChannel.setVibrationPattern(new long[]{0, 1000, 500, 1000});
        notificationChannel.enableVibration(true);
        notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
        mNotifyManager.createNotificationChannel(notificationChannel);

        mBuilder.setChannelId(NOTIFICATION_CHANNEL_ID);
        startForeground(17, mBuilder.build());
    }
    else
    {
        mBuilder.setChannelId(NOTIFICATION_CHANNEL_ID);
        //startForeground(17, mBuilder.build());
        mNotifyManager.notify(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_NOT_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");
}
}

Now in the receiver before calling insert phone numbers into sqlite database table;现在在接收方调用之前插入电话号码到sqlite数据库表中; so that you can read it from CatchNumbers.java service and perform whatever actions you wants on incoming and outgoing numbers.以便您可以从 CatchNumbers.java 服务读取它并对传入和传出号码执行任何您想要的操作。 Hope it helps you or someone else希望它可以帮助您或其他人

The solution of Sandhya Sasane work for me on the android 9 emulator the BOOT_COMPLETED notification is received (either forcing it via "adb" or rebooting the emulator). Sandhya Sasane 的解决方案在 android 9 模拟器上为我工作,收到 BOOT_COMPLETED 通知(通过“adb”强制它或重新启动模拟器)。

But on a real device Huawei P-Smart with EMUI 9.1.0.119 never happens :(但是在带有 EMUI 9.1.0.119 的真实设备上,华为 P-Smart 永远不会发生:(

None of the above answers seem to work for me.以上答案似乎都不适合我。 Here is my solution but in kotlin.这是我的解决方案,但在 kotlin 中。 Paste the following parts of the code and change the necessary details as per your app.粘贴以下代码部分并根据您的应用更改必要的详细信息。

After onCreate method in Mainactivity:在 Mainactivity 中的 onCreate 方法之后:

override fun onStart() {
    super.onStart()
    var intentfilter1: IntentFilter = IntentFilter("com.spotify.music.playbackstatechanged")

    intentfilter1.addCategory(Intent.CATEGORY_DEFAULT)
    registerReceiver(mreceiver, intentfilter1)


}

override fun onStop() {
    super.onStop()
    unregisterReceiver(mreceiver)
}

In onCreate method:在 onCreate 方法中:

mreceiver = SpotifyBroadcastReceiver()

In MainAvtivity before onCreate method:在 onCreate 方法之前的 MainAvtivity 中:

lateinit var mreceiver: SpotifyBroadcastReceiver

Mainfest.xml file Mainfest.xml 文件

     <receiver android:name=".SpotifyBroadcastReceiver" //name of the broadcast receiver class
        android:permission="android.permission.RECEIVE_BOOT_COMPLETED"
        android:enabled="true"
        android:exported="true">
        <intent-filter>
            <action android:name="com.spotify.music.playbackstatechanged" /> //Things required by my broadcast receiver class
        </intent-filter>
    </receiver>

Let me know if i missed something or you need some other info related to the snippet.如果我错过了什么,或者您需要一些与代码段相关的其他信息,请告诉我。

PS: Im new to kotlin too....im just sharing what worked for me. PS:我也是 kotlin 的新手......我只是分享对我有用的东西。 It might or might not work for you configuration so Happy coding!!它可能适用于您的配置,也可能不适用,所以编码快乐!!

I also had this kind of issue, but I found a better solution:我也有这种问题,但我找到了更好的解决方案:

@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());
    }
}

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);

    }
}

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();
    }
}

For complete reference you can see also https://github.com/devggaurav/BroadcastReceiver-For-Naught-and-Oreo-devices如需完整参考,您还可以查看https://github.com/devggaurav/BroadcastReceiver-For-Naught-and-Oreo-devices

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM