您的位置:首页 > 移动开发 > 微信开发

Android微信自动回复及锁屏控制界面

2016-05-31 19:43 537 查看
本文内容:
AccessibilityService与微信自动回复
锁屏显示界面及activity切换动画

自定义样式与圆角矩形按钮

电量信息获取

来去电通话状态监听

ViewFlipper与页面切换动画

一、实现自动回复再次用到了Android的辅助功能AccessibilityService(参考微信抢红包辅助),通过自动进入微信聊天界面查找到文本编辑框(android.widget.EditText)并获取焦点后将回复内容粘贴进去,之后再查找到发送按钮模拟点击。

AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
AccessibilityNodeInfo targetNode = null;
AccessibilityNodeInfo editText = null;
//通过组件名递归查找编辑框
private void findNodeInfosByName(AccessibilityNodeInfo nodeInfo, String name) {
if(name.equals(nodeInfo.getClassName())) {
editText = nodeInfo;
return;
}
for(int i = 0; i < nodeInfo.getChildCount(); i++) {
findNodeInfosByName(nodeInfo.getChild(i), name);
}
}

查找编辑框
if(editText == null) {
//第一种查找方法
List<AccessibilityNodeInfo> list1 = nodeInfo.findAccessibilityNodeInfosByViewId(StaticData.editId);
if( !list1.isEmpty() )
editText = list1.get(0);
//第二种查找方法
if(editText == null)
findNodeInfosByName(nodeInfo, "android.widget.EditText");
}
targetNode = editText;


粘贴回复信息
if(targetNode != null) {
//android >= 21=5.0时可以用ACTION_SET_TEXT
//android >= 18=4.3时可以通过复制粘贴的方法,先确定焦点,再粘贴ACTION_PASTE
//使用剪切板
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("message", StaticData.message);
//设置粘贴板
clipboard.setPrimaryClip(clip);

//获取焦点
targetNode.performAction(AccessibilityNodeInfo.ACTION_FOCUS);
//粘贴内容
targetNode.performAction(AccessibilityNodeInfo.ACTION_PASTE);
}


查找发送按钮
if(targetNode != null) {
targetNode = null;
List<AccessibilityNodeInfo> list2 = nodeInfo.findAccessibilityNodeInfosByViewId(StaticData.sendId);
if( !list2.isEmpty() )
targetNode = list2.get(0);
//第二种查找方法
if(targetNode == null)
targetNode = findNodeInfosByText(nodeInfo, "发送");
}


点击发送按钮
if(targetNode != null) {
final AccessibilityNodeInfo n = targetNode;
performClick(n);
}


二、锁屏显示界面及activity切换动画
构造锁屏显示界面,用两个Flag:WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD 和 WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED即可使Activity显示在锁屏界面之上
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
setContentView(R.layout.activity_screen);
}


在AndroidManifest.xml中配置锁屏显示界面,使其独占一个新的活动栈且只有一个实例且不在任务历史中显示
<activity
android:excludeFromRecents="true"
android:exported="false"
android:launchMode="singleInstance"
android:name="com.example.autoreply.LockScreenActivity"
android:screenOrientation="portrait"
android:taskAffinity="com.example.autoreply.lockscreen"
android:noHistory="true"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
>
</activity>


Activity的消失动画效果,在滑动锁或无锁屏状态下有效果,其他如九宫格锁好像无效
@Override
public void finish() {
super.finish();
//overridePendingTransition(android.R.anim.slide_in_left,android.R.anim.slide_out_right);//系统自带动画
overridePendingTransition(R.drawable.activity_close, R.drawable.activity_start);//自定义动画
}

其中activity_close:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<translate
android:duration="500"
android:fromYDelta="100%p"
android:toYDelta="0" />
</set>

其中activity_start:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<translate
android:duration="500"
android:fromYDelta="0"
android:toYDelta="-100%p" />
</set>


