我試圖實現應用程序以在android上發送,接收和解析USSD代碼。到目前爲止,我使用http://commandus.com/blog/?p=58上的代碼來獲得此功能。爲了使服務起作用,需要重新啓動手機。這在用戶第一次安裝應用程序時不會出現問題,但是我在模擬器上進行測試時發現,即使這些服務沒有任何新增功能,手機也需要在每次更新時重新啓動。 什麼,我想知道的是以下幾點:實施USSD功能。將服務綁定到PhoneUtils而不必在每次更新時重新啓動手機
- 那裏可能離開讓PhoneUtils綁定到我的服務,而無需重新啓動?至少在更新時間?
- 如果沒有辦法這樣做,我正在考慮創建2個應用程序,一個是用戶將與之交互的普通應用程序,另一個是包含我的服務的單獨應用程序。在這種情況下,如果用戶需要任何ussd功能,則會在第一次運行時提示用戶安裝第二個應用程序。我很擔心,但這對用戶來說很煩人。你認爲什麼是解決這種方法的最佳方法?
作爲參考,我已經包含了我用於服務的代碼,因爲界面部分不同於在原始網站上發佈的代碼。
接口:
* This file is auto-generated. DO NOT MODIFY.
package com.android.internal.telephony;
/**
* Interface used to interact with extended MMI/USSD network service.
*/
public interface IExtendedNetworkService extends android.os.IInterface {
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements
com.android.internal.telephony.IExtendedNetworkService {
private static final java.lang.String DESCRIPTOR = "com.android.internal.telephony.IExtendedNetworkService";
/** Construct the stub at attach it to the interface. */
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an
* com.android.internal.telephony.IExtendedNetworkService interface,
* generating a proxy if needed.
*/
public static com.android.internal.telephony.IExtendedNetworkService asInterface(
android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = (android.os.IInterface) obj
.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.android.internal.telephony.IExtendedNetworkService))) {
return ((com.android.internal.telephony.IExtendedNetworkService) iin);
}
return new com.android.internal.telephony.IExtendedNetworkService.Stub.Proxy(
obj);
}
public android.os.IBinder asBinder() {
return this;
}
@Override
public boolean onTransact(int code, android.os.Parcel data,
android.os.Parcel reply, int flags)
throws android.os.RemoteException {
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_setMmiString: {
data.enforceInterface(DESCRIPTOR);
java.lang.String _arg0;
_arg0 = data.readString();
this.setMmiString(_arg0);
reply.writeNoException();
return true;
}
case TRANSACTION_getMmiRunningText: {
data.enforceInterface(DESCRIPTOR);
java.lang.CharSequence _result = this.getMmiRunningText();
reply.writeNoException();
if ((_result != null)) {
reply.writeInt(1);
android.text.TextUtils
.writeToParcel(
_result,
reply,
android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
} else {
reply.writeInt(0);
}
return true;
}
case TRANSACTION_getUserMessage: {
data.enforceInterface(DESCRIPTOR);
java.lang.CharSequence _arg0;
if ((0 != data.readInt())) {
_arg0 = android.text.TextUtils.CHAR_SEQUENCE_CREATOR
.createFromParcel(data);
} else {
_arg0 = null;
}
java.lang.CharSequence _result = this.getUserMessage(_arg0);
reply.writeNoException();
if ((_result != null)) {
reply.writeInt(1);
android.text.TextUtils
.writeToParcel(
_result,
reply,
android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
} else {
reply.writeInt(0);
}
return true;
}
case TRANSACTION_clearMmiString: {
data.enforceInterface(DESCRIPTOR);
this.clearMmiString();
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements
com.android.internal.telephony.IExtendedNetworkService {
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
public android.os.IBinder asBinder() {
return mRemote;
}
public java.lang.String getInterfaceDescriptor() {
return DESCRIPTOR;
}
/**
* 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.
*/
public void setMmiString(java.lang.String number)
throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeString(number);
mRemote.transact(Stub.TRANSACTION_setMmiString, _data,
_reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
/**
* return the specific string which is used to prompt MMI/USSD is
* running
*/
public java.lang.CharSequence getMmiRunningText()
throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.lang.CharSequence _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getMmiRunningText, _data,
_reply, 0);
_reply.readException();
if ((0 != _reply.readInt())) {
_result = android.text.TextUtils.CHAR_SEQUENCE_CREATOR
.createFromParcel(_reply);
} else {
_result = null;
}
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
/**
* 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.
*/
public java.lang.CharSequence getUserMessage(
java.lang.CharSequence text)
throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.lang.CharSequence _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
if ((text != null)) {
_data.writeInt(1);
android.text.TextUtils.writeToParcel(text, _data, 0);
} else {
_data.writeInt(0);
}
mRemote.transact(Stub.TRANSACTION_getUserMessage, _data,
_reply, 0);
_reply.readException();
if ((0 != _reply.readInt())) {
_result = android.text.TextUtils.CHAR_SEQUENCE_CREATOR
.createFromParcel(_reply);
} else {
_result = null;
}
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
/**
* Clear pre-set MMI/USSD command. This should be called when user
* cancel a pre-dialed MMI command.
*/
public void clearMmiString() throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_clearMmiString, _data,
_reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
}
static final int TRANSACTION_setMmiString = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_getMmiRunningText = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
static final int TRANSACTION_getUserMessage = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
static final int TRANSACTION_clearMmiString = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);
}
/**
* 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.
*/
public void setMmiString(java.lang.String number)
throws android.os.RemoteException;
/**
* return the specific string which is used to prompt MMI/USSD is running
*/
public java.lang.CharSequence getMmiRunningText()
throws android.os.RemoteException;
/**
* 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.
*/
public java.lang.CharSequence getUserMessage(java.lang.CharSequence text)
throws android.os.RemoteException;
/**
* Clear pre-set MMI/USSD command. This should be called when user cancel a
* pre-dialed MMI command.
*/
public void clearMmiString() throws android.os.RemoteException;
}
服務:
package net.g_el.mobile.mtc;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.IBinder;
import android.os.PatternMatcher;
import android.os.RemoteException;
import android.util.Log;
import com.android.internal.telephony.IExtendedNetworkService;
/**
* Service implements IExtendedNetworkService interface.
* USSDDumbExtendedNetworkService Service must have name
* "com.android.ussd.IExtendedNetworkService" of the intent declared in the
* Android manifest file so com.android.phone.PhoneUtils class bind to this
* service after system rebooted. Please note service is loaded after system
* reboot! Your application must check is system rebooted.
*
* @see Util#syslogHasLine(String, String, String, boolean)
*/
public class USSDDumbExtendedNetworkService extends Service {
public static final String TAG = "MobileServices";
public static final String LOG_STAMP = "*USSDTestExtendedNetworkService bind successfully*";
public static final String URI_SCHEME = "ussd";
public static final String URI_AUTHORITY = "g_el.net";
public static final String URI_PATH = "/";
public static final String URI_PAR = "return";
public static final String URI_PARON = "on";
public static final String URI_PAROFF = "off";
public static final String MAGIC_ON = ":ON;)";
public static final String MAGIC_OFF = ":OFF;(";
public static final String MAGIC_RETVAL = ":RETVAL;(";
private static boolean mActive = false;
private static CharSequence mRetVal = null;
private Context mContext = null;
private String msgUssdRunning = "G Testing...";
final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_INSERT.equals(intent.getAction())) {
mContext = context;
if (mContext != null) {
msgUssdRunning = mContext.getString(R.string.msgRunning);
mActive = true;
Log.d(TAG, "activate");
}
} else if (Intent.ACTION_DELETE.equals(intent.getAction())) {
mContext = null;
mActive = false;
Log.d(TAG, "deactivate");
}
}
};
private final IExtendedNetworkService.Stub mBinder = new IExtendedNetworkService.Stub() {
@Override
public void setMmiString(String number) throws RemoteException {
Log.d(TAG, "setMmiString: " + number);
}
@Override
public CharSequence getMmiRunningText() throws RemoteException {
Log.d(TAG, "getMmiRunningText: " + msgUssdRunning);
return msgUssdRunning;
}
@Override
public CharSequence getUserMessage(CharSequence text)
throws RemoteException {
if (MAGIC_ON.contentEquals(text)) {
mActive = true;
Log.d(TAG, "control: ON");
return text;
} else {
if (MAGIC_OFF.contentEquals(text)) {
mActive = false;
Log.d(TAG, "control: OFF");
return text;
} else {
if (MAGIC_RETVAL.contentEquals(text)) {
mActive = false;
Log.d(TAG, "control: return");
return mRetVal;
}
}
}
if (!mActive) {
Log.d(TAG, "getUserMessage deactivated: " + text);
//return null;//Use this in order to cancel the output on the screen.
return text;
}
String s = text.toString();
// store s to the !
Uri uri = new Uri.Builder().scheme(URI_SCHEME).authority(URI_AUTHORITY).path(URI_PATH).appendQueryParameter(URI_PAR,text.toString()).build();
sendBroadcast(new Intent(Intent.ACTION_GET_CONTENT, uri));
mActive = false;
mRetVal = text;
Log.d(TAG, "getUserMessage: " + text + "=" + s);
return null;
}
@Override
public void clearMmiString() throws RemoteException {
Log.d(TAG, "clearMmiString");
}
};
/**
* Put stamp to the system log when PhoneUtils bind to the service after
* Android has rebooted. Application must call
* {@link Util#syslogHasLine(String, String, String, boolean)} to check is
* phone rebooted or no. Without reboot phone application does not bind tom
* this service!
*/
@Override
public IBinder onBind(Intent intent) {
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_INSERT);
filter.addAction(Intent.ACTION_DELETE);
filter.addDataScheme(URI_SCHEME);
filter.addDataAuthority(URI_AUTHORITY, null);
filter.addDataPath(URI_PATH, PatternMatcher.PATTERN_LITERAL);
registerReceiver(mReceiver, filter);
// Do not localize!
Log.i(TAG, LOG_STAMP);
return mBinder;
}
public IBinder asBinder() {
Log.d(TAG, "asBinder");
return mBinder;
}
@Override
public boolean onUnbind(Intent intent) {
unregisterReceiver(mReceiver);
return super.onUnbind(intent);
}
}
謝謝
Android提供的USSD沒有API。去年,我們做了一個跟蹤用戶呼叫和消息的項目。我們到達解析USSD消息。如果你想購買解決方案,我們將討論。 –
嗨Abdennour,你的方法是否允許ussd API無需重新啓動?還有反射嗎? (只是想知道它是多麼穩定......如果它不是我感興趣:) – vach
https://play.google.com/store/apps/details?id=name.pilgr.android.pibalance&hl=en https://play.google.com/store/apps/details?id=sk.paco.ussd&hl=zh-CN 這兩個應用程序會抑制USSD響應並讀取內容。不知道他們是如何做到的。 – in3xes