Is it possible to read the call cost history from

2019-03-09 13:20发布

问题:

Is there a possibility of handling the data displayed on call cost dialogue received by prepaid user. I want to save all the balance reduction for along with call duration in my sqlite db.

回答1:

As we learn from the already famous blog post

As a start, look at the PhoneUtils class in the Android source code. [...] Specifically, looking at line 217, an intent with the name “com.android.ussd.IExtendedNetworkService” is being composed. So what you need to do is implement your own service that responds to that intent. The service needs to be implemented according to the IExtendedNetworkService.aidl which is a part of the Android framework.

where to start at? the best is to follow this even more famous blog post

First of all, we understand the basics:

  1. We need a service that implements IExtendedNetworkService interface.
  2. The service will be aware of the intent "com.android.ussd.IExtendedNetworkService", so it will have the correspondent intent filter in the app manifest.
  3. What we know is that com.android.phone.PhoneUtils will bind to this service. (If you dont know what binding a service is, refer to here)
  4. on Bind we return a binder, which contanins the functions that PhoneUtils will actually call
  5. The service has to be be running, so we will have it started when the system reboot. For that we need a broadcast receiver. (If you don't know what is this, and you want to understand all this better, refer to here)

Let`s get into it.

First, the receiver, this is the easy part. We make a file called BootReceiver.java with this contents.

package com.android.ussdcodes;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class BootReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        // TODO Auto-generated method stub
        Log.d("USSDService", context.getString(R.string.service_started));
        context.startService(new Intent(context,USSDDumbExtendedNetworkService.class));
    }

}

Now, the service itself. I havent tried it myself, but i have read the code here to find the methods explanation, that i've put in comments. Also i edited some stuff.

As far as i understand, you will receive the actual text in getUserMessage, there you parse the text, and return what you want to be in the popup. If you dont want popup, return null. So, it is also there where you should do any other stuff with that text.

public class USSDDumbExtendedNetworkService extends Service {

public static final String TAG = "ExtNetService";
public static CharSequence mRetVal = null;
public static boolean mActive = true;
private boolean change = false;
private String msgUssdRunning = null;

private final IExtendedNetworkService.Stub mBinder = new IExtendedNetworkService.Stub() {


    //Set a MMI/USSD command to ExtendedNetworkService for further process. This should be called when a MMI command is placed from panel.
    //we don't need it in this case
    @Override
    public void setMmiString(String number) throws RemoteException {

    }



    //return the specific string which is used to prompt MMI/USSD is running

    @Override
    public CharSequence getMmiRunningText() throws RemoteException {
        return msgUssdRunning;
    }

    //Get specific message which should be displayed on pop-up dialog.
   Parameters:
   text original MMI/USSD message response from framework
   Returns:
   specific user message correspond to text. null stands for no pop-up dialog need to show.
    @Override
    public CharSequence getUserMessage(CharSequence text)
            throws RemoteException {
         return text;
    }
   //Clear pre-set MMI/USSD command. This should be called when user cancel a pre-dialed MMI    command.
    //we don't need it in this case
    @Override
    public void clearMmiString() throws RemoteException {
    }
};

@Override
public IBinder onBind(Intent intent) {
    msgUssdRunning = "Some text to show";

    return mBinder; 
}

public IBinder asBinder() {
    return mBinder;
}

@Override
public boolean onUnbind(Intent intent) {
    return super.onUnbind(intent);
}}

And the last part, the manifest. You have to register the service, and the broadcastreceiver

<receiver android:name="com.android.ussdcodes.BootReceiver">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    /intent-filter>
</receiver>

<service android:name=".USSDDumbExtendedNetworkService" >
    <intent-filter android:icon="@drawable/ic_launcher">
        <action android:name="com.android.ussd.IExtendedNetworkService" />
            <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</service>