2012-05-23 21 views
32

Sto cercando di implementare un'applicazione per inviare, ricevere e analizzare i codici USSD su Android. Finora ho usato il codice su http://commandus.com/blog/?p=58 per ottenere questa funzionalità. Affinché il servizio funzioni, è necessario riavviare il telefono. Questo non sarebbe un problema la prima volta che l'utente installa l'applicazione, ma quello che ho notato durante il test sull'emulatore è che il telefono richiederà un riavvio ad ogni aggiornamento, anche se non c'è nulla di nuovo nel servizio. Quello che vorrei sapere è il seguente:Implementazione delle funzionalità USSD. Associazione di un servizio a PhoneUtils senza riavviare il telefono ad ogni aggiornamento

  • Potrebbe non essere lontano per fare le PhoneUtils si legano al mio servizio senza un riavvio? Almeno al momento dell'aggiornamento?
  • Nel caso in cui non ci sia modo di farlo, sto pensando di creare 2 applicazioni, una che è la normale applicazione con cui l'utente interagirebbe e una separata che contiene il mio servizio. In questo caso, l'utente verrà richiesto alla prima esecuzione, nel caso in cui lui/lei necessiti di una delle funzionalità ussd, per installare la seconda applicazione. Sono preoccupato che ciò sia fastidioso per l'utente. Quale pensi che sarebbe il modo migliore per affrontare questo approccio?

Per riferimento, ho incluso il codice utilizzato per il servizio in quanto la parte dell'interfaccia è diversa da quella pubblicata sul sito Web originale.

Interfaccia:

* 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; 
} 

Servizio:

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); 
} 

    } 

Grazie

+0

Nessuna API per USSD fornita da Android.L'anno scorso, abbiamo realizzato un progetto che tiene traccia delle chiamate e dei messaggi degli utenti. raggiungiamo l'analisi del messaggio USSD. se vuoi comprare una soluzione, discuteremo. –

+0

Ciao Abdennour, il tuo approccio consente a ussd api senza riavvio? Inoltre è stata utilizzata la riflessione? (voglio solo sapere quanto è stabile ... se non mi interessa :) – 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=it Queste due app sopprimono la risposta USSD e leggono il contenuto. Non so come lo fanno. – in3xes

risposta

1

Si prega di essere chiari, si è completamente fuori nelle erbacce di implementazioni interne della piattaforma. Sembra che tu voglia che questo funzioni "bene". Quello che stai facendo non funzionerà bene, punto. Non si ha alcuna garanzia che queste implementazioni interne rimarranno invariate su diverse versioni delle piattaforme, o anche diverse versioni della piattaforma sui dispositivi del produttore, né che il comportamento che si sta osservando attorno a questa interfaccia funzionerà allo stesso modo in situazioni diverse.

Questo è solo un brutto male. Non farlo.

+2

Sono assolutamente d'accordo, il problema è che non esiste un vero supporto USSD su Android che ho dovuto ricorrere a tale hacking. – ghaith

+3

Il solo dire che qualcosa è "cattivo" non costituisce una risposta o un commento personale, e questo è particolarmente fastidioso quando proviene dallo sviluppatore principale di Android. Ci sono molti motivi per cui vorresti usarlo, ma ciò che lo rende peggiore è che hai rimosso completamente il 'IExtendedNetworkService' in API> 4.2.2. E cosa succede? [QUESTO] (https://code.google.com/p/android/issues/detail?id=57120) è ciò che accade! (Un intero paese viene spammato con USSD dai propri fornitori di servizi.) – not2qubit

+1

Questo dovrebbe essere un commento piuttosto che una risposta. Ciò che ritieni sia rimasto nella domanda. Puoi sempre chiedere maggiori dettagli ... – cafebabe1991