着信コールを独自に表示する

Androidアプリケーションに関する最後の投稿の後、記事の読者の何人かは、通話中に自分の情報プレートを表示する方法について質問しましたか? さて、今日はこの質問に答えます。



一般的な計画は非常に簡単です。



各項目を詳しく見ていきましょう。



通話を傍受する



「they are calling us」イベントをインターセプトできるようにするには、アプリケーションマニフェストに電話のステータスを読み取る要求を追加する必要があります。



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





そこで、「呼び出し」イベントをインターセプトするサービスを登録します。



  <receiver android:name=".CallReceiver"> <intent-filter> <action android:name="android.intent.action.PHONE_STATE"/> </intent-filter> </receiver> </application>
      
      





最後に、このイベントを処理するコードを作成します。



 public class CallReceiver extends BroadcastReceiver { private static boolean incomingCall = false; @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals("android.intent.action.PHONE_STATE")) { String phoneState = intent.getStringExtra(TelephonyManager.EXTRA_STATE); if (phoneState.equals(TelephonyManager.EXTRA_STATE_RINGING)) { //  ,   String phoneNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER); incomingCall = true; Log.debug("Show window: " + phoneNumber); } else if (phoneState.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) { //     (     / ) if (incomingCall) { Log.debug("Close window."); incomingCall = false; } } else if (phoneState.equals(TelephonyManager.EXTRA_STATE_IDLE)) { //     -       //   "     ". if (incomingCall) { Log.debug("Close window."); incomingCall = false; } } } } }
      
      





この例では「着信コール」イベントのみをキャッチしますが、コードは、発信イベントも追跡する必要がある場合にどのようにやり直すことができるかを示しています。 BroadcastReceiverは「メッセージの受信-処理-死んだ」という原則に基づいて生存し、「会話を拾い上げ/終了した」というイベントはオブジェクトの新しいインスタンスを受け取るため、呼び出しに関する情報を持つ変数は静的です。



デバッグを呼び出す



もちろん、実際の電話で通話をデバッグできますが、エミュレータでテストする方が簡単で高速です。 1つのネイティブエミュレータから別のエミュレータへの呼び出しは、標準のダイヤラアプリケーションを使用して行われます。4桁は電話番号として機能します。このエミュレータのポートです。







別の方法は、 Android Device Monitorユーティリティから、またはADBを使用してコンソールから呼び出すことです。 これらのすべてのメソッドの顕著なマイナスは、エミュレーターが呼び出しの間デバッガーとの接続を切断することですが、異なるOSバージョンおよび異なる解像度でウィンドウの動作をテストする機能は価値があります。



ダイを見せます



さて、今、最も興味深い部分は私たちのダイを見せることです。 これを行うには、まず、「システム通知」フラグを使用してウィンドウを作成するために、マニフェストに権限のリクエストを追加する必要があります。



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





次に、OnRecieveメソッドを編集し、単純なログエントリを呼び出しまたはウィンドウのクローズに置き換えます。



 Log.debug("Show window: " + phoneNumber); showWindow(context, phoneNumber);// //[...] Log.debug("Close window."); closeWindow();//
      
      





さて、最も興味深いのは、ウィンドウの開閉です。



 private static WindowManager windowManager; private static ViewGroup windowLayout; private void showWindow(Context context, String phone) { windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); WindowManager.LayoutParams params = new WindowManager.LayoutParams( WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, PixelFormat.TRANSLUCENT); params.gravity = Gravity.TOP; windowLayout = (ViewGroup) layoutInflater.inflate(R.layout.info, null); TextView textViewNumber=(TextView) windowLayout.findViewById(R.id.textViewNumber); Button buttonClose=(Button) windowLayout.findViewById(R.id.buttonClose); textViewNumber.setText(phone); buttonClose.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { closeWindow(); } }); windowManager.addView(windowLayout, params); } private void closeWindow() { if (windowLayout !=null){ windowManager.removeView(windowLayout); windowLayout =null; } }
      
      





ウィンドウを表示するために別個のアクティビティを開始するのではなく、手でWindowManagerを介して新しいウィンドウを表示することに注意してください。 なんで? 新しいアクティビティは画面の一般的なスタックに分類されるため、アプリケーションに少なくとも1つの画面があり、呼び出し時に実行されている場合、次のことが発生します。



  1. ネイティブの電話ダイヤラが画面に表示されます
  2. 画面には、アプリケーションのアクティブな画面が表示されます
  3. ダイヤラーの「上のウィンドウ」が画面に表示されます


その結果、ユーザーは自分でダイヤラに切り替えることなく、コールに応答したり拒否したりすることができなくなります。 手動でウィンドウを作成する場合、ポイント2は実行されず、ユーザーは望みどおりに表示されます。電話ダイヤラーとその上のウィンドウです。



落とし穴



残念ながら、すべてが見た目ほどバラ色ではありません。 アンドロイドでよくあることですが、トリッキーな機能の完全な互換性を達成することは困難です。



まず、ユーザーはさまざまな画面サイズ、さまざまな解像度、さまざまなバージョンのAndroidを搭載した携帯電話を持つことができることを理解する必要があります。



第二に、独自の通話プログラムを備えたHTC電話の場合、情報ブロックは表示されません。 彼らのダイヤラーアプリケーションもシステム優先度で表示されているように見えるので、私たちのプレートは「彼らの窓の下」にあるように見えます。 不快ですが、この問題の解決策はまだ見つかりません。 他の一部の電話機のダイヤラーもこの機能と競合する可能性がありますが、これまでのところ、HTCの一部のモデルのみで否定的な経験があります。



GitHubのデモプロジェクト。



All Articles