2012-05-23 13 views
32

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

+0

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. –

+0

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

+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=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

Trả lời

1

Hãy rõ ràng, bạn là hoàn toàn lạc đường triển khai nội bộ của nền tảng này. Có vẻ như bạn đang muốn điều này hoạt động "tốt". Những gì bạn đang làm sẽ không hoạt động tốt, thời gian. Bạn không đảm bảo rằng các triển khai bên trong sẽ giống nhau trên các phiên bản khác nhau của nền tảng hoặc thậm chí là các bản dựng nền tảng khác nhau trên thiết bị của nhà sản xuất cũng như hành vi mà bạn nhìn thấy trên giao diện này sẽ hoạt động giống nhau trong các tình huống khác nhau.

Đây chỉ là xấu xấu xấu. Đừng làm thế.

+2

Tôi hoàn toàn đồng ý rằng, vấn đề là không có hỗ trợ USSD thực trên Android mà tôi đã phải nghỉ mát để hack như vậy. – ghaith

+3

Chỉ cần nói rằng điều gì đó "xấu" không cấu thành câu trả lời hoặc thậm chí là nhận xét cá nhân và điều đó đặc biệt đáng lo ngại khi đến từ nhà phát triển chính của Android. Có nhiều lý do tại sao bạn muốn sử dụng điều này, nhưng điều làm cho nó tồi tệ hơn là bạn đã xóa hoàn toàn 'IExtendedNetworkService' trong API> 4.2.2. Và những gì sẽ xảy ra? [NÀY] (https://code.google.com/p/android/issues/detail?id=57120) là những gì sẽ xảy ra! (Cả một quốc gia bị các nhà cung cấp dịch vụ của chính họ gửi thư rác với USSD.) – not2qubit

+1

Đây phải là một nhận xét chứ không phải là câu trả lời. Những gì bạn cảm thấy đã bị bỏ lại trong câu hỏi. Bạn luôn có thể hỏi thêm chi tiết ... – cafebabe1991