这里只讲技术和思路 这里只讲技术和思路 这里只讲技术和思路
在之前的一片文章中描述了如何通过NotificationListenerService获取微信通知的消息,利用NotificationListenerService获取微信通知消息的头像和内容
1.通过虚拟点击回复消息:
1.1当通过NotificationListenerService可以获取一个PendingIntent ,这个PendingIntent封装了数据,可以直接跳转到对应发送消息的会话列表。然后执行虚拟点击找控件,填写回复的内容,点击发送,就完成了一次回复操作
PendingIntent pendingIntent = sbn.getNotification().contentIntent; //获取通知的PendingIntent
跳转到要回复消息的收件人会话列表
Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startIntentSender(pendingIntent.getIntentSender(), intent, Intent.FLAG_ACTIVITY_NEW_TASK,
Intent.FLAG_ACTIVITY_NEW_TASK, 0);
2.通过auto回复消息:
利用虚拟点击回复微信消息,有两个天然的弊端就是一是AccessibilityService可能会被系统kill,这样的话使用的时候必须检测且手动开启,非常麻烦。二是微信的控件id和布局会随着微信版本的升级不断地变化,适配的工作量会不断的增大,且重复id变多,代码越写越麻烦,不易维护。
在Android 5.0以后Android推出了一个Android auto的功能,这里我们可以借鉴使用来实现回复的功能,这个功能使用起来更方便且易维护
在微信生成一个Notification的时候,如果检测到手机上有安装Android auto apk,会在Notification中加入扩展的数据,我们就是要利用这块数据来做事情。
Android auto是原声谷歌应用,国内手机基本上是没有的,也没有谁去会去专门安装这个apk(感兴趣的可以去下载一个体验下),那么我们又要使用,只有“欺骗”微信了,我们可以在手机端安装一个包名为“com.google.android.projection.gearhead” 的apk(可以自己创建一个同样包名的apk安装在手机上即可,没必要安装auto),当微信在创建Notification的时候会检测这个apk是否存在,如果存在就在Notification中扩展了数据字段。
通过NotificationListenerService获取微信的通知,如果安装了auto,在回复微信的时候就可以使用如下代码直接回复
sbn是StatusBarNotification的缩写,在NotificationListenerService中获取
@Override
public void onNotificationPosted(StatusBarNotification sbn) {
...
} catch (ClassCastException e) {
}
}
public void Test() {
Notification notification = sbn.getNotification();//sbn可以看前面
if (notification != null) {
NotificationCompat.CarExtender mCarExtender = new NotificationCompat.CarExtender(notification);
if (mCarExtender != null) {
NotificationCompat.CarExtender.UnreadConversation conversation = mCarExtender.getUnreadConversation();
if (conversation != null) {
PendingIntent pendingReply = conversation.getReplyPendingIntent();
RemoteInput remoteInput = conversation.getRemoteInput();
String key = remoteInput.getResultKey();
if (pendingReply != null) {
Intent localIntent = new Intent();
Bundle resultBundle = new Bundle();
resultBundle.putString(key, "回复的内容");
RemoteInput.addResultsToIntent(new RemoteInput[]{new RemoteInput.Builder(key).build()}, localIntent, resultBundle);
try {
pendingReply.send(mContext, 0, localIntent);
} catch (Exception e) {
}
}
}
}
}
}
加一段demo代码,获取Notification的代码在上一篇文章中已经说明
import android.app.Notification;
import android.app.PendingIntent;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.provider.Settings;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.RemoteInput;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
public class MainActivity extends AppCompatActivity {
Button mtest;
ImageView mTestImg;//通知的头像
Notification mNotification;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();//初始化控件
toggleNotificationListenerService(this);
if (!isNotificationListenersEnabled()) {
gotoNotificationAccessSetting();
}
EventBus.getDefault().register(this);
}
private void toggleNotificationListenerService(Context context) {
PackageManager pm = context.getPackageManager();
pm.setComponentEnabledSetting(new ComponentName(context, MyNotificationListenerService .class),
PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
pm.setComponentEnabledSetting(new ComponentName(context, MyNotificationListenerService .class),
PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
}
protected boolean gotoNotificationAccessSetting() {
try {
Intent intent = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
return true;
} catch (ActivityNotFoundException e) {//普通情况下找不到的时候需要再特殊处理找一次
try {
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ComponentName cn = new ComponentName("com.android.settings", "com.android.settings.Settings$NotificationAccessSettingsActivity");
intent.setComponent(cn);
intent.putExtra(":settings:show_fragment", "NotificationAccessSettings");
startActivity(intent);
return true;
} catch (Exception e1) {
e1.printStackTrace();
}
Toast.makeText(this, "对不起,您的手机暂不支持", Toast.LENGTH_SHORT).show();
System.out.println("--------------对不起,您的手机暂不支持------------->>");
e.printStackTrace();
return false;
}
}
public boolean isNotificationListenersEnabled() {
String pkgName = getPackageName();
final String flat = Settings.Secure.getString(getContentResolver(), "enabled_notification_listeners");
System.out.println("-----flat-------->" + flat);
if (!TextUtils.isEmpty(flat)) {
final String[] names = flat.split(":");
for (int i = 0; i < names.length; i++) {
final ComponentName cn = ComponentName.unflattenFromString(names[i]);
if (cn != null) {
if (TextUtils.equals(pkgName, cn.getPackageName())) {
return true;
}
}
}
}
return false;
}
private void init() {
mtest = (Button) this.findViewById(R.id.test_btn);
mtest.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
test();
}
});
mTestImg = (ImageView) this.findViewById(R.id.test_img);
}
@Override
protected void onStart() {
super.onStart();
System.out.println("------onStart----");
}
@Override
protected void onResume() {
super.onResume();
System.out.println("------onResume----");
}
@Override
protected void onPause() {
super.onPause();
System.out.println("------onPause----");
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(NoticesBean event) {
mTestImg.setImageBitmap(event.getLargeIcon());
mNotification = event.getNotification();
}
public void test() {
Notification notification = mNotification;
if (notification != null) {
NotificationCompat.CarExtender mCarExtender = new NotificationCompat.CarExtender(notification);
if (mCarExtender != null) {
NotificationCompat.CarExtender.UnreadConversation conversation = mCarExtender.getUnreadConversation();
if (conversation != null) {
PendingIntent pendingReply = conversation.getReplyPendingIntent();
RemoteInput remoteInput = conversation.getRemoteInput();
String key = remoteInput.getResultKey();
if (pendingReply != null) {
Intent localIntent = new Intent();
Bundle resultBundle = new Bundle();
resultBundle.putString(key, "回复的内容");
RemoteInput.addResultsToIntent(new RemoteInput[]{new RemoteInput.Builder(key).build()}, localIntent, resultBundle);
try {
pendingReply.send(MainActivity.this, 0, localIntent);
} catch (Exception e) {
}
}
}
}
}
}
}