Я планирую создать приложение для Android, которое будет автоматизировать отправку ответов пользователей на USSD-меню. По нажатию кнопки приложение отправит начальный код, а затем остальные входные данные меню.
Например, начальный номер — *143#, за которым следуют 1, 1, 1 и PIN-код пользователя. Я хотел бы иметь возможность автоматизировать эту последовательность ввода, чтобы пользователю не приходилось вводить ее самостоятельно.
Я знаю, что в Android Oreo они реализовали обратный вызов USSD с помощью TelephonyManager, где приложение Android может отправить запрос USSD, а затем прочитать полученный ответ.
В настоящее время я изучаю этот вариант, и это то, что я пробовал до сих пор. Существенно взято из этого вопроса StackOverflow.
interface UssdResultNotifiable {
void notifyUssdResult(String request, String returnMessage, int resultCode);
}
public class MainActivity extends Activity implements UssdResultNotifiable {
USSDSessionHandler hdl;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void onUssdSend(View view) {
hdl = new USSDSessionHandler(MainActivity.this, MainActivity.this);
hdl.doSession(((EditText) this.findViewById(R.id.ussdText)).getText().toString());
}
@Override
public void notifyUssdResult(final String request, final String returnMessage, final int resultCode) {
this.runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, "Request was " + request + "\n response is "
+ returnMessage + "\n result code is " + resultCode, Toast.LENGTH_LONG).show();
Log.e(TAG, "ussd result hit! Response is = " + returnMessage);
hdl.doSession("1");
}
});
}
}
class USSDSessionHandler {
TelephonyManager tm;
private UssdResultNotifiable client;
private Method handleUssdRequest;
private Object iTelephony;
USSDSessionHandler(Context parent, UssdResultNotifiable client) {
this.client = client;
this.tm = (TelephonyManager) parent.getSystemService(Context.TELEPHONY_SERVICE);
try {
this.getUssdRequestMethod();
} catch (Exception ex) {
//log
}
}
private void getUssdRequestMethod() throws ClassNotFoundException, NoSuchMethodException,
InvocationTargetException, IllegalAccessException {
if (tm != null) {
Class telephonyManagerClass = Class.forName(tm.getClass().getName());
if (telephonyManagerClass != null) {
Method getITelephony = telephonyManagerClass.getDeclaredMethod("getITelephony");
getITelephony.setAccessible(true);
this.iTelephony = getITelephony.invoke(tm); // Get the internal ITelephony object
Method[] methodList = iTelephony.getClass().getMethods();
this.handleUssdRequest = null;
for (Method _m : methodList)
if (_m.getName().equals("handleUssdRequest")) {
handleUssdRequest = _m;
break;
}
}
}
}
@android.support.annotation.RequiresApi(api = Build.VERSION_CODES.N)
public void doSession(String ussdRequest) {
try {
if (handleUssdRequest != null) {
handleUssdRequest.setAccessible(true);
handleUssdRequest.invoke(iTelephony, SubscriptionManager.getDefaultSubscriptionId(), ussdRequest, new ResultReceiver(new Handler()) {
@Override
protected void onReceiveResult(int resultCode, Bundle ussdResponse) {
Object p = ussdResponse.getParcelable("USSD_RESPONSE");
if (p != null) {
Method[] methodList = p.getClass().getMethods();
for(Method m : methodList){
Log.e(TAG, "onReceiveResult: " + m.getName());
}
try {
CharSequence returnMessage = (CharSequence) p.getClass().getMethod("getReturnMessage").invoke(p);
CharSequence request = (CharSequence) p.getClass().getMethod("getUssdRequest").invoke(p);
USSDSessionHandler.this.client.notifyUssdResult("" + request, "" + returnMessage, resultCode); //they could be null
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
});
}
} catch (IllegalAccessException | InvocationTargetException e1) {
e1.printStackTrace();
}
}
}
Вы получаете приложение, которое запрашивает ввод USSD для пользователя, и после нажатия кнопки «Отправить» ответ USSD отображается с помощью Toast в функции notifyUssdResult
. В той же функции я отправляю следующий вход в моей последовательности, который равен «1». Могу ли я еще раз отправить ответ на USSD, а USSD принимает его на вход и переходит в следующее меню.
Однако, как только я отправляю ответ, на моем устройстве появляется меню USSD, и я не могу продолжить. Я не могу перемещаться по USSD-меню только через свое приложение, так как USSD-меню мешает экрану и не исчезает.
Есть ли образцы, которым я могу следовать?