这里只讲技术和思路 这里只讲技术和思路 这里只讲技术和思路
在之前的一片文章中描述了如何通过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) { } } } } } }
}