2012-05-23 37 views
32

我試圖實現應用程序以在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); 
} 

    } 

謝謝

+0

Android提供的USSD沒有API。去年,我們做了一個跟蹤用戶呼叫和消息的項目。我們到達解析USSD消息。如果你想購買解決方案,我們將討論。 –

+0

嗨Abdennour,你的方法是否允許ussd API無需重新啓動?還有反射嗎? (只是想知道它是多麼穩定......如果它不是我感興趣:) – vach

+0

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

回答

1

請清楚,你完全關閉到平臺內部實現的雜草。這聽起來像是你想讓它「很好地」工作。你正在做的事情不會很好,時間。您無法保證這些內部實現將在不同版本的平臺上保持不變,甚至不同製造商設備上的平臺構建也不會相同,也不保證您在此界面上看到的行爲在不同情況下的工作方式相同。

這只是壞壞壞。不要這樣做。

+2

我完全同意這一點,問題是沒有真正的USSD支持在Android上,我不得不訴諸這種黑客行爲。 – ghaith

+3

只是說有些東西是「不好的」並不構成答案或甚至是個人評論,而這一點在來自Android的首席開發人員時尤其令人不安。爲什麼要使用它有很多原因,但更糟糕的是,您已經完全刪除API> 4.2.2中的'IExtendedNetworkService'。會發生什麼? [THIS](https://code.google.com/p/android/issues/detail?id=57120)會發生什麼! (整個國家通過自己的服務提供商獲得USSD的垃圾郵件。) – not2qubit

+1

這應該是一條評論,而不是一個答案。你在問題中留下了什麼。你總是可以詢問更多細節... – cafebabe1991

相關問題