Java 发送SMS时,应用程序在getContentResolver()上停止。查询(…)
你好,我正在编写一个应用程序来捕获发送的消息。一切正常,每次我尝试发送SMS时都会调用ContentObserver,但在onChange(布尔自更改)方法中,应用程序会将其放置在:Java 发送SMS时,应用程序在getContentResolver()上停止。查询(…),java,android,android-studio,service,contentobserver,Java,Android,Android Studio,Service,Contentobserver,你好,我正在编写一个应用程序来捕获发送的消息。一切正常,每次我尝试发送SMS时都会调用ContentObserver,但在onChange(布尔自更改)方法中,应用程序会将其放置在: 游标cur=getContentResolver().query(URI,null,null,null,null) .............................. 屏风 在mObserver的TrackerService.java中。当我通过Step Over(F8)对其进行解扰时,它会在这一行中
- 游标cur=getContentResolver().query(URI,null,null,null,null) .............................. 屏风
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
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.activity_main);
}
@Override
protected void onPause() {
Log.i("Status","Pause");
unregisterReceiver(mServiceReceiver);
super.onPause();
}
@Override
protected void onResume() {
Log.i("Status","Resume");
serviceIntent = new Intent(MainActivity.this, TrackerService.class);
startService(serviceIntent);
mServiceReceiver = new MyReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(TrackerService.mAction);
registerReceiver(mServiceReceiver, intentFilter);
super.onResume();
}
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;
}
}
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
{
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 = this.getContentResolver();
contentResolver.registerContentObserver(Uri.parse("content://sms/"), true, new mObserver(new Handler()));
return super.onStartCommand(intent, flags, startId);
}
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 = getContentResolver().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;
}
}
TrackerService.java
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
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.activity_main);
}
@Override
protected void onPause() {
Log.i("Status","Pause");
unregisterReceiver(mServiceReceiver);
super.onPause();
}
@Override
protected void onResume() {
Log.i("Status","Resume");
serviceIntent = new Intent(MainActivity.this, TrackerService.class);
startService(serviceIntent);
mServiceReceiver = new MyReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(TrackerService.mAction);
registerReceiver(mServiceReceiver, intentFilter);
super.onResume();
}
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;
}
}
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
{
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 = this.getContentResolver();
contentResolver.registerContentObserver(Uri.parse("content://sms/"), true, new mObserver(new Handler()));
return super.onStartCommand(intent, flags, startId);
}
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 = getContentResolver().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;
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="wut.com.smstry">
<uses-permission android:name="android.permission.RECEIVE_SMS"></uses-permission>
<uses-permission android:name="android.permission.READ_SMS"></uses-permission>
<application
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".TrackerService" />
</application>
</manifest>
确保您注册的内容路径正确。例:-
Inbox = "content://sms/inbox"
Failed = "content://sms/failed"
Queued = "content://sms/queued"
Sent = "content://sms/sent"
Draft = "content://sms/draft"
Outbox = "content://sms/outbox"
Undelivered = "content://sms/undelivered"
All = "content://sms/all"
Conversations = "content://sms/conversations".
contentResolver.registerContentObserver(Uri.parse("content://sms/outbox"), true, new mObserver(new Handler()));
类似地,在游标上使用相同的路径。querygetContentResolver().query(URI,null,null,null,null);返回java.lang.SecurityException SMS权限是危险的权限,因此如果您在棉花糖或更高版本上运行,则需要在运行时请求这些权限,并且
targetSdkVersion
为23+。还有,”content://sms/out/“
是无效的URI。这是outbox
,不是out
。非常感谢你,@MikeM。我将targetSdkVersion更改为19,并在发件箱上运行,但现在我在this命令字符串smsText=cur.getString(cur.getColumnIndex(“body”);;上收到一个错误;,它会返回此值。您需要检查moveToNext()
返回的内容。如果在此处返回false,则返回的光标
为空。我不认为你所想的是发件箱。如果消息发送成功,消息不会在那里停留很长时间。也许你想改成发送
?是的,发送的对我有用:)谢谢你抽出时间!感谢您的反应,我已经修复了它,但是现在我在this命令字符串smsText=cur.getString(cur.getColumnIndex(“body”);,上遇到了一个错误;,它返回这个imgur.com/a/hIUK5,您有一些提示吗,应该是什么?您可能需要在访问游标之前添加一个检查。如果(cursor.getCount()>0&&cursor.moveToFirst){String smsText=cursor.getString(cursor.getColumnIndex(“body”);也尝试访问content://sms/sent 而不是Outbox谢谢你,好人content://sms/sent/ 修好了!!我很高兴:)