Prevent USSD dialog and read USSD response?
Solution 1
It is possible using accessibility service. First create a service class:
public class USSDService extends AccessibilityService {
public static String TAG = USSDService.class.getSimpleName();
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
Log.d(TAG, "onAccessibilityEvent");
AccessibilityNodeInfo source = event.getSource();
/* if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED && !event.getClassName().equals("android.app.AlertDialog")) { // android.app.AlertDialog is the standard but not for all phones */
if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED && !String.valueOf(event.getClassName()).contains("AlertDialog")) {
return;
}
if(event.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED && (source == null || !source.getClassName().equals("android.widget.TextView"))) {
return;
}
if(event.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED && TextUtils.isEmpty(source.getText())) {
return;
}
List<CharSequence> eventText;
if(event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
eventText = event.getText();
} else {
eventText = Collections.singletonList(source.getText());
}
String text = processUSSDText(eventText);
if( TextUtils.isEmpty(text) ) return;
// Close dialog
performGlobalAction(GLOBAL_ACTION_BACK); // This works on 4.1+ only
Log.d(TAG, text);
// Handle USSD response here
}
private String processUSSDText(List<CharSequence> eventText) {
for (CharSequence s : eventText) {
String text = String.valueOf(s);
// Return text if text is the expected ussd response
if( true ) {
return text;
}
}
return null;
}
@Override
public void onInterrupt() {
}
@Override
protected void onServiceConnected() {
super.onServiceConnected();
Log.d(TAG, "onServiceConnected");
AccessibilityServiceInfo info = new AccessibilityServiceInfo();
info.flags = AccessibilityServiceInfo.DEFAULT;
info.packageNames = new String[]{"com.android.phone"};
info.eventTypes = AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED | AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;
info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
setServiceInfo(info);
}
}
Declare it in Android manifest
<service android:name=".USSDService"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data android:name="android.accessibilityservice"
android:resource="@xml/ussd_service" />
</service>
Create a xml file that describes the accessibility service called ussd_service
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeWindowStateChanged|typeWindowContentChanged"
android:accessibilityFeedbackType="feedbackGeneric"
android:accessibilityFlags="flagDefault"
android:canRetrieveWindowContent="true"
android:description="@string/accessibility_service_description"
android:notificationTimeout="0"
android:packageNames="com.android.phone" />
That's it. Once app is installed, you have to enable the service in Accessibility Settings (Setting->Accessibility Setting -> YourAppName).
Solution described here and here (russian).
Solution 2
It works in Android 2.3, but i'm not completely sure if this can work in a superior version, follow the instructions:
- Connect your phone USB to your computer (Debug Mode)
- Type
adb devices
(your phone must be listing) - Type
adb shell
- Type
logcat -v time -b main PhoneUtils:D > output.txt
- Now in your phone, send a ussd code example: #123# wait a moment and then in your console press Ctrl + C
- Read the
output.txt
and find this worddisplayMMIComplete
Related videos on Youtube
Jack
Updated on July 09, 2022Comments
-
Jack almost 2 years
i did many research about ussd but I can't read USSD respone and how can I prevent ussd dialog like this application.
https://play.google.com/store/apps/details?id=com.iba.ussdchecker&hl=en
i install this https://github.com/alaasalman/ussdinterceptor restart my phone (S2 android 4.0.3), send ussd code but nothing happen, someone tell me that I have to read the log, but how can i do that.
i try these code to read USSD from log
USSD.java
package com.example.ussd; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.Calendar; import java.util.Date; import java.text.ParseException; import java.text.SimpleDateFormat; import android.util.Log; public class USSD { private static String startmsg = "displayMMIComplete"; // start msg to look // for private static String endmsg = "MMI code has finished running"; // stop msg private static String trimmsg = "- using text from MMI message: '"; // a msg // to // remove // from // the // text private long before = 3000; // delay (ms) before creation of the class // before a msg (USDD) is valid (use timestamp) private long after = 3000; // delay (ms) after creation of the class that a // msg (USDD) is valid (wait after ms) private String msg = ""; // the USSD message private boolean found = false; private long t = -1; // timestamp of the found log public USSD() { this(3000, 3000); } // USSD in log : example public USSD(long before_creation, long after_creation) { before = before_creation; after = after_creation; long timestamp = System.currentTimeMillis(); // creation of the class // --> look for the USSD // msg in the logs Log.d("USSDClass", "Class creation - timestamp: " + String.valueOf(timestamp)); try { // sample code taken from alogcat ... Process logcatProc = Runtime.getRuntime().exec( "logcat -v time -b main PhoneUtils:D"); // get PhoneUtils // debug log with // time information BufferedReader mReader = new BufferedReader(new InputStreamReader( logcatProc.getInputStream()), 1024); String line = ""; boolean tostop = false; long stop = timestamp + after; // to stop the while after "after" ms while (((line = mReader.readLine()) != null) && (System.currentTimeMillis() < stop) && (tostop == false)) { if (line.length() > 19) // the line should be at least with a // length of a timestamp (19) ! { if (line.contains(startmsg)) // check if it is a USSD msg { // log example : // "12-10 20:36:39.321 D/PhoneUtils( 178): displayMMIComplete: state=COMPLETE" t = extracttimestamp(line); // extract the timestamp of // thie msg Log.d("USSDClass", "Found line at timestamp : " + String.valueOf(t)); if (t >= timestamp - before) found = true; // start of an USDD is found & is // recent ! } else if (found) { // log example : // "12-10 20:36:39.321 D/PhoneUtils( 178): displayMMIComplete: state=COMPLETE" if (line.contains(endmsg)) tostop = true; else { // log example : // "12-10 20:36:39.321 D/PhoneUtils( 178): - using text from MMI message: 'Your USSD message with one or several lines" Log.d("USSDClass", "Line content : " + line); String[] v = line.split("\\): "); // doesn't need // log // information // --> split // with "): " // separator if (v.length > 1) msg += v[1].replace(trimmsg, "").trim() + "\n"; } } } } } catch (IOException e) { Log.d("USSDClass", "Exception:" + e.toString()); } } public boolean IsFound() { return found; } public String getMsg() { return msg; } // extract timestamp from a log line with format // "MM-dd HH:mm:ss.ms Level/App:msg" Example : 12-10 20:36:39.321 // Note : known bug : happy new year check will not work !!! private long extracttimestamp(String line) { long timestamp = -1; // default value if no timestamp is found String[] v = line.split(" "); if (v.length > 1) // check if there is space { Calendar C = Calendar.getInstance(); int y = C.get(Calendar.YEAR); String txt = v[0] + "-" + y + " " + v[1]; // transform in format // "MM-dd-yyyy HH:mm:ss" SimpleDateFormat formatter = new SimpleDateFormat( "MM-dd-yyyy HH:mm:ss"); try { Date tmp = formatter.parse(txt); timestamp = tmp.getTime(); String[] ms = v[1].split("."); // get ms if (ms.length > 1) timestamp += Integer.getInteger(ms[1]); } catch (ParseException e) { Log.d("USSDClass", "USDD.extractimestamp exception:" + e.toString()); } } return timestamp; } }
UssdActivity.java
package com.example.ussd; import android.app.Activity; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.AutoCompleteTextView; import android.widget.Button; import android.widget.TextView; public class UssdActivity extends Activity implements OnClickListener { /** Called when the activity is first created. */ private TextView view; private AutoCompleteTextView number; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Button button = (Button) findViewById(R.id.button1); button.setOnClickListener(this); this.view = (TextView) findViewById(R.id.Text2); this.number = (AutoCompleteTextView) findViewById(R.id.Text1); } @Override public void onClick(View arg0) { String encodedHash = Uri.encode("#"); call("*" + number.getText() + encodedHash); this.view.setText(""); } protected void call(String phoneNumber) { try { startActivityForResult( new Intent("android.intent.action.CALL", Uri.parse("tel:" + phoneNumber)), 1); } catch (Exception eExcept) { this.view.append("\n\n " + "\n" + eExcept.toString()); } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { USSD ussd = new USSD(4000, 4000); if (ussd.IsFound()) this.view.append("\n test" + ussd.getMsg()); else this.view.append("" + R.string.error_ussd_msg); } }
and output is something like this:
com.sec.android.app.callsetting.allcalls:com.sec.android.callsetting.allcalls.AllCallsProvider Terminated ALSA PLAYBACK device hifi
-
Wilson almost 10 yearsHave you got the solution ?
-
Jack almost 10 yearsnot yet, does you have any idea for this problem?
-
Wilson almost 10 yearsNo i am just trying and working around but no +ve progress.
-
Jack almost 10 yearsplease response in this topic whenever you found solution :)
-
Wilson almost 10 yearsYa sure I'll do Jack.
-
hamidfzm over 9 yearsLook at this page: code.google.com/p/android/issues/detail?id=1285
-
Jack over 9 years@HamidFzM in android > 4.2, we make USSD dial like this
-
Gh0sT over 9 yearsCheck out the answer here stackoverflow.com/questions/6515906/…
-
Harry Sharma over 8 yearsHave you find the solution..??
-
-
Umesh Isran over 8 yearsThis works perfect on lollipop, but no success on 4.2.2 and 4.0.3.?
-
Umesh Isran over 8 yearsI gues this problem is device specific. The above code works for Samsung Duos(4.0.4), One plus one(5.1.1), Xiomi mi(4.4), but fails to work on Micromax A177(4.2.2), Micromax A905(4.0.4), Lenovo (4.2.2). Please if you can check the same and look for a solution..
-
HenBoy331 over 8 yearsYes on some devices it does not work. On some devices it is com.android.phone.UssdAlertActivity instead of android.app.AlertDialog
-
HenBoy331 over 8 yearsPlease check my new answer. I made it work from my side. Please check!
-
HenBoy331 over 8 yearsVote up if I helped ;)
-
Umesh Isran over 8 years@henboy - Did u find a solution to make this work on all devices.?
-
Umesh Isran over 8 years@henboy - the above code is not working for me:( Plz if u can u pass me the code at [email protected]
-
HenBoy331 over 8 yearsI met also some case where it does not work. I manage to make it work on those phones(Htc One, Htc One X). Please try my updated answer.
-
Umesh Isran over 8 years@henboy : I tried your updated answer, still no luck. event.getText() returns "Phone" as value for micromax and lenovo device..
-
Avanish Singh about 8 yearsHey guys.. i am not geting text of AlertDialog box using event.getText(). i got "PHONE" text.. help any one ..
-
Alex over 7 yearsOn all devices / Android versions or is there any limitation ?
-
Tefa almost 7 yearsWhere to create xml file?
-
HenBoy331 almost 7 yearsin res/xml folder
-
Bloomberg58 over 6 years@HenBoy331.... Hello. I tried it...It did not worked as expected...In
Log.d
, I getonAccessibilityEvent
... I never getLog.d(TAG, text);
I thought I'd get the content of the dialog box of ANY popup... But it seems I do not get intoif (event.getClassName().equals("android.app.AlertDialog"))
of the original tutorial -
sma6871 about 6 years@Alex This would only be possible in an Android version earlier than 4.2.2. In 4.2.2 the IExtendedNetworkService seems to have been removed by Google due to security risk. See issue posted at Google – code.google.com/p/android/issues/detail?id=57120 android.googlesource.com/platform/packages/apps/Phone/+/…
-
HendraWD almost 6 yearsIf you are targetting Oreo and up, you can check here developer.android.com/reference/android/telephony/…
-
davkutalek about 4 years@HendraWD That API only works for USSD sessions that do not require any steps
-
Hashem Alhariry almost 4 yearshow to call the service ? can you send github link
-
cgb_pandey almost 4 years@HashemKhaled, see an example here : umeshisran4android.blogspot.com/2015/11/…