4

我正在尝试检测何时发送短信。我在网上和 StackOverflow 上搜索过,似乎都是相同的解决方案。我有一个启动服务的简单活动,并且在服务中我试图检测何时发送短信:

MainActivity.java

import android.os.Bundle;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.util.Log;
import android.view.Menu;

public class MainActivity extends Activity {

    Intent serviceIntent;
    private static MyReceiver mServiceReceiver; 

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }

    @Override
    protected void onPause() {
        Log.i("Status","Pause");
        unregisterReceiver(mServiceReceiver);
        super.onPause();
    }

    @Override
    protected void onResume() {
        Log.i("Status","Resume");

        // Inicio el Servicio
        serviceIntent = new Intent(MainActivity.this, TrackerService.class);
        startService(serviceIntent);
        // Registro el broadcast del Service para obtener los datos
        mServiceReceiver = new MyReceiver();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(TrackerService.mAction);
        registerReceiver(mServiceReceiver, intentFilter);

        super.onResume();
    }

    /**
     * Receiver del Service, aqui se obtienen los datos que envia el Service
     */
    private class MyReceiver extends BroadcastReceiver{
        @Override
        public void onReceive(Context arg0, Intent arg1) {
            Log.i("ServiceReceiver", "onReceive()");
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
}

TrackerService.java

import android.app.Service;
import android.content.ContentResolver;
import android.content.Intent;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;

public class TrackerService extends Service{

    // Nombre del service
    public static final String mAction = "SMSTracker";
    ContentResolver content;
    ContentResolver contentResolver;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("Status","Service Start");

        // ContentResolver para obtener los SMS salientes
        contentResolver = this.getContentResolver();
        contentResolver.registerContentObserver(Uri.parse("content://sms/out"), true, new mObserver(new Handler()));

        return super.onStartCommand(intent, flags, startId);
    }

    /**
     * Observer que obtiene los SMS salientes
     */
    class mObserver extends ContentObserver {

        public mObserver(Handler handler) {
            super(handler);
        }

        @Override
        public void onChange(boolean selfChange) {
            super.onChange(selfChange);
            Log.i("Status","onChange");

            Uri uriSMS = Uri.parse("content://sms/out");
            Cursor cur = contentResolver.query(uriSMS, null, null, null, null);
            Log.i("SMS", "Columns: " + cur.getColumnNames());

            cur.moveToNext();
            String smsText = cur.getString(cur.getColumnIndex("body"));

            Log.i("SMS", "SMS Lenght: " + smsText.length());

        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.i("Status","Service Destroy");
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.i("Status","Service Bind");
        return null;
    }

}

显现

<uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="15" />
    <uses-permission android:name="android.permission.RECEIVE_SMS"></uses-permission>
    <uses-permission android:name="android.permission.READ_SMS"></uses-permission>

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/title_activity_main" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    <service android:name=".TrackerService" />

</application>

根据我的 LogCat,该服务已启动,我可以在我的 Android 手机运行服务中看到它,我的服务中的 onChange() 方法在我发送短信时永远不会被调用。我错过了什么吗?

4

2 回答 2

1

如果您替换content://sms/outcontent://sms/,您将看到在发送 SMS 时不调用 ContentObserver,而是在收到 SMS 时调用。这是我的观察者的代码。只有在收到短信时才进入 onChange(boolean)。此时协议为“0”。

所以,我和你一样被打动:(

class SmsProviderObserver extends ContentObserver {

    public SmsProviderObserver(Handler handler) {
        super(handler);
    }

    @Override
    public void onChange(boolean selfChange) {
        super.onChange(selfChange);

        Uri uriSms = Uri.parse("content://sms/");

        ContentResolver cr = getContentResolver();
        Cursor cur = cr.query(uriSms, null, null, null, null);
        // this will make it point to the first record, which is the last
        // SMS sent
        if (!cur.moveToNext()) {
            return; // weird!
        }

        String protocol = cur.getString(cur.getColumnIndex("protocol"));
        if (protocol == null) {
            // send
            Log.i("SMS", "SMS SEND");
            int threadId = cur.getInt(cur.getColumnIndex("thread_id"));

            Log.i("SMS", "SMS SEND ID = " + threadId);
            Cursor c = cr.query(
                    Uri.parse("content://sms/outbox/" + threadId), null,
                    null, null, null);
            c.moveToNext();
            int p = cur.getInt(cur.getColumnIndex("person"));
            Log.i("SMS", "SMS SEND person= " + p);
            // getContentResolver().delete(Uri.parse("content://sms/conversations/"
            // + threadId), null, null);

        } else {
            // receive
            Log.i("SMS", "SMS RECIEVE");
            int threadIdIn = cur.getInt(cur.getColumnIndex("thread_id"));

            cr.delete(
                    Uri.parse("content://sms/conversations/" + threadIdIn),
                    null, null);
        }
    }
}

以及注册观察者的代码:

ContentResolver contentResolver = getContentResolver();
mSmsObserverHandler = new Handler();
mSmsProviderObserver = new SmsProviderObserver(mSmsObserverHandler);
contentResolver.registerContentObserver(Uri.parse("content://sms/"), true, mSmsProviderObserver);
于 2012-10-05T16:59:04.483 回答
1

好的,似乎没有办法,不知道这是否是我在 Android 错误上的错误,但我得到了它的工作:

        if( (type == 2 || type == 1) && (!lastID.contentEquals(cur.getString(cur.getColumnIndex("_id")))) ){
            String protocol = cur.getString(cur.getColumnIndex("protocol"));
            lastID = cur.getString(cur.getColumnIndex("_id"));
            // Mensaje enviado
            if(protocol == null){
                Log.i("SMSStatus", "SMS Sent");
            }
            // Mensaje recibido
            else{
                Log.i("SMSStatus", "SMS received");
            }
        }

收到短信时type = 1,发送短信时type = 6、4,最后发送时type = 2。要小心,因为有时onChange方法会被调用很多次,如果它只是一条短信,因此您应该通过检查 _id 参数来检测它是否是相同的短信。

于 2012-10-05T17:05:12.377 回答