web-dev-qa-db-ja.com

上のポップアップウィンドウAndroid真の発信者のようなネイティブ着信画面Android app

Androidで着信コール用のブロードキャストレシーバーを開発しています。着信コールを取得すると、ネイティブの着信コール画面でポップアップを膨らませたいと思います。

そのコードを完成させました。しかし今の問題は、 Android 4.1(Jelly bean)APIレベル17 で、電話が鳴ったときにPHONE_STATEOFF 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アプリでこの機能を実現するにはどうすればよいですか?

これが真の発信者の仕組みです:

Enter image description here

私の現在の出力:

Enter image description here

アップデート1

報奨金を受け取った後も、探しているものが正確に得られませんが、すべてに戻ります。私はそれに取り組んでいます。とにかく、このコードはほとんどのAndroid携帯電話で動作します。誰かがそのソリューションを使用してキャッチしようとしている場合は、誰もが利益を得ることができるようにここに書いてください。

更新2

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

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

48
Nikhil Agrawal

システムブロードキャストレシーバーとレシーバーの両方が画面の上部に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);

それがあなたのお役に立てば幸いです。

27
Hiren Dabhi

super.onCreateメソッドの前にコードを試してください。スーパーを呼び出した後、コードはスキップされると思います。いつか、この種のトリックがうまくいきました。

9
Jashan PJ

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>
9
Sam Adamsh

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

Enter image description here

ファイル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. 初めて動作するだけです。もう一度電話をかけると、アプリが停止します(通話が閉じられたときにアクティビティが閉じられていないためだと思います)

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

[〜#〜] update [〜#〜]

こちらIS LINK OF SMALL DEMO) これを達成する方法。

  1. 閉じられたコールがクロース(不在または拒否)の場合、アクティビティはクローズされていません。 -解決済み
  2. アクティビティをクリックできない(アプリ用にボタンを1つ配置したい)-解決済み
  3. 初めて動作するだけです。もう一度電話をかけると、アプリが停止します(通話が閉じられたときにアクティビティが閉じられていないためだと思います)-解決済み
7
Dharmik

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

私が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;
    }
6
bgse

記述された結果を達成するために活動を開始すべきではないと思います。レイアウトパラメータに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 -完全なソースコードであると考えてくださいサンプル。

6

また、ピンロックのあるデバイスでオーバーレイが表示されないという同様の問題に直面していました。私たちのために働いた解決策は以下の通りです:

mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
    mParams = new LayoutParams(
        LayoutParams.MATCH_PARENT,
        LayoutParams.WRAP_CONTENT,
        LayoutParams.TYPE_SYSTEM_ERROR,
        LayoutParams.FLAG_NOT_FOCUSABLE,
        PixelFormat.TRANSLUCENT);

そうだった LayoutParams.TYPE_SYSTEM_ERROR違いを生みました。

1
Manju Mathew

私の方法:

  1. レシーバーを使用して電話のイベントを受信する
  2. サービスを使用してオーバーレイを作成する

    ps:wmParams.type = WindowManager.LayoutParams.TYPE_PHONE; 
    
0
user2927550

これを試して

AlertDialog.Builder builder = new AlertDialog.Builder(context.getApplicationContext());
            LayoutInflater inflater = LayoutInflater.from(context);
            View dialogView = inflater.inflate(R.layout.caller_dialog, null);
            ImageView button = dialogView.findViewById(R.id.close_btn);
            builder.setView(dialogView);
            final AlertDialog alert = builder.create();
            alert.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
            alert.getWindow().setType(WindowManager.LayoutParams.TYPE_PHONE);
            alert.setCanceledOnTouchOutside(true);
            alert.show();
            WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
            Window window = alert.getWindow();
            window.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
            window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
            window.setGravity(Gravity.TOP);
            lp.copyFrom(window.getAttributes());
            //This makes the dialog take up the full width
            lp.width = WindowManager.LayoutParams.MATCH_PARENT;
            lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
            window.setAttributes(lp);
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    //close the service and remove the from from the window
                    alert.dismiss();
                }
            });
0

シンプルなブロードキャストレシーバーを使用して、このコードをブロードキャストレシーバーに配置します。

public void onReceive(final Context context, final Intent intent) {

    Log.v(LOG_TAG, "Receieved notification about network status");
    WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);

    WindowManager.LayoutParams params = new WindowManager.LayoutParams(
            WindowManager.LayoutParams.MATCH_PARENT,
            WindowManager.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 = WindowManager.LayoutParams.MATCH_PARENT;
    params.width = WindowManager.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);

}
0
Riyaz Khan
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
0
Amrish Kakadiya