52

私は Android で着信コール用のブロードキャスト レシーバを開発しています。着信コールを受信すると、ネイティブの着信コール画面にポップアップを表示したいと考えています。

そのコードを完成させました。しかし今の問題は、Android 4.1 (Jelly Bean) API レベル 17では、電話が鳴ったときにPHONE_STATEが として来てOFF HOOK、アクティビティを呼び出している場合は呼び出されますが、その下のコードは実行されません。コードをリストしています:

私の放送受信機

package com.example.popwindowonincomingcallscreen;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;

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

public class IncomingBroadcastReceiver extends BroadcastReceiver {

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

        Log.d("IncomingBroadcastReceiver: onReceive: ", "flag1");

        String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
        Log.d("IncomingBroadcastReceiver: onReceive: ", state);
        if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)
                || state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) {

            Log.d("Ringing", "Phone is ringing");

            Intent i = new Intent(context, IncomingCallActivity.class);
            i.putExtras(intent);
            i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            i.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
            Wait.oneSec();
            context.startActivity(i);
        }
    }
}

私が呼んでいる活動:

import android.app.Activity;
import android.os.Bundle;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.View.MeasureSpec;
import android.view.Window;
import android.view.WindowManager;
import android.widget.TextView;

public class IncomingCallActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        try {
            Log.d("IncomingCallActivity: onCreate: ", "flag2");

