A new way to manage USSD dialogs in android
Asked Answered
K

2

31

I've been reading threads about USSD dialogs in here and other forums for a few days. (by USSD I mean operator's notifications with call cost details in it).

I've seen many solutions which apparently worked for lower API levels in android but after lots of tests, figured they don't work anymore or at least I couldn't get them to work.

First I wanted to know if there's any way to detect if a ussd dialog has been shown to the user. so I tried this : Prevent USSD dialog and read USSD response?

but all I could get from logs were somehow related to my app, although I could see them in Eclipse's LogCat but no MMI related logs were captured in my app ! maybe it was working in lower Android versions than mine (4.2.2).

then I decided to use "IExtendedNetworkService" like it was used in the following links and many others :

https://github.com/alaasalman/ussdinterceptor

Using IExtendedNetworkService to get USSD response in Android

How to read USSD messages in android?

Implementing USSD features. Binding a service to the PhoneUtils without restarting the phone on every update

but it was also useless for android 4.2.2 and above.

then I found this link : How to dismiss system dialog in Android?

it seemed promising but I couldn't get it to work even after lots of tests. I thought maybe I was doing something wrong or it was for lower APIs too.

after that I tried many other things like simulating home key and back key and even touching programmatically to hide that notification but none of them worked since they all work under my own activity.

Does anyone know if any of these methods or others work for managing or even detecting USSD messages in android 4.2.2 and above ?

I really appreciate any help, thanks in advance.

Kape answered 21/7, 2014 at 22:29 Comment(6)
Does anyone know anything new about it ?Kape
I have not found anything new. I went down the exact same path that you outlined here. Have you come up with a solution since that time?Peafowl
No, nothing useful :'(Kape
Hello did you got any solution..??Dybbuk
There isn't a way to do this. Android does not provide a USSD API. Any of these hacks are not supported and may break at any time. You're better off finding a completely different way of doing it not using USSD. Really USSD should be considered dead in general- it was a hack for when phones didn't have data, and shouldn't be used in the modern world.Propolis
Any latest developments on this question?Hautesalpes
U
8

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" />

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).

Unlike answered 7/12, 2015 at 11:3 Comment(4)
This should be a commentSweatbox
@HenBoy331 , thanks. I'll check it ASAP & let you know if it works for me.Kape
hi i've tried this one, i managed to get the USSD Response in my apps, but the problem is, the ussd diaglog cant be closed, I'm using Lolipop,Borax
I am on Marshmallow and the USSD dialog can't be closed with performGlobalAction. Seems like the only way is to programmatically click on the USSD dialog buttons.Hinkle
Y
0

Unfortunately no way.

We've been searching for that command is also a solution to this problem, but if it turned out to get information only through the parsing of logs in the phone that does not guarantee 100% of the work on all devices.

As a result, we were able to reach an agreement with mobile operators in our country (we only have 3 mobile operator), and they provided us with the API to obtain the balance of the phone number, but this method only works locally.

Yaws answered 21/10, 2015 at 7:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.