Tôi đang cố gắng triển khai ứng dụng để gửi, nhận và phân tích mã USSD trên Android. Cho đến nay tôi đã sử dụng mã trên http://commandus.com/blog/?p=58 để có được chức năng này. Để dịch vụ hoạt động, điện thoại cần được khởi động lại. Đây không phải là vấn đề khi người dùng cài đặt ứng dụng lần đầu tiên, nhưng những gì tôi đã nhận thấy trong khi thử nghiệm trên trình mô phỏng là điện thoại sẽ yêu cầu khởi động lại trên mọi bản cập nhật, ngay cả khi không có gì mới với dịch vụ. Điều tôi muốn biết là:Triển khai các tính năng của USSD. Liên kết dịch vụ với PhoneUtils mà không cần khởi động lại điện thoại trên mọi bản cập nhật
- Có thể có để PhoneUtils liên kết với dịch vụ của tôi mà không cần khởi động lại không? Ít nhất là vào thời gian cập nhật?
- Trong trường hợp không có cách nào để làm như vậy, tôi đang nghĩ đến việc tạo 2 ứng dụng, một ứng dụng bình thường mà người dùng sẽ tương tác và một ứng dụng riêng có chứa dịch vụ của tôi. Trong trường hợp này, người dùng sẽ được nhắc về lần chạy đầu tiên, trong trường hợp người đó yêu cầu bất kỳ tính năng nào của ussd, để cài đặt ứng dụng thứ hai. Tôi lo lắng mặc dù điều này gây phiền toái cho người dùng. Bạn nghĩ gì sẽ là cách tốt nhất để giải quyết cách tiếp cận như vậy?
Để tham khảo, tôi đã bao gồm mã tôi sử dụng cho dịch vụ vì phần giao diện khác với mã được đăng trên trang web gốc.
Interface:
* 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;
}
dịch vụ:
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);
}
}
Cảm ơn bạn
Không có API cho USSD do Android cung cấp. Năm tới, chúng tôi đã thực hiện dự án theo dõi cuộc gọi và tin nhắn của người dùng. chúng tôi tiếp cận để phân tích cú pháp thông điệp USSD. nếu bạn muốn mua giải pháp, chúng tôi sẽ thảo luận. –
Hi Abdennour, cách tiếp cận của bạn có cho phép apsd ussd không khởi động lại không? Cũng có phản ánh được sử dụng? (chỉ muốn biết làm thế nào ổn định nó là ... nếu nó không phải là tôi quan tâm :) – 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=vi Hai ứng dụng này sẽ loại bỏ phản hồi USSD và đọc nội dung. Không biết làm thế nào họ làm điều đó. – in3xes