            */ After this line, the code is not executed in Android 4.1 (Jelly Bean) only/*

            // TODO Auto-generated method stub
            super.onCreate(savedInstanceState);

            getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
            getWindow().addFlags(
                    WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);

            Log.d("IncomingCallActivity: onCreate: ", "flagy");

            setContentView(R.layout.main);

            Log.d("IncomingCallActivity: onCreate: ", "flagz");

            String number = getIntent().getStringExtra(
                    TelephonyManager.EXTRA_INCOMING_NUMBER);
            TextView text = (TextView) findViewById(R.id.text);
            text.setText("Incoming call from " + number);
        } 
        catch (Exception e) {
            Log.d("Exception", e.toString());
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

try {
    Log.d("IncomingCallActivity: onCreate: ", "flag2");
}

コードは Android 4.1 (Jelly Bean) では実行されていませんが、他のバージョンでは動作しています。

私ができるほとんどすべての方法を試しました。このコードは、ネイティブの通話画面に半透明のアクティビティを表示しており、電話を取るなどのバックグラウンド コントロールをブロックしていません。しかし、私はそれが本当の発信者のようになりたいです。真の発信者が着信画面にウィンドウを表示している様子のスナップショットを添付しました。

Android アプリでこの機能を実現するにはどうすればよいですか?

これは真の呼び出し元がどのように機能するかです:

ここに画像の説明を入力してください

私の現在の出力:

ここに画像の説明を入力してください

更新 1

報奨金の後も、探しているものを正確に取得できませんが、すべてに戻ります。私はそれに取り組んでいます。とにかく、このコードはほとんどの Android フォンで機能します。誰かがそれを使用して解決策を見つけようとしている場合は、誰もが利益を得ることができるようにここに書いてください.

更新 2

トーストは Android のネイティブ コンポーネントであるため、ブロードキャスト レシーバーの onReceive メソッドに Toast を実装しようとしましたが、Android 4.1 (Jelly Bean) でも表示されません。

私のアイデアは、ブロードキャスト レシーバーの onReceive メソッドに Toast を実装し、その後、必要に応じてそのデザインを変更し、表示期間を調整することでした。しかし、もう 1 つの問題は、ブロードキャスト レシーバーでfindViewByIdが機能しないことです。そのため、トーストをカスタマイズするには、LinearLayout をプログラムで作成する必要があると思います。

4

11 に答える 11

32

システム ブロードキャスト レシーバーとレシーバーの両方がその GUI を画面の上に表示しようとしているため、カスタム GUI が常にデフォルトの GUI の上に表示されるかどうかはわかりません。どちらが最初に呼び出されるかはわかりませんが、GUI を画面上部に表示するためのトリッキーな作業の 1 つは、電話が鳴っているときに、そのハンドラーを使用して 1 ~ 2 秒後にアクティビティを呼び出すことです。

new Handler().postDelayed(new Runnable() {

     @Override
     public void run() {
         // TODO Auto-generated method stub
         Intent intent = new Intent(context, AcceptReject.class);
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         context.startActivity(intent);
     }
 }, 2000);

お役に立てば幸いです。

于 2013-04-20T05:32:55.480 に答える
9

Android 4.2 (Jelly Bean)エミュレーターでテストしたところ、truecaller のように着信画面全体をブロックすることで完璧に動作します。

public void onReceive(Context context, Intent intent) {

    WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);

    WindowManager.LayoutParams params = new WindowManager.LayoutParams(
        LayoutParams.MATCH_PARENT,
        LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.TYPE_SYSTEM_ALERT |
        WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
        WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
        WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
        PixelFormat.TRANSPARENT);

    params.height = LayoutParams.MATCH_PARENT;
    params.width = LayoutParams.MATCH_PARENT;
    params.format = PixelFormat.TRANSLUCENT;

    params.gravity = Gravity.TOP;

    LinearLayout ly = new LinearLayout(context);
    ly.setBackgroundColor(Color.RED);
    ly.setOrientation(LinearLayout.VERTICAL);

    wm.addView(ly, params);
}

マニフェストで:

<receiver android:name=""  android:enabled="true" >
    <intent-filter android:priority="-1">
        <action android:name="android.intent.action.PHONE_STATE" />
    </intent-filter>
</receiver>
于 2013-05-18T06:38:15.927 に答える
7

私もそれに取り組んでいます(ここであなたを理解するのは間違っているかもしれません)。達成したいことは、そのアクティビティを Android 4.2 (Jelly Bean) で表示することです。アクティビティを表示するのを遅らせただけです。別のクラスで PhoneStateListener を使用しました。発信者の画面に新しいアクティビティを表示できます。ここに私の完全なコードがあります:

ここに画像の説明を入力してください

ファイル MyBroadcastReceiver.java

public class MyBroadcastReceiver extends BroadcastReceiver {
    static CustomPhoneStateListener phoneStateListener;
    Context context;
    Intent intent;

    @Override
    public void onReceive(Context context, Intent intent) {
        this.context = context;
        this.intent = intent;
        // TODO Auto-generated method stub

            TelephonyManager telephonyManager = (TelephonyManager) context
                    .getSystemService(Context.TELEPHONY_SERVICE);           
            phoneStateListener = new CustomPhoneStateListener(context);
            telephonyManager.listen(phoneStateListener,
                    PhoneStateListener.LISTEN_CALL_STATE);
    }
}

ファイル CustomPhoneStateListener.java

public class CustomPhoneStateListener extends PhoneStateListener {

    // private static final String TAG = "PhoneStateChanged";
    Context context; // Context to make Toast if required
    private AudioManager amanager;
    Intent i1;

    public CustomPhoneStateListener(Context context) {
        super();
        this.context = context;
        i1 = new Intent(context, YourActivity.class);       
        i1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        i1.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);

    }

    @Override
    public void onCallStateChanged(int state, String incomingNumber) {
        super.onCallStateChanged(state, incomingNumber);

        switch (state) {
        case TelephonyManager.CALL_STATE_IDLE:
            Toast.makeText(context, "Phone state Idle", Toast.LENGTH_LONG)
                    .show();

            break;
        case TelephonyManager.CALL_STATE_OFFHOOK:

            Toast.makeText(context, "Phone state Off hook", Toast.LENGTH_LONG)
                    .show();

            break;
        case TelephonyManager.CALL_STATE_RINGING:           
            try {
                Thread.sleep(3000);
                context.startActivity(i1);              
            } catch (Exception e) {
                e.getLocalizedMessage();
            }

        default:
            break;
        }
    }

YourActivity は作成したままになります... 注: このコードでもいくつかの問題に直面しています。

  1. クローズされた通話がクローズ (不在着信または拒否) の場合、アクティビティはクローズされていません。
  2. アクティビティをクリックできません (アプリ用に 1 つのボタンを配置したい)
  3. 初めてのみ機能します。2回目に電話をかけると、アプリが停止します(通話が終了したときにアクティビティが閉じられていないためだと思います)

(これらの問題に対してヘルプを受け入れました。ありがとうございます。誰かを助けるかもしれません)

アップデート

これを達成するための小さなデモのリンクはこちらです。

  1. クローズされた通話がクローズ (不在着信または拒否) の場合、アクティビティはクローズされていません。-解決済み
  2. アクティビティをクリックできません (アプリにボタンを 1 つ配置したい) - 解決済み
  3. 初めてのみ機能します。もう一度電話をかけると、アプリが停止します (通話が終了したときにアクティビティが閉じられていないためだと思います) - 解決済み
于 2013-06-15T07:22:30.187 に答える
6

着信画面にボタンを追加して、同様のことを試みています。

私はPhoneStateListenerからコードを呼び出していますが、Sam Adamsが投稿した答えは私にとってはうまくいきます。それとは別に、彼のコードとの唯一の本当の違いは、レイアウトを膨らませていることです。

overlay = (RelativeLayout) inflater.inflate(R.layout.overlay, null);
wm.addView(overlay, params);

エミュレーターと HTC One S (Android 4.1.1 を実行) で動作しています。

覚えておく必要があるのは、追加しているオーバーレイ ビューへの参照を保持し、電話がアイドル状態に戻ったとき (リスナーが TelephonyManager.CALL_STATE_IDLE を取得したとき) にそれを再度削除する (windowmanager インスタンスで removeView() を呼び出す) ことです。オーバーレイは画面に残ります。

        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    if(overlay!=null)
    {
        wm.removeView(overlay);
        overlay = null;
    }
于 2013-08-02T04:04:44.950 に答える
6

記載されている結果を達成するために活動を開始するべきではないと思います。LayoutParams.TYPE_SYSTEM_OVERLAYレイアウト パラメータを設定した別のビューが必要です。

このビューは、画面上の好きな場所に配置することも、画面全体をカバーすることもできます。

数行のコードを次に示します。

 _av = new ActivatorView(this);
 _avLayoutParams = new WindowManager.LayoutParams(0, 0, 0, 0,
     WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
     WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
     PixelFormat.OPAQUE);
 _avLayoutParams.screenBrightness = _fScreenBrightness = 20f;

 WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
 wm.addView(_av, _avLayoutParams);

https://bitbucket.org/gyrussolutions/yaab/src/f01cc8aff690cae1b1107287cb17835b8a3c1643/src/biz/gyrus/yaab/LightMonitorService.java?at=default#cl-338 - 完全なソース コードです。サンプルと考えてください。

于 2013-04-20T07:01:38.177 に答える
0
new Handler().postDelayed(new Runnable() {
    @Override
    public void run() {
        // TODO Auto-generated method stub
        Intent i = new Intent(context, CallingIncoming.class);
        i.putExtras(intent);
        i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK /*| Intent.FLAG_ACTIVITY_CLEAR_TASK*/);
        context.startActivity(i);
    }
}, 450);//It will help you to delay your screen and after it your screen will be top of default app screen
于 2016-06-26T06:51:55.177 に答える