Prevent USSD dialog and read USSD response?

前端 未结 3 429
孤街浪徒
孤街浪徒 2020-11-29 00:57

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=

相关标签:
3条回答
  • 2020-11-29 01:16

    Use IExtendedNetworkService.aidl

    Create this file in path com\android\internal\telephony

    package com.android.internal.telephony;
    
    /**
     * Interface used to interact with extended MMI/USSD network service.
     */
    interface IExtendedNetworkService {
        /**
         * Set a MMI/USSD command to ExtendedNetworkService for further process.
         * This should be called when a MMI command is placed from panel.
         * @param number the dialed MMI/USSD number.
         */
        void setMmiString(String number);
    
        /**
         * return the specific string which is used to prompt MMI/USSD is running
         */
        CharSequence getMmiRunningText();
    
        /**
         * Get specific message which should be displayed on pop-up dialog.
         * @param text original MMI/USSD message response from framework
         * @return specific user message correspond to text. null stands for no pop-up dialog need to show.
         */
        CharSequence getUserMessage(CharSequence text);
    
        /**
         * Clear pre-set MMI/USSD command.
         * This should be called when user cancel a pre-dialed MMI command.
         */
        void clearMmiString();
    }
    

    Add com.android.ussd.IExtendedNetworkService filter in manifast :

    <?xml version="1.0" encoding="UTF-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
         >
        <application
            android:icon="@drawable/icon"
            android:label="@string/app_name" >
            <service
                android:name=".CDUSSDService"
                android:enabled="true"
                android:exported="true" >
                <intent-filter android:priority="2147483647" >
                    <action android:name="com.android.ussd.IExtendedNetworkService" />
                </intent-filter>
    
        </application>
    
    </manifest>
    

    CDUSSDService.java

    import com.android.internal.telephony.IExtendedNetworkService;
    
    public class CDUSSDService extends Service {
    
        private boolean mActive = false; // we will only activate this
                                            // "USSD listener" when we want it
    
    
        private final IExtendedNetworkService.Stub mBinder = new IExtendedNetworkService.Stub() {
    
            public void clearMmiString() throws RemoteException {
                // Log.d(TAG, "called clear");
            }
    
            public void setMmiString(String number) throws RemoteException {
                clearMmiString();
                Log.d(TAG, "setMmiString:" + number);
                ussdcode = number;
            }
    
            public CharSequence getMmiRunningText() throws RemoteException {
                if (mActive == true) {
                    return null;
                }
                Log.d(TAG, "USSD code running...");
                return "USSD code running...";
            }
    
            public CharSequence getUserMessage(CharSequence text)
                    throws RemoteException {
    
                Intent iBroad = new Intent(getString(R.string.EXTRA_ACTION_USSD));
                iBroad.putExtra(getString(R.string.EXTRA_USSD_MSG), text);
                iBroad.putExtra(getString(R.string.EXTRA_USSD_CODE), ussdcode);
                sendBroadcast(iBroad);
    
                if (mActive == false) {
                    // listener is still inactive, so return whatever we got
                    Log.d(TAG, " seven sky " + text);
    
    
                    return text;
    
                }
    
                // listener is active, so broadcast data and suppress it from
                // default behavior
    
                // build data to send with intent for activity, format URI as per
                // RFC 2396
    
                Uri ussdDataUri = new Uri.Builder()
                        .scheme(getBaseContext().getString(R.string.uri_scheme))
                        .authority(
                                getBaseContext().getString(R.string.uri_authority))
                        .path(getBaseContext().getString(R.string.uri_path))
                        .appendQueryParameter(
                                getBaseContext().getString(R.string.uri_param_name),
                                text.toString()).build();
    
                // if (!hidden)
                sendBroadcast(new Intent(Intent.ACTION_GET_CONTENT, ussdDataUri));
                Log.d(TAG, "" + ussdDataUri.toString());
                mActive = false;
                return null;
            }
        };
    
        @Override
        public IBinder onBind(Intent intent) {
    
            // Log.i(TAG, "called onbind");
    
            // the insert/delete intents will be fired by activity to
            // activate/deactivate listener since service cannot be stopped
    
    
            return mBinder;
        }
    }
    

    Once the device must reboot to run

    0 讨论(0)
  • 2020-11-29 01:30

    It works in Android 2.3, but i'm not completely sure if this can work in a superior version, follow the instructions:

    1. Connect your phone USB to your computer (Debug Mode)
    2. Type adb devices (your phone must be listing)
    3. Type adb shell
    4. Type logcat -v time -b main PhoneUtils:D > output.txt
    5. Now in your phone, send a ussd code example: #123# wait a moment and then in your console press Ctrl + C
    6. Read the output.txt and find this word displayMMIComplete
    0 讨论(0)
  • 2020-11-29 01:40

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

    0 讨论(0)
提交回复
热议问题