Androidでメッセージと通話を監視する

私が開発しているAndroidプロジェクトでは、着信および発信の呼び出しとメッセージを監視することが必要になりました。 ドキュメントと利用可能な本を読むことは有益でしたが、残念なことに、1つの問題の各部分には実装に異なるアプローチが必要であるため、タスクが完全に些細なものではないことに気付きました。 一般に、多くの本や記事は常に、たとえば受信メッセージの処理など、より簡単な例を挙げようとしますが、実装がより複雑な場合は送信ワードについて説明します。 おそらくこれが私の偏見ですが、これに注意を向けたのはこれが初めてではありません

私はすべてをまとめて、この問題の解決策を見つけようとして口が痛い人と共有することにしました。 私自身は勉強しているので、最適性のふりをしません





受信トレイの監視





おそらく、この部分の実装は最も単純で簡単です。 アプリケーションマニフェストでは、メッセージの受信を処理する許可を与えます



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







そして、受信メッセージのイベントによってトリガーされるReceiverを登録します



 <receiver android:name="MessageReceiver" android:enabled="true"> <intent-filter> <action android:name="android.provider.Telephony.SMS_RECEIVED"/> </intent-filter> </receiver>
      
      







コード例からわかるように、メッセージを受信すると、制御はMessageReceiverレシーバーに転送されます。



サンプル実装:



 public class MessageReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { Bundle bundle = intent.getExtras(); if (bundle != null) { Object[] pdus = (Object[]) bundle.get("pdus"); SmsMessage[] msgs = new SmsMessage[pdus.length]; ArrayList<String> numbers = new ArrayList<String>(); ArrayList<String> messages = new ArrayList<String>(); for (int i=0; i<msgs.length; i++){ //     msgs[i] = SmsMessage.createFromPdu((byte[])pdus[i]); numbers.add(msgs[i].getOriginatingAddress()); //   messages.add(msgs[i].getMessageBody().toString());//   } if (messages.size() > 0){ // -   } } } }
      
      







発信メッセージの監視





残念ながら、送信メッセージの使用は受信トレイほど簡単ではありません。 Telephony APIは、個別のアウトバウンドイベントを提供しません。 私にとって、これはかなり洗練された製品であるAndroidでは非常に奇妙に見えます。 それにもかかわらず、まだ解決策があります。



アプリケーションマニフェストで、メッセージの読み取りを許可します。



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







次に、メッセージベース変更ハンドラーを作成して登録する必要があります。 ここでは、着信メッセージと発信メッセージの処理を組み合わせることができますが、何らかの方法で着信メッセージを使用すると、すべてがはるかに簡単になります。 送信メッセージを処理する場合、同じメッセージを送信するときにハンドラーが複数回呼び出される可能性があるという事実を考慮する必要があります。 すべてのメッセージのハッシュテーブルを作成して、データベースで処理中のメッセージがあるかどうかを確認することをお勧めします。 以下のコードは、メッセージIDによるプリミティブチェックを示しています



 private static final String CONTENT_SMS = "content://sms/"; private static long id = 0; //     ContentResolver contentResolver = getBaseContext().getContentResolver(); contentResolver.registerContentObserver(Uri.parse(CONTENT_SMS),true, new OutgoingSmsObserver(new Handler())); private class OutgoingSmsObserver extends ContentObserver { @Override public void onChange(boolean selfChange) { super.onChange(selfChange); Uri uriSMSURI = Uri.parse(CONTENT_SMS); Cursor cur = getContentResolver().query(uriSMSURI, null, null,null, null); cur.moveToNext(); String protocol = cur.getString(cur.getColumnIndex("protocol")); if(protocol == null){ long messageId = cur.getLong(cur.getColumnIndex("_id")); //       - if (messageId != id){ id = messageId; int threadId = cur.getInt(cur.getColumnIndex("thread_id")); Cursor c = getContentResolver().query(Uri.parse("content://sms/outbox/" + threadId), null, null, null, null); c.moveToNext(); //   String address = cur.getString(cur.getColumnIndex("address")); //   String body= cur.getString(cur.getColumnIndex("body")); // -   } } } }
      
      







通話監視





Androidには、アクションandroid.intent.action.PHONE_STATEを介して電話のステータスを監視する機能がありますが、発信コール中に加入者の番号を取得するのにまだ問題があったため、2つのアクションの受信者を登録する必要がありました。



アプリケーションマニフェストでは、電話の状態を読み取り、発信通話を処理する許可を与えます。



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







そして、受信メッセージのイベントによってトリガーされるReceiverを登録します



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







サンプル実装:



 String phoneNumber = ""; public class CallReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { if (intent.getAction().equals("android.intent.action.NEW_OUTGOING_CALL")) { //   phoneNumber = intent.getExtras().getString("android.intent.extra.PHONE_NUMBER"); } else if (intent.getAction().equals("android.intent.action.PHONE_STATE")){ String phone_state = intent.getStringExtra(TelephonyManager.EXTRA_STATE); if (phone_state.equals(TelephonyManager.EXTRA_STATE_RINGING)) { // ,    phoneNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER); } else if (phone_state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)){ //     (  / ) } else if (phone_state.equals(TelephonyManager.EXTRA_STATE_IDLE)){ //    .      ,         } } } }
      
      







冒頭で説明した問題を要約すると、やはり、未完成のAndroid APIの感覚を残していなかったと言えます。 着信メッセージは非常に簡単に傍受されますが、発信については言えません。 同じことが通話についても言えます。 もちろん、メッセージに1つのソリューションを使用できますが、受信トレイが非常に単純な場合、送信メッセージにそのような単純性がないのはなぜですか?



All Articles