关闭

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

6518人阅读 评论(2) 收藏 举报
分类:
本文内容:
  • 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


1
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:178483次
    • 积分:2100
    • 等级:
    • 排名:第18806名
    • 原创:30篇
    • 转载:0篇
    • 译文:0篇
    • 评论:44条
    GitHub
    文章分类