I'm wanting to write a widget displays the users' prepay balance, remaining data etc.
I'm thinking of automatically calling the USSD code which returns this data (will have to have a regex for each network), at intervals (not often, to save battery). This would have to be done in the background. I have an app at the moment which runs the ussd code and returns the result, so I think this should be possible - but I'm not sure how it would be done in the background.
I've seen the intents for Calling a number, but I'm not sure how to get the result, and I'm also thinking that that intent would cause the call screen to come up into the foreground?
The other option is to get the data by screen-scraping the result from the carrier's website/maybe wap site but that would result in data charges for the user, so I would prefer a solution using the USSD code.
Thanks in advance for any help - only started wor开发者_运维知识库king on understanding android today so got quite a lot to learn :)
USSD is not yet supported on Android. There is a feature request for it: http://code.google.com/p/android/issues/detail?id=1285
You can send a USSD code by below code and also you need to add permission (This should be a run time permission after Marshmallow update)
<uses-permission android:name="android.permission.CALL_PHONE" />
String code = "*" + Uri.encode("#") + 456 + Uri.encode("#");
startActivity(new Intent("android.intent.action.CALL", Uri.parse("tel:" + code)));
And you can read USSD codes by AccessibilityService
Here is the example:
Service:
public class USSDService extends AccessibilityService {
private static final String TAG = "USSDService";
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
Log.d(TAG, "onAccessibilityEvent");
String text = event.getText().toString();
Log.d(TAG, text);
}
}
@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;
info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
setServiceInfo(info);
}
}
AndroidManifest.xml :
<service android:name=".services.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/config_service" /> // created below
</service>
res/xml/config_service.xml :
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFeedbackType="feedbackSpoken"
android:accessibilityFlags="flagDefault"
android:canRetrieveWindowContent="true"
android:description="@string/accessibility_description"
android:notificationTimeout="100"
android:packageNames="com.cootf.sims"
android:settingsActivity="com.example.android.accessibility.ServiceSettingsActivity" />
Run the code --> Enable the accessibility through Settings --> Accessibility --> [Your app name] --> Enable. Job Done!
You can use the following code to call the ussd codes on android phone to check the balance and etc......
String s=calledittext.getText.toString();//calledittext is editText on the
//screen from which can get the number
if((s.startsWith("*"))&&(s.endsWith("#"))){
//if true then it is a USSD call----
callstring=s.substring(0, s.length()-1);
callstring=callstring+Uri.encode("#");
Log.d("CALL TYPE---------->", "USSD CALL");
}else{
callstring=s;
Log.d("CALL TYPE---------->", "Not a USSD CALL");
//Intent i=new Intent(android.content.Intent.ACTION_CALL,Uri.parse("tel:"+output.getText().toString()));
//startActivity(i);
}
Intent i=new Intent(android.content.Intent.ACTION_CALL,Uri.parse("tel:"+callstring));
startActivity(i);
Android O(API level 26) adds a sendUssdRequest
method to the TelephonyManager
, which also includes a callback for getting the result for the request.
The docs.
I'm not completely sure but I think USSD is not yet supported on android, however you can try this workaround:
startActivity(new Intent("android.intent.action.CALL",Uri.parse("tel:*123" + Uri.encode("#")));
USSD call interuptn is not yet supported n Android
Android 8 (Oreo) and above now supports this. Here is the code. The TelephonyManager class is used to achieve this.
public void dialUssdToGetPhoneNumber(String ussdCode, int sim) {
if (ussdCode.equalsIgnoreCase("")) return;
if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.CALL_PHONE}, 234);
return;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
TelephonyManager manager = (TelephonyManager) getActivity().getSystemService(TELEPHONY_SERVICE);
TelephonyManager manager2 = manager.createForSubscriptionId(2);
TelephonyManager managerMain = (sim == 0) ? manager : manager2;
managerMain.sendUssdRequest(ussdCode, new TelephonyManager.UssdResponseCallback() {
@Override
public void onReceiveUssdResponse(TelephonyManager telephonyManager, String request, CharSequence response) {
super.onReceiveUssdResponse(telephonyManager, request, response);
Log.e("TAG", "onReceiveUssdResponse: Ussd Response = " + response.toString().trim() );
}
@Override
public void onReceiveUssdResponseFailed(TelephonyManager telephonyManager, String request, int failureCode) {
super.onReceiveUssdResponseFailed(telephonyManager, request, failureCode);
Log.e("TAG", "onReceiveUssdResponseFailed: " + "" + failureCode + request);
}
}, new Handler());
}
}
For anyone still looking for a solution to this, there's a platform called AutoUssd (https://autoussd.com) which allows you to do exactly this. It also supports multi-step USSD sessions...
精彩评论