web-dev-qa-db-ja.com

BroadcastReceiverを存続させる方法

現在、Truecallerのようなコールブロッカーアプリケーションを開発しています。

必要なもの

最近のアプリリストから自分のアプリが削除されていても、着信を検出したい。

Manifest.xmlコード

<receiver Android:name=".PhoneStateReceiver">
        <intent-filter>
            <action Android:name="Android.intent.action.PHONE_STATE" />
        </intent-filter>
    </receiver>

私の放送受信機コード

@Override
public void onReceive(Context context, Intent intent) {
  //my call blocking code
}

私の問題

BroadcastReceiverは、最近のアプリリストから削除したかのようにバックグラウンドで動作しません。

ここに私の完全なマニフェストコード

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:Android="http://schemas.Android.com/apk/res/Android"
package="ranjith.callblocker">

<uses-permission Android:name="Android.permission.READ_PHONE_STATE" />

<uses-permission Android:name="Android.permission.CALL_PHONE" />
<uses-permission Android:name="Android.permission.READ_CONTACTS" />

<uses-permission Android:name="Android.permission.GET_TASKS" />

<application
    Android:allowBackup="true"
    Android:enabled="true"
    Android:icon="@mipmap/ic_launcher"
    Android:label="@string/app_name"
    Android:supportsRtl="true"
    Android:theme="@style/AppTheme">
    <receiver
        Android:name=".PhoneStateReceiver"
        Android:enabled="true"
        Android:exported="true"
        Android:process=":anotherProcess">
        <intent-filter Android:priority="1000">
            <action Android:name="Android.intent.action.PHONE_STATE" />
        </intent-filter>
    </receiver>
    <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>
</application>

</manifest>

サービスなどを利用する必要がありますか?

更新:

Surajの回答で、レシーバーでこのタグを試しました

    Android:enabled="true"
    Android:exported="true"
    Android:process=":anotherProcess"

kitKatで動作します。ただし、Lollipopでは動作しません。

更新された質問:

放送受信機を存続させることができない場合アプリが閉じていても着信を検出するにはどうすればよいですか?

誰もが詳細な答えを与えます。

21
Ranjith Kumar

Serviceを作成し、マニフェストに登録する必要があります。その後、マニフェストではなく、サービス内にBroadcastReceiverを登録する必要があります。

アプリが最近から削除されても、Serviceは停止しないため、レシーバーも引き続き機能します。アプリが最近から削除されると、Service#onTaskRemovedを介してコールバックを受け取ることもあります。

他のいくつかのケースも処理する必要がありますが、Serviceを停止できる場合。

1つのケースは、システムのメモリが不足しているときにAndroidがサービスを停止できる場合、onStartCommandメソッドからSTART_STICKYを返すことで修正できます。

他のケースは、デバイスが再起動されたとき、これを修正するためにmnifestでACTION_BOOT_COMPLETEDのブロードキャストレシーバーを登録する必要があります。 onReceiveメソッドでサービスを再起動できます。

以下のサンプルコードがお役に立てば幸いです-

private BroadcastReceiver mReceiver;

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.v(LOG_TAG, "worked");
        }
    };
    registerReceiver(mReceiver, 
            new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));

    return START_STICKY;
}

@Override
public void onDestroy() {
    unregisterReceiver(mReceiver);
    super.onDestroy()
}
2
Sachin Gupta

これがコードですそれは私にとってはうまくいきます:

マニフェストで権限を追加します。
<uses-permission Android:name="Android.permission.READ_PHONE_STATE" />

次のステップでは、アプリの起動時にService startを作成します(おそらくMainActivity)。このコードをonCreateのメソッドServiceで呼び出します。

コード

((TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE)).listen(new PhoneStateListener(new PhoneStateListener.PhoneCallListener() {
            @Override
            public void PhoneCall() {
              // Do something
            }
            @Override
            public void PhoneOff() {
               // Do something
            }
            @Override
            public void MissCall() {
               // Do something
            }
        }), PhoneStateListener.LISTEN_CALL_STATE);

PhoneStateListener.Java

import Android.telephony.TelephonyManager;

/**
 * PhoneStateListener.
 *
 * @author DaoLQ
 */
public class PhoneStateListener extends Android.telephony.PhoneStateListener {

    public interface PhoneCallListener {
        void PhoneCall();

        void PhoneOff();

        void MissCall();
    }

    private PhoneCallListener mPhoneCallListener;

    private boolean ring = false;
    private boolean callReceived = false;

    public PhoneStateListener(PhoneCallListener listener) {
        mPhoneCallListener = listener;
    }

    @Override
    public void onCallStateChanged(int state, String incomingNumber) {
        super.onCallStateChanged(state, incomingNumber);
        switch (state) {
            case TelephonyManager.CALL_STATE_IDLE:
                mPhoneCallListener.PhoneOff();
                if (ring && !callReceived) {
                    mPhoneCallListener.MissCall();
                }
                break;

            case TelephonyManager.CALL_STATE_OFFHOOK:
                // CALL_STATE_OFFHOOK;
                callReceived = true;
                mPhoneCallListener.PhoneCall();
                break;

            case TelephonyManager.CALL_STATE_RINGING:
                ring = true;
                mPhoneCallListener.PhoneCall();
                break;

            default:
                break;
        }
    }
}
0
DaoLQ
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:Android="http://schemas.Android.com/apk/res/Android"
package="com.Android.phonestatelistener">
<uses-permission Android:name="Android.permission.RECEIVE_SMS" />
<uses-permission Android:name="Android.permission.READ_PHONE_STATE"/>

<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.Android.receiver.PhoneStateListener"           Android:exported="true"  >

        <intent-filter >
            <action Android:name="Android.intent.action.PHONE_STATE"/>
            <action Android:name="Android.intent.action.NEW_OUTGOING_CALL"/>
            <action Android:name="Android.provider.Telephony.SMS_RECEIVED" />
        </intent-filter>
    </receiver>
</application>
public class PhoneStateListener extends BroadcastReceiver {

public static String TAG="PhoneStateListener";

public static String ACTION_PHONE_STATE = "Android.intent.action.PHONE_STATE";
public static String ACTION_OUTGOING_CALL = "Android.intent.action.NEW_OUTGOING_CALL";
public static String ACTION_SMS_RECEIVED = "Android.provider.Telephony.SMS_RECEIVED";

@Override
public void onReceive(Context context, Intent intent) {

    if (intent.getAction().equals(ACTION_PHONE_STATE)) {

        String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
        if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {

            Toast.makeText(context, "Incoming call", Toast.LENGTH_SHORT).show();
            Log.d(TAG, "Incoming call");
        }

    } else if (intent.getAction().equals(ACTION_OUTGOING_CALL)) {
        Toast.makeText(context, "Outgoing call", Toast.LENGTH_SHORT).show();

        Log.d(TAG, "Outgoing call");
    } else if (intent.getAction().equals(ACTION_SMS_RECEIVED)) {

        Toast.makeText(context, "Incoming message", Toast.LENGTH_SHORT).show();
        Log.d(TAG, "Incoming message");
    }

}

}

これを試して 。アプリケーションを強制的に閉じるまで機能します

0
anoopg87

アクティビティのonCreate()でブロードキャストレシーバーを内部に登録してみてください。

0
user4356416