利用NotificationListenerService和Android Auto自动回复微信消息

这里只讲技术和思路         这里只讲技术和思路              这里只讲技术和思路

在之前的一片文章中描述了如何通过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) {
                        }
                    }
                }
            }
        }
    }

}

你可能感兴趣的:(framework)