【问题标题】:Android: Presenting a notification during a call?Android:在通话期间显示通知?
【发布时间】:2011-03-24 23:51:20
【问题描述】:

我有一个监听来电的广播接收器。我想调整来电屏幕。现在我可以向通知栏展示祝酒词并向通知栏添加通知(顺便说一句,在接听电话之前,由于屏幕被锁定,用户无法将其拉下,这有点糟糕)。我试图显示警报但它崩溃了 - 不允许吗?广播接收器中的代码有没有办法做其他事情,比如更改呼叫者的头像或给它一个名字(即使它不存在于联系人中)。假设我的广播接收器拦截了一个电话 - 它可以将电话号码和自定义头像添加到联系人,以便他们立即出现在通话屏幕中吗?

你怎么看?


编辑

我已经测试了供应商的代码,它可以工作,但是从后台线程更改 UI 是不安全的,所以我尝试稍微调整他的代码以使其线程安全,但 toast 没有出现一些原因。你怎么看?

private Handler handler = new Handler();

    private void showToast() { 
        Thread thread = new Thread(null, doBackgroundThreadProcessing, "Background");
        thread.start();
    }

    private Runnable doBackgroundThreadProcessing = new Runnable() { 
        public void run() {
            backgroundThreadProcessing();
        } 
    };

    private void backgroundThreadProcessing() {
        handler.post(new Runnable() {
            public void run() { 
                int count = 0;
                try{
                    while (count < 10) {
                        toast.show();
                        Thread.sleep(1850);
                        count++;

                    }
                }
                catch(Exception e){

                    Log.e("LongToast", "", e);
                }
            } 
        });
    }

【问题讨论】:

    标签: android broadcastreceiver android-notifications alert phone-call


    【解决方案1】:

    你需要一个这样的广播接收器:

    public class IncomingBroadcastReceiver extends BroadcastReceiver {
    
        @Override
        public void onReceive(Context context, Intent intent) {
    
            MyLog.d("IncomingBroadcastReceiver: onReceive: ");
    
            String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
            MyLog.d("IncomingBroadcastReceiver: onReceive: " + state);
            if (state.equals(TelephonyManager.EXTRA_STATE_RINGING))
            {
                Intent i = new Intent(context, IncomingCallActivity.class);
                i.putExtras(intent);
                i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    
                context.startActivity(i);
            }
    
        }
    
    }
    

    并在清单中将其注册到&lt;action android:name="android.intent.action.PHONE_STATE"&gt;&lt;/action&gt;

    然后像这样创建一个 Activity:

    public class IncomingCallActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
    
            MyLog.d("IncomingCallActivity: onCreate: ");
    
            // TODO Auto-generated method stub
            super.onCreate(savedInstanceState);
    
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
    
            setContentView(R.layout.main);
    
            String number = getIntent().getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
            TextView text = (TextView)findViewById(R.id.text);
            text.setText("Incoming call from " + number);
        }
    }
    

    有这样的布局:

    <?xml version="1.0" encoding="utf-8"?>
    
    <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/text"
        android:layout_width="match_parent" android:layout_height="match_parent"
        android:gravity="center_vertical|center_horizontal"
        android:text="text"
        android:windowBackground="@android:color/transparent" 
        android:windowIsTranslucent="true" 
        android:windowAnimationStyle="@android:style/Animation.Translucent"></TextView>
    

    这将在来电屏幕顶部产生一个类似对话框的半透明活动,允许用户接听电话(不干扰触摸事件)。

    【讨论】:

    • 我刚刚尝试了您的代码,当收到呼叫时,自定义活动会显示片刻,然后会显示常规呼叫屏幕。我根本看不到自定义活动。我正在使用 2.3 的关系 1 上对其进行测试。
    • 您好,由于某些设备在显示来电活动时存在延迟,您可以尝试在显示活动之前插入 1000 毫秒的睡眠。我也有这个问题。
    • 我正在尝试这个,但是我的透明窗口弹出在我的应用程序中打开的最后一个活动之上,而不是拨号器。出了什么问题?
    • @SirKnigget,我尝试了你解释的方式,但是当我接到电话时,它首先显示呼叫屏幕一秒钟,然后显示我们放置文本视图的新活动,它覆盖了后面屏幕我的意思是通话屏幕,我看不到通话屏幕。我已将 1000 毫秒睡眠,但没有工作。请指导我,在这种情况下该怎么办?谢谢
    • @malandro95:我面临同样的问题,如果我在我的应用程序中并且有来电,窗口会在我的应用程序屏幕上弹出,而不是拨号器。拨号器被推回。你怎么修好它的。非常感谢您的帮助
    【解决方案2】:

    在 Android 2.3 之前,您无法覆盖呼叫屏幕,但您可以在其上显示 Toast 消息。吐司的最长持续时间是 3 秒,之后它就会消失。但是,您可以创建一个线程,每 2 秒调用一次 toast 的 show() 方法。类似的东西:

    Thread t = new Thread() {
            public void run() {
    
                try {
                    while (true) {
                        if( isInCall ){
    
                            toast.cancel();
                            break;
                        }
    
                        toast.show();
                        sleep(1850);
                    }
                } catch (Exception e) {
    
                    Log.d("Exception: " + e.toString());
                }
            }
        };
        t.start();
    

    你必须声明 toast:

    private Toast toast;
    

    您必须先初始化 toast 对象才能显示它。

    toast = new Toast(getBaseContext());    
    LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View layout = inflater.inflate(R.layout.toast, null, false);
    
        toast.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 0);
        toast.setDuration(Toast.LENGTH_LONG);
        toast.setView(layout);
    

    【讨论】:

    • 我确实测试了您的代码并且它可以工作,但是您正在从后台线程执行 UI 操作,这可能会导致异常。
    • @Alex1987 这是一个简单的代码。您可以添加处理程序并使 UI 操作线程安全。
    • 是的,我知道。但是当我用处理程序包装它时,吐司没有出现。我在原始消息中发布了一些代码。
    【解决方案3】:

    【讨论】:

    • 你的链接是关于活动的,这不是我问的。我要求一种创造性的方式来显示通知。现在,我可以在来电期间显示具有复杂布局的 toast 约 3 秒钟。我还可以在通知栏上显示通知 - 现在还有其他选项吗?
    • @Alex1987 我也有同样的问题。您只能在通知栏中显示一个 toast 和一个通知图标。但是,您可以创建自定义 toast 外观并多次调用 show 方法:)
    • @vendor 如何让吐司长时间可见?你有处理这个的后台线程吗?如果有,你有一些工作代码吗?
    • @vendor 您的代码有效,但您正在从后台线程进行 UI 操作,这可能会导致异常。我试图调整您的代码(我已将其发布在原始问题中)以使其线程安全,但由于某种原因未显示敬酒 - 您知道为什么吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-06
    • 1970-01-01
    • 2023-04-04
    • 1970-01-01
    • 2012-04-25
    相关资源
    最近更新 更多