Pertanyaan Menerapkan fitur USSD. Mengikat layanan ke PhoneUtils tanpa menghidupkan ulang ponsel pada setiap pembaruan


Saya mencoba menerapkan aplikasi untuk mengirim, menerima, dan mem-parsing kode USSD di android. Sejauh ini saya menggunakan kode http://commandus.com/blog/?p=58 untuk mendapatkan fungsi ini. Agar layanan berfungsi, ponsel perlu dihidupkan ulang. Ini tidak akan menjadi masalah saat pertama kali pengguna menginstal aplikasi, tetapi apa yang saya perhatikan saat menguji pada emulator adalah bahwa ponsel akan memerlukan restart pada setiap pembaruan, meskipun tidak ada yang baru dengan layanan ini. Yang ingin saya ketahui adalah sebagai berikut:

  • Mungkinkah ada jauh untuk membuat PhoneUtils mengikat ke layanan saya tanpa restart? Setidaknya pada waktu pembaruan?
  • Dalam hal tidak ada cara untuk melakukannya, saya berpikir untuk membuat 2 aplikasi, yang merupakan aplikasi normal yang akan berinteraksi dengan pengguna dan yang terpisah yang berisi layanan saya. Dalam hal ini pengguna akan diminta pada run pertama, jika dia memerlukan salah satu fitur ussd, untuk menginstal aplikasi kedua. Saya khawatir meskipun ini mengganggu bagi pengguna. Menurut Anda, apa cara terbaik untuk mengatasi pendekatan semacam itu?

Untuk referensi, saya telah menyertakan kode yang saya gunakan untuk layanan sebagai bagian antarmuka berbeda dari yang diposting di situs web asli.

Antarmuka:

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

Layanan:

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

   }

Terima kasih


32
2018-05-23 14:35


asal


Jawaban:


Harap jelas, Anda benar-benar masuk ke dalam gulma implementasi internal platform. Kedengarannya seperti Anda menginginkan ini bekerja "baik". Apa yang Anda lakukan tidak akan berjalan dengan baik, titik. Anda tidak memiliki jaminan bahwa penerapan internal ini akan tetap sama di berbagai versi platform yang berbeda, atau bahkan versi platform yang berbeda di perangkat pabrikan, atau bahwa perilaku yang Anda lihat di sekitar antarmuka ini akan bekerja sama dalam situasi yang berbeda.

Ini hanya buruk buruk. Jangan lakukan ini.


1
2017-11-29 00:24