创建与启动锁屏显示界面,在接收到屏幕状态变化(亮屏或黑屏)广播后创建启动Activity,需要添加Flag:Intent.FLAG_ACTIVITY_NEW_TASK。若是来电唤醒或在通话时的屏幕状态变化则不启动activity,不然需先关闭activity才能接听电话,同理当需要自动回复时也不显示锁屏activity
class ScreenOffReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//若在通话则不显示锁屏界面
if(StaticData.iscalling)
return;
String action = intent.getAction();
if (action.equals(Intent.ACTION_SCREEN_OFF)) {
Log.i("demo", "screen off");
Intent lockscreen = new Intent(AutoReplyService.this, LockScreenActivity.class);
lockscreen.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(lockscreen);
} else if (action.equals(Intent.ACTION_SCREEN_ON)) {
Log.i("demo", "screen on");
//若需要自动回复也不显示,否则需解锁两次而导致自动回复失败
if(canGet)
return;
Intent lockscreen = new Intent(AutoReplyService.this, LockScreenActivity.class);
lockscreen.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(lockscreen);
}
}
}


三、自定义样式与圆角矩形按钮
自定义样式button.xml

<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="false">
<shape android:shape="rectangle">
<solid android:color="#BCCCCC"/>

<!-- 设置按钮的四个角为弧形 -->
<corners android:radius="20dip"/>

<!-- 按钮里面的文字与边界的间隔 -->
<padding android:bottom="10dp" android:left="13dp" android:right="13dp" android:top="10dp" />
</shape>
</item>

<item android:state_pressed="true">
<shape android:shape="rectangle">
<solid android:color="#95AEAE"/>
<corners android:radius="20dip"/>
</shape>
</item>
</selector>


使用样式
<Button
android:id="@+id/startbtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/button"
android:text="start"
android:textColor="#5F656D" />


四、电量信息获取
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
//获取当前电量,如未获取具体数值,则默认为0
batteryLevel=intent.getIntExtra(BatteryManager.EXTRA_LEVEL,0);
//获取最大电量,如未获取到具体数值,则默认为100
batteryScale=intent.getIntExtra(BatteryManager.EXTRA_SCALE,100);
//显示电量
Levelbtn.setText((batteryLevel*100/batteryScale)+"%");
}
};


五、来去电通话状态监听
相关定义

private TelephonyManager tm;
private PhoneReceiver preceiver;

//通话状态变化广播接收器,通话期间不弹出锁屏活动
public class PhoneReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(Intent.ACTION_NEW_OUTGOING_CALL)) {
StaticData.iscalling = true;
Log.i("demo", "去电");
} else {
StaticData.iscalling = true;
Log.i("demo", "来电");
}
}
}
//通话状态变化广播接收器,通话期间不弹出锁屏活动
private PhoneStateListener listener = new PhoneStateListener() {
@Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
switch(state) {
case TelephonyManager.CALL_STATE_IDLE:
StaticData.iscalling = false;
Log.i("demo", "挂断");
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
StaticData.iscalling = true;
Log.i("demo", "接听");
break;
case TelephonyManager.CALL_STATE_RINGING:
StaticData.iscalling = true;
Log.i("demo", "来电");
break;
}
}
};


相关使用

//注册广播接收器
preceiver = new PhoneReceiver();
filter = new IntentFilter();
filter.addAction(Intent.ACTION_NEW_OUTGOING_CALL);
registerReceiver(preceiver, filter);
tm = (TelephonyManager)getSystemService(Service.TELEPHONY_SERVICE);
//设置监听器
tm.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);


六、ViewFlipper与页面切换动画
布局

<ViewFlipper
......>

<!-- 第一个页面 -->
<LinearLayout
......
</LinearLayout>

<!-- 第二个页面 -->
<LinearLayout
......
</LinearLayout>
</ViewFlipper>


使用

//设置切换动画
viewFlipper.setInAnimation(this, android.R.anim.slide_in_left);
viewFlipper.setOutAnimation(this, android.R.anim.slide_out_right);

//切换页面
viewFlipper.showNext();


效果如图:



七、详细源码请看这里:GitHub
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: