实施USSD功能。 绑定到PhoneUtils服务无需重新启动手机上的每一次更新(Impleme

2019-06-24 17:24发布

我试图实现应用程序发送,接收并解析USSD代码在Android上。 到目前为止,我所使用的代码http://commandus.com/blog/?p=58为了得到这个功能。 为了使服务工作,手机需要重新启动。 这不会是一个问题,当用户第一次安装该应用程序,但我已经注意到,而在模拟器上测试,该手机将需要在每次更新重新启动,即使有什么新的服务。 我想知道的是以下几点:

  • 可能会有离开使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);
}

   }

谢谢

Answer 1:

请清楚,你是完全关闭到平台内部实现的杂草。 这听起来像你想要这个工作,“井”。 你在做什么是行不通的好,期。 你不能保证这些内部实现要保持不变在不同版本的平台,甚至不同的基础上生产设备的平台,也不是说你看到身边这个接口的行为将工作在不同的情况相同。

这仅仅是很坏很坏的坏。 不要这样做。



文章来源: Implementing USSD features. Binding a service to the PhoneUtils without restarting the phone on every update