Android 4.0以降のシンプルなUSSDリクエスト

AndroidにはUSSDリクエスト用のAPIはまだありません。 バグは6年間ぶら下がっています!

USSDリクエストから情報を作成および取得するさまざまな方法を見つけましたが、最終的にはうまくいきませんでした。

それから、Android 4.0で更新された特別なサービスの助けを借りて言及していることがわかりました。 ウィンドウの内容を簡単に取得できるため、ウィンドウからテキストとUSSDリクエストの結果を取得できます。 私はそれを試しました-それはうまくいくことが判明しました! 再起動せず、信頼できます。



提出依頼


最初に、USSD要求自体を送信します。 とても簡単です:



String encodedHash = Uri.encode("#"); String ussd = "*100" + encodedHash; startActivityForResult(new Intent("android.intent.action.CALL", Uri.parse("tel:" + ussd)), 1);
      
      





電話での作業許可を取得するには、許可を取得する必要があります。これを行うには、Android.Manifest.xmlに登録します。



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





OK、リクエストはプログラムから送信されます。テキストを取得するには一生懸命作業する必要があります。



アクセシビリティサービス


特別に働くために。 機会は私たちのサービスをエクスポートする必要があります。 これを行うには、Android.Manifest.xmlに追加します。



 <service android:name=".USSDService" android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE" > <intent-filter> <action android:name="android.accessibilityservice.AccessibilityService" /> </intent-filter> </service>
      
      





USSDServiceの代わりに、クラスの名前を記述します。



ここからクラス自体はほとんど変わりませんでし



取得しすぎないように、onServiceConnectedメソッドを変更します。



 protected void onServiceConnected() { super.onServiceConnected(); Log.v(TAG, "onServiceConnected"); AccessibilityServiceInfo info = new AccessibilityServiceInfo(); info.flags = AccessibilityServiceInfo.DEFAULT; info.packageNames = new String[] {"com.android.phone"}; info.eventTypes = AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED; info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC; setServiceInfo(info); }
      
      





また、onAccessibilityEventメソッドに追加のフィルターが必要です。



 public void onAccessibilityEvent(AccessibilityEvent event) { String text = getEventText(event); Log.v(TAG, String.format( "onAccessibilityEvent: [type] %s [class] %s [package] %s [time] %s [text] %s", getEventType(event), event.getClassName(), event.getPackageName(), event.getEventTime(), getEventText(event))); if (event.getClassName().equals("android.app.AlertDialog")) { performGlobalAction(GLOBAL_ACTION_BACK); Log.i(TAG, text); Intent intent = new Intent("REFRESH"); intent.putExtra("message", text); sendBroadcast(intent); } }
      
      





performGlobalAction(GLOBAL_ACTION_BACK)メソッドにはAndroid 4.1以降が必要です。使用しない場合は4.0のままにしておくことができます。 AlertDialogが表示された直後にウィンドウが閉じられるため、ウィンドウはハングしたままになりません。

簡単にするために、受信メッセージをさらに送信するためにsendBroadcastメソッドをすでに追加しています。

メッセージを受信するには、次のメソッドを目的のクラスに追加します。



 private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String message = intent.getStringExtra("message"); Log.i("receiver", "Got message: " + message); showText(message); } };
      
      





showTextは、受信したテキストで何かを行うプロシージャです。



BroadcastReceiverが機能するには、onCreate()またはクラスの同様のメソッドにいくつかのコードを追加する必要があります。



 IntentFilter mFilter = new IntentFilter("REFRESH"); mContext.registerReceiver(mMessageReceiver, mFilter); isRegistered = true;
      
      





そして、これはonPause()などにあります。



 try { if (isRegistered) { mContext.unregisterReceiver(mMessageReceiver); isRegistered = false; } } catch (Exception e) { e.printStackTrace(); }
      
      





以上です! ご覧のとおり、シンプルで信頼性が高いです。



落とし穴


バックグラウンドでの作業に問題がある可能性があります。たとえば、画面がロックされている場合、AccessibilityServiceはまったく機能しません。デバイスをウェイクアップする必要があります。 ロック解除状態では、リクエストは常に前面に表示されますが、これも便利ではありません。



AccessibilityServiceは、ユーザーが自分でUSSDコードをダイヤルした場合や、さらに悪いことにcom.android.phoneがAlertDialogをスローした場合でも、常にリッスンします。 そのため、フィルターを強化する(たとえば、メッセージに特定のシーケンスがある場合のみ解析する)か、アプリケーションがUSSD要求を行った場合にのみフラグを使用してイベントを処理する必要があります。



そして、特別な設定で忘れないでください。 ちなみに、このために、a%チェックを追加することも良いでしょう)



代替案:

habrahabr.ru/post/130717-ログから回答を取得します。 ウィンドウを非表示にするためにハッキングに頼らなければならず、AccessibilityServiceを介してこれを行うことはよりクリーンで簡単です。

github.com/alaasalman/ussdinterceptorはまだ古い方法です。 文書化されていないクラスを使用します。 レビューによると、それはしばしば落ち、再起動が必要です。



All Articles