web-dev-qa-db-ja.com

オレオ:放送受信機が機能しない

ユーザーが新しい電話をかけるたびに、アプリケーションで通知トリガーを取得しようとしていました。アクティビティにレシーバーを登録し、onDestroy()メソッドで破棄しています。以下は、登録するためのコードスニペットです

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

私が直面している問題は、ブロードキャストレシーバーのオーバーライドonReceive()メソッドでトリガーを取得していないことです。特にオレオの放送を受信するために、新しい実装や別の方法が必要かどうかを教えてください。

前もって感謝します。

4
user1955126

私は長い間この問題に直面していました。そして、誰もがあなたにグーグル開発者サイトへのリンクを提供します。それは彼らがバックグラウンドサービスにどのように制限を持っているかについて何も説明していません。適切なドキュメントがなく、開発者にOreo以上で実装する方法を示すサンプルコードもありません。スタック上でも-オーバーフローでは、制限に関するグーグル開発者サイトへのリンクのみが見つかります。


あなたや他の開発者がこれが非常に役立つことを願っています。


NEW_OUTGOING_CALL OR BOOT_COMPLETEDのように、マニフェストで引き続き使用できる除外事項がまだいくつかあります。ただし、アプリケーションコンテキストでランタイムを実装することをお勧めします。PHONE_STATEを常に着信および発信呼び出しを取得できるように準備したかったのです。 ;再起動するたびに...


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

上記のmanifest.xmlには、WRITE_EXTERNAL_STORAGEREAD_EXTERNAL_STORAGEを配置していません。ランタイムに実装すると、Android studioによって自動的に挿入されます。


これが私の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));
    }
}
}

これが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");
}
}

電話をかける前に受信機でsqliteデータベーステーブルに電話番号を挿入します。これにより、CatchNumbers.Javaサービスからそれを読み取り、着信番号と発信番号に対して必要なアクションを実行できます。それがあなたや他の誰かに役立つことを願っています

6
sandhya sasane

Sandhya Sasaneのソリューションは、Android 9エミュレーターでBOOT_COMPLETED通知を受信します(「adb」を介して強制するか、エミュレーターを再起動します)。

しかし、実際のデバイスでは、EMUI9.1.0.119を搭載したHuaweiP-Smartは発生しません:(

0
Ice72