📜 ⬆️ ⬇️

Simple USSD request in Android 4.0+

In Android, there is still no API for USSD requests. The bug has been hanging for 6 years !
I found different ways to create and retrieve information from USSD requests, but in the end none of them arranged it.
Then I found references to the fact that with the help of the updated services in Android 4.0, the specials. features you can easily get the contents of the windows and so get the text from the window and the result of the USSD request. I tried - it turns out great! Without rebooting and securely.

Submit request

First, you need to send the USSD request itself. It is quite simple:

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

To get permission to work with the phone, you need to get permission, for this we register in Android.Manifest.xml:
')
 <uses-permission android:name="android.permission.CALL_PHONE" /> 

OK, the request is sent from the program, now you have to work hard to get its text.

Accessibility service

To work with specials. capabilities need to export our service. To do this, add to 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> 

Instead of USSDService write the name of your class.

I took the class itself almost unchanged from here .

In order not to get too much, change the method 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); } 

You will also need an additional filter in the onAccessibilityEvent method:

 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); } } 

The performGlobalAction method (GLOBAL_ACTION_BACK) requires Android 4.1+, if you don’t use it, you can fit in 4.0. It closes the window immediately after an AlertDialog appears, so the window will not remain to hang.
For simplicity, I have already added the sendBroadcast method to send the received message further.
To get the message, add the following methods to the required class:

 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 is your procedure that does something with the received text.

For BroadcastReceiver to work, you need to add some code to onCreate () or a similar method of your class:

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

And this is in onPause () or similar:

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

That's all! As you can see, simple and reliable.

Underwater rocks

There may be problems with working in the background: for example, if the screen is locked, then the AccessibilityService will not work at all - you need to wake the device. In the unlocked state, the request will always come to the fore, which is also not convenient.

AccessibilityService will listen constantly, even when the user himself dials the USSD code or, even worse, if com.android.phone throws an AlertDialog. So it is necessary either to enhance the filters (for example, to parse only if there is a certain sequence in the message), or to use the flag to process events only if your application makes a USSD request.

And do not forget to customize the settings. opportunities to activate your application, by the way for this, it would also be nice to add a check%)

Alternatives:
habrahabr.ru/post/130717 - takes the answer from the logs. It is inconvenient that in order to suppress the window, it is necessary to resort to hacks, and to do this through the AccessibilityService is cleaner and simpler.
github.com/alaasalman/ussdinterceptor is still the old way. Uses undocumented class. According to reviews, often falls off and requires a reboot.

Source: https://habr.com/ru/post/234425/


All Articles