Displaying a message from BroadcastReceiver

2019-09-02 07:45发布

I wrote a simple class that extends BroadcastReceiver to handle an incoming call and get the caller's number. Now I want to display that number in a popup window or something similar. I've tried to display an alert dialog or open an activity but my app crashed. Then I read that it's not a good idea to start dialog from a BroadcastReceiver class. I need you to advice me how to correctly display the caller's number on the screen when there's an incoming call. This is my Broadcast Receiver class:

package com.example.nrsearch;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;

public class CallReceiver extends BroadcastReceiver {
    public CallReceiver() {
    }

@Override
public void onReceive(Context context, Intent intent) {
    Log.i("CallReceiverBroadcast", "onReceive() is called. ");
    TelephonyManager teleMgr = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
    PhoneStateListener psl = new PhoneStateListener() {
        @Override
        public void onCallStateChanged(int state, String incomingNumber) {
            Log.i("CallReceiverBroadcast", "onCallStateChanged() is called. ");
            switch (state) {
            case TelephonyManager.CALL_STATE_RINGING:
                Log.i("CallReceiverBroadcast", "Incoming call caught. Caller's number is " + incomingNumber + ".");
            }
        }
    };
    teleMgr.listen(psl, PhoneStateListener.LISTEN_CALL_STATE);
    teleMgr.listen(psl, PhoneStateListener.LISTEN_NONE);
}
}

2条回答
Deceive 欺骗
2楼-- · 2019-09-02 08:19

I created a IncomingCallService service that extends from BroadcastReceiver to handle an incoming call and get the caller's number. Now I displayed that Incoming caller number in a popup window like TrueCaller. Its working fine me. Hope it should helpful for you. Please try and let me know. Thanks

CallReceiver.java

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;

public class CallReceiver extends BroadcastReceiver {

    static String IncomingNumber;
    @Override
    public void onReceive(final Context context, Intent intent) {
        TelephonyManager teleMgr = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
        PhoneStateListener psl = new PhoneStateListener() {
        @Override
        public void onCallStateChanged(int state, String incomingNumber) {
            switch (state) {
            case TelephonyManager.CALL_STATE_RINGING:
                IncomingNumber = incomingNumber;
                Log.i("CallReceiverBroadcast", "Incoming call caught. Caller's number is " + incomingNumber + ".");
                Intent i = new Intent(context, IncomingCallService.class);
                context.startService(i);
            case TelephonyManager.CALL_STATE_IDLE:
                Log.i("CallReceiverBroadcast", "CALL_STATE_IDLE");                  
                IncomingCallService.clearView(context);
                // Call Disconnected
                break;

            case TelephonyManager.CALL_STATE_OFFHOOK:
                Log.i("CallReceiverBroadcast", "CALL_STATE_OFFHOOK");
                IncomingCallService.clearView(context);
                // Call Answer Mode
                break;
            }
        }
        };
        teleMgr.listen(psl, PhoneStateListener.LISTEN_CALL_STATE);
        teleMgr.listen(psl, PhoneStateListener.LISTEN_NONE);
    }
}

IncomingCallService.java:

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.os.IBinder;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView;

public class IncomingCallService extends Service {

    static View view = null;
    static WindowManager wm;
    static LayoutInflater inflater;
    static WindowManager.LayoutParams params;
    private static TextView txtIncomingnumber;
    static boolean processingAction = false;

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
    super.onCreate();
    params = new WindowManager.LayoutParams(WindowManager.LayoutParams.MATCH_PARENT, 350,
                WindowManager.LayoutParams.TYPE_PHONE, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                        | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT);

    params.gravity = Gravity.LEFT | Gravity.TOP;
    params.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;

    wm = (WindowManager) getSystemService(WINDOW_SERVICE);

    inflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    view = inflater.inflate(R.layout.activity_main,null);

    wm.addView(view, params);
    txtIncomingnumber = (TextView)view.findViewById(R.id.txtIncomingnumber);
    txtIncomingnumber.setText("You have Incoming Call from " + CallReceiver.IncomingNumber);

        return START_STICKY;
    }

    public static void clearView(Context context) {
        wm = (WindowManager) context.getSystemService(WINDOW_SERVICE);
        if(view != null) {
            if(view.isEnabled()){
                wm.removeView(view);
                view = null;
            }           
        }
    }
}

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_alignParentLeft="true"
    android:background="#0090FF"
    android:padding="10dp"
    android:keepScreenOn="true" >

    <TextView
    android:id="@+id/txtIncomingnumber"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:layout_centerHorizontal="true"
    android:layout_marginTop="30dp"
    android:text="Incoming Call Number"
    android:textColor="#fff" />

</RelativeLayout>

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.stackoverflow"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
    android:minSdkVersion="8"
    android:targetSdkVersion="18" />

    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
    <uses-permission android:name="android.permission.CALL_PHONE" />
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" ></uses-permission>
    <uses-permission android:name="android.permission.VIBRATE"></uses-permission> 

    <application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <receiver android:name=".CallReceiver" >                     
        <intent-filter android:priority="99999">
            <action android:name="android.intent.action.PHONE_STATE"/>
        </intent-filter>
    </receiver>

    <activity
        android:name="com.stackoverflow.MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <service android:name=".IncomingCallService">
    </service> 
    </application>

</manifest>
查看更多
可以哭但决不认输i
3楼-- · 2019-09-02 08:28

If you want to show a dialog from inside your onReceive of the BroadcastReceiver, you have to start a transparent activity with an alert dialog and NEVER called setContentView(). The activity will have an transparent view and only the alert dialog will show..

Your Broadcast Receiver onReceive

@Override
 public void onReceive(Context context, Intent intent) {
Log.i("CallReceiverBroadcast", "onReceive() is called. ");
TelephonyManager teleMgr =(TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
PhoneStateListener psl = new PhoneStateListener() {
    @Override
    public void onCallStateChanged(int state, String incomingNumber) {
        Log.i("CallReceiverBroadcast", "onCallStateChanged() is called. ");
        switch (state) {
        case TelephonyManager.CALL_STATE_RINGING:
            Log.i("CallReceiverBroadcast", "Incoming call caught. Caller's number is " +incomingNumber + ".");
 //start activity which has dialog  
    Intent i=new Intent(context,DialogActivity.class);
     i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
     context.startActivity(i);
        }
    }
};
teleMgr.listen(psl, PhoneStateListener.LISTEN_CALL_STATE);
teleMgr.listen(psl, PhoneStateListener.LISTEN_NONE);
}

And your DiaLogActivity

  public class DialogActivity extends Activity 
{

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
  //dont call setcontent view

    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setMessage("Are you sure you want to exit?").setCancelable(
        false).setPositiveButton("Yes",
        new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
                dialog.cancel();
            }
        }).setNegativeButton("No",
        new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
                dialog.cancel();
            }
        });
    AlertDialog alert = builder.create();
    alert.show();
 }

  }
查看更多
登录 后发表回答