新版本Android由于数据安全限制,在读取短信内容前必须预先取得授权,不能直接在MainActivity中直接读取
若要定时读取Android内容,尽量使用服务(service)通知的形式,而不是直接使用Java Timer定时器,否则程序运行10s后自动退出
Android读取手机短信
1. AndroidManifest.xml 权限配置
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
2. 授权申请
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_SMS) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(context, Manifest.permission.RECEIVE_SMS) != PackageManager.PERMISSION_GRANTED) {
LOG.i("demo", "未申请到读取短信权限,请手动授权");
return;
}
// 有了权限,即可读取短信内容
3. 读取短信内容
Uri uri = Uri.parse("content://sms/");
String[] projection = new String[] {"address", "body", "date"};
// 获取手机内部短信
Cursor cur = contentResolver.query(uri, projection, null, null, "date desc");
if (null != cur && cur.moveToFirst()) {
int index_Address = cur.getColumnIndex("address");
int index_Body = cur.getColumnIndex("body");
int index_Date = cur.getColumnIndex("date");
while(cur.moveToNext()) {
String sender = cur.getString(cur.getColumnIndex("address"));
String content = cur.getString(cur.getColumnIndex("body"));
long timeMs = cur.getLong(cur.getColumnIndex("date"));
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
Date d = new Date(timeMs);
String createTime = dateFormat.format(d);
};
if (!cur.isClosed()) {
cur.close();
cur = null;
}
}
Android定时器实现
1. 编写服务类,执行任务,并发消息给接收者,重新唤醒服务
public class AlarmService extends Service {
//每10s更新一次数据
private static final int ONE_Miniute = 10 * 1000;
private static final int PENDING_REQUEST = 0;
@Override
public void onCreate() {
super.onCreate();
// 每次service创建,都发送消息给接收者,唤醒服务
if (Build.VERSION.SDK_INT >= 26) {
String CHANNEL_ID = "my_channel_01";
NotificationChannel channel = new NotificationChannel(CHANNEL_ID,
"Channel human readable title",
NotificationManager.IMPORTANCE_DEFAULT);
((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel(channel);
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("")
.setContentText("").build();
startForeground(1, notification);
}
Log.v("demo", "alarmService created");
}
/**
* 调用Service都会执行到该方法
*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
String phone = SmsUtil.getPhone(getApplicationContext());
if(null == phone) {
return super.onStartCommand(intent, flags, startId);
}
// 定时执行任务
new Thread(new Runnable() {
@Override
public void run() {
Log.e("demo", "I am running");
}
}).start();
//通过AlarmManager定时启动广播
AlarmManager alarmManager= (AlarmManager) getSystemService(ALARM_SERVICE);
//从开机到现在的毫秒书(手机睡眠(sleep)的时间也包括在内
long triggerAtTime = SystemClock.elapsedRealtime()+ONE_Miniute;
Intent i = new Intent(this, AlarmReceive.class);
PendingIntent pIntent = PendingIntent.getBroadcast(this, PENDING_REQUEST,i, PendingIntent.FLAG_IMMUTABLE);
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,triggerAtTime,pIntent);
return super.onStartCommand(intent, flags, startId);
}
@Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
}
2. 编写接收类,唤醒服务
public class AlarmReceive extends BroadcastReceiver {
public AlarmReceive() {
super();
Log.i("demo", "AlarmReceiver create");
}
@Override
public void onReceive(Context context, Intent intent) {
//循环启动Service
Intent i = new Intent(context, AlarmService.class);
// 后台程序需使用startForegroundService启动服务
context.startForegroundService(i);
}
}
3. AndroidManifest.xml 配置service 和 receiver
<!-- 该权限也需要 -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<service android:name=".AlarmService"/>
<receiver android:name=".AlarmReceive"/>