2020-12-18 V1.0.1
*.[新增]支持通过wifi名称来判断是否在上班。 *.[新增]增加游戏模式(尚未完成)。 *.[改进]不连公司wifi的情况下,个性化购物和淘口令声音。
This commit is contained in:
parent
00c4b1dc9e
commit
732d4c7c64
6
.idea/vcs.xml
Normal file
6
.idea/vcs.xml
Normal file
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
|
@ -1,2 +1,7 @@
|
|||
2020-11-28 V1.0
|
||||
暂无。
|
||||
#### 2020-12-18 V1.0.1
|
||||
- *.[新增]支持通过wifi名称来判断是否在上班。
|
||||
- *.[新增]增加游戏模式(尚未完成)。
|
||||
- *.[改进]不连公司wifi的情况下,个性化购物和淘口令声音。
|
||||
|
||||
#### 2020-11-28 V1.0
|
||||
- 暂无。
|
|
@ -10,8 +10,8 @@ android {
|
|||
applicationId "com.itrycn.tellmenotice"
|
||||
minSdkVersion 23
|
||||
targetSdkVersion 29
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
versionCode 2
|
||||
versionName "1.0.1"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
|
|
@ -4,24 +4,37 @@
|
|||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_USER_PRESENT" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
|
||||
<!--如果是安卓10.0,需要后台获取连接的wifi名称则添加进程获取位置信息权限 -->
|
||||
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:usesCleartextTraffic="true"
|
||||
android:theme="@style/Theme.TellMeNotice">
|
||||
<activity android:name=".MainActivity">
|
||||
<activity android:name=".MainActivity" android:process=":BackgroundService">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name="com.itrycn.ta.AccessibilityOpenHelperActivity"
|
||||
android:excludeFromRecents="true"
|
||||
android:launchMode="singleTask"
|
||||
android:process=":BackgroundService"
|
||||
android:taskAffinity="com.open.helper" />
|
||||
<receiver android:name=".BootBroadcastReceiver"
|
||||
android:enabled="true"
|
||||
android:exported="true"
|
||||
|
@ -46,6 +59,18 @@
|
|||
<action android:name="android.service.notification.NotificationListenerService" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
<service android:name="com.itrycn.ta.AccessibilityTaService"
|
||||
android:label="通知提醒辅助服务"
|
||||
android:exported="true"
|
||||
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
|
||||
android:process=":BackgroundService">
|
||||
<intent-filter>
|
||||
<action android:name="android.accessibilityservice.AccessibilityService" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.accessibilityservice"
|
||||
android:resource="@xml/accessibility_config"/>
|
||||
</service>
|
||||
</application>
|
||||
|
||||
</manifest>
|
|
@ -0,0 +1,158 @@
|
|||
package com.itrycn.ta;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.itrycn.ta.utils.AccessibilityUtil;
|
||||
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
|
||||
/**
|
||||
* 辅助功能权限打开辅助activity,用于启动辅助功能设置页面
|
||||
*/
|
||||
public class AccessibilityOpenHelperActivity extends Activity {
|
||||
private boolean isFirstCome = true;
|
||||
private static final String ACTION = "action";
|
||||
private static final String ACTION_FINISH_SELF = "action_finis_self";
|
||||
|
||||
private Timer timer;
|
||||
private TimerTask timerTask;
|
||||
private int mTimeoutCounter = 0;
|
||||
|
||||
private int TIMEOUT_MAX_INTERVAL = 60 * 2; // 2 min
|
||||
|
||||
private long TIMER_CHECK_INTERVAL = 1000;
|
||||
protected static Handler mHandle = new Handler();
|
||||
protected static Runnable tipToastDelayRunnable;
|
||||
|
||||
private static void removeDelayedToastTask() {
|
||||
if (mHandle != null && tipToastDelayRunnable != null) {
|
||||
mHandle.removeCallbacks(tipToastDelayRunnable);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
//setContentView(R.layout.activity_accessibility_transparent_layout);
|
||||
Intent intent = getIntent();
|
||||
if (intent != null && intent.getExtras() != null) {
|
||||
String action = intent.getStringExtra(ACTION);
|
||||
if (ACTION_FINISH_SELF.equals(action)) {
|
||||
finishCurrentActivity();
|
||||
return;
|
||||
}
|
||||
}
|
||||
mTimeoutCounter = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
super.onBackPressed();
|
||||
finishCurrentActivity();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNewIntent(Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
if (intent != null && intent.getExtras() != null) {
|
||||
String action = intent.getStringExtra(ACTION);
|
||||
if (ACTION_FINISH_SELF.equals(action)) {
|
||||
finishCurrentActivity();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
if (!isFirstCome) {
|
||||
removeDelayedToastTask();
|
||||
finishCurrentActivity();
|
||||
} else {
|
||||
jumpActivities();
|
||||
startCheckAccessibilityOpen();
|
||||
}
|
||||
isFirstCome = false;
|
||||
}
|
||||
|
||||
private void jumpActivities() {
|
||||
try {
|
||||
Intent intent = AccessibilityUtil.getAccessibilitySettingPageIntent(this);
|
||||
startActivity(intent);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
freeTimeTask();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
private void finishCurrentActivity() {
|
||||
freeTimeTask();
|
||||
finish();
|
||||
}
|
||||
|
||||
private void startCheckAccessibilityOpen() {
|
||||
freeTimeTask();
|
||||
initTimeTask();
|
||||
timer.schedule(timerTask, 0, TIMER_CHECK_INTERVAL);
|
||||
}
|
||||
|
||||
private void initTimeTask() {
|
||||
timer = new Timer();
|
||||
mTimeoutCounter = 0;
|
||||
timerTask = new TimerTask() {
|
||||
|
||||
@SuppressWarnings("static-access")
|
||||
@Override
|
||||
public void run() {
|
||||
if (AccessibilityUtil.isAccessibilitySettingsOn(AccessibilityOpenHelperActivity.this)) {
|
||||
freeTimeTask();
|
||||
Looper.prepare();
|
||||
try {
|
||||
AccessibilityOpenHelperActivity.this.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Toast.makeText(AccessibilityOpenHelperActivity.this, "辅助功能开启成功", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra(ACTION, ACTION_FINISH_SELF);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.setClass(AccessibilityOpenHelperActivity.this, AccessibilityOpenHelperActivity.this.getClass());
|
||||
startActivity(intent);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
Looper.loop();
|
||||
}
|
||||
// 超过2分钟超时,就释放timer。
|
||||
mTimeoutCounter++;
|
||||
if (mTimeoutCounter > TIMEOUT_MAX_INTERVAL) {
|
||||
freeTimeTask();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void freeTimeTask() {
|
||||
if (timerTask != null) {
|
||||
timerTask.cancel();
|
||||
timerTask = null;
|
||||
}
|
||||
if (timer != null) {
|
||||
timer.cancel();
|
||||
timer = null;
|
||||
}
|
||||
}
|
||||
}
|
601
app/src/main/java/com/itrycn/ta/AccessibilityOperator.java
Normal file
601
app/src/main/java/com/itrycn/ta/AccessibilityOperator.java
Normal file
|
@ -0,0 +1,601 @@
|
|||
package com.itrycn.ta;
|
||||
|
||||
import android.accessibilityservice.AccessibilityService;
|
||||
import android.accessibilityservice.GestureDescription;
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.DownloadManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.Rect;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
import android.provider.DocumentsContract;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.util.Size;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.core.content.FileProvider;
|
||||
|
||||
import com.itrycn.ta.script.ScriptSystemInfo;
|
||||
import com.itrycn.ta.utils.AccessibilityLog;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.security.PublicKey;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Created by popfisher on 2017/7/11.
|
||||
*/
|
||||
|
||||
@TargetApi(16)
|
||||
public class AccessibilityOperator {
|
||||
|
||||
private Context mContext;
|
||||
private static AccessibilityOperator mInstance = new AccessibilityOperator();
|
||||
private AccessibilityEvent mAccessibilityEvent;
|
||||
private AccessibilityService mAccessibilityService;
|
||||
public Handler UIHandler;
|
||||
public boolean IsExit=false;
|
||||
private boolean result_bool=false;
|
||||
public ScriptSystemInfo SystemInfo=ScriptSystemInfo.getInstance();
|
||||
private AccessibilityOperator() {
|
||||
}
|
||||
|
||||
public static AccessibilityOperator getInstance() {
|
||||
return mInstance;
|
||||
}
|
||||
|
||||
public void init(Context context) {
|
||||
mContext = context;
|
||||
ScriptSystemInfo.getInstance().init(context);
|
||||
}
|
||||
|
||||
public void updateEvent(AccessibilityService service, AccessibilityEvent event) {
|
||||
if (service != null && mAccessibilityService == null) {
|
||||
mAccessibilityService = service;
|
||||
}
|
||||
if (event != null) {
|
||||
mAccessibilityEvent = event;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isServiceRunning() {
|
||||
ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
|
||||
List<ActivityManager.RunningServiceInfo> services = am.getRunningServices(Short.MAX_VALUE);
|
||||
for (ActivityManager.RunningServiceInfo info : services) {
|
||||
if (info.service.getClassName().equals("com.itryn.ta.AccessibilityTaService")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private AccessibilityNodeInfo getRootNodeInfo() {
|
||||
AccessibilityEvent curEvent = mAccessibilityEvent;
|
||||
AccessibilityNodeInfo nodeInfo = null;
|
||||
if (Build.VERSION.SDK_INT >= 16) {
|
||||
// 建议使用getRootInActiveWindow,这样不依赖当前的事件类型
|
||||
if (mAccessibilityService != null) {
|
||||
nodeInfo = mAccessibilityService.getRootInActiveWindow();
|
||||
if(nodeInfo==null)
|
||||
{
|
||||
Toast("无法获取当前界面内容1");
|
||||
}
|
||||
//AccessibilityLog.printLog("nodeInfo: " + nodeInfo);
|
||||
}
|
||||
else{
|
||||
Toast("辅助服务开启失败,请重启软件");
|
||||
}
|
||||
// 下面这个必须依赖当前的AccessibilityEvent
|
||||
// nodeInfo = curEvent.getSource();
|
||||
} else {
|
||||
nodeInfo = curEvent.getSource();
|
||||
if(nodeInfo==null)
|
||||
{
|
||||
Toast("无法获取当前界面内容2");
|
||||
}
|
||||
}
|
||||
return nodeInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据Text搜索所有符合条件的节点, 精确搜索方式
|
||||
*/
|
||||
public List<AccessibilityNodeInfo> findNodesByText(String text) {
|
||||
AccessibilityNodeInfo nodeInfo = getRootNodeInfo();
|
||||
if (nodeInfo != null) {
|
||||
return FindByText(nodeInfo,text);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* 根据Text搜索所有符合条件的节点, 精确搜索方式
|
||||
*/
|
||||
public List<AccessibilityNodeInfo> findNodesByText(String[] text) {
|
||||
AccessibilityNodeInfo nodeInfo = getRootNodeInfo();
|
||||
if (nodeInfo != null) {
|
||||
return FindByText(nodeInfo,text);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* 根据Text搜索所有符合条件的节点, 模糊搜索方式
|
||||
*/
|
||||
public List<AccessibilityNodeInfo> findNodesByContainsText(String text) {
|
||||
AccessibilityNodeInfo nodeInfo = getRootNodeInfo();
|
||||
if (nodeInfo != null) {
|
||||
return FindByContainsText(nodeInfo,text);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* 根据Text搜索所有符合条件的节点, 模糊搜索方式
|
||||
*/
|
||||
public List<AccessibilityNodeInfo> findNodesByContainsText(String[] text) {
|
||||
AccessibilityNodeInfo nodeInfo = getRootNodeInfo();
|
||||
if (nodeInfo != null) {
|
||||
return FindByContainsText(nodeInfo,text);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* 根据Text搜索所有符合条件的节点, 精确搜索方式
|
||||
*/
|
||||
public List<AccessibilityNodeInfo> FindByText(AccessibilityNodeInfo info,String text) {
|
||||
List<AccessibilityNodeInfo> list=new ArrayList<AccessibilityNodeInfo>();
|
||||
if (info.getChildCount() == 0 && info.getText()!=null) {
|
||||
if(info.getText().toString().equals(text))
|
||||
{
|
||||
list.add(info);
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < info.getChildCount(); i++) {
|
||||
if(info.getChild(i)!=null){
|
||||
list.addAll(FindByText(info.getChild(i),text));
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
/**
|
||||
* 根据Text搜索所有符合条件的节点, 精确搜索方式
|
||||
*/
|
||||
public List<AccessibilityNodeInfo> FindByText(AccessibilityNodeInfo info,String[] text) {
|
||||
List<AccessibilityNodeInfo> list=new ArrayList<AccessibilityNodeInfo>();
|
||||
if (info.getChildCount() == 0 && info.getText()!=null) {
|
||||
for (int k=0;k<text.length;k++)
|
||||
{
|
||||
if(info.getText().toString().equals(text[k]))
|
||||
{
|
||||
list.add(info);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < info.getChildCount(); i++) {
|
||||
if(info.getChild(i)!=null){
|
||||
list.addAll(FindByText(info.getChild(i),text));
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
/**
|
||||
* 根据Text搜索所有符合条件的节点, 模糊搜索方式
|
||||
*/
|
||||
public List<AccessibilityNodeInfo> FindByContainsText(AccessibilityNodeInfo info,String[] text) {
|
||||
List<AccessibilityNodeInfo> list=new ArrayList<AccessibilityNodeInfo>();
|
||||
if (info.getChildCount() == 0 && info.getText()!=null) {
|
||||
for (int k=0;k<text.length;k++)
|
||||
{
|
||||
if(info.getText().toString().contains(text[k]))
|
||||
{
|
||||
list.add(info);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < info.getChildCount(); i++) {
|
||||
if(info.getChild(i)!=null){
|
||||
list.addAll(FindByContainsText(info.getChild(i),text));
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
/**
|
||||
* 根据Text搜索所有符合条件的节点, 模糊搜索方式
|
||||
*/
|
||||
public List<AccessibilityNodeInfo> FindByContainsText(AccessibilityNodeInfo info,String text) {
|
||||
List<AccessibilityNodeInfo> list=new ArrayList<AccessibilityNodeInfo>();
|
||||
if (info.getChildCount() == 0 && info.getText()!=null) {
|
||||
if(info.getText().toString().contains(text))
|
||||
{
|
||||
list.add(info);
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < info.getChildCount(); i++) {
|
||||
if(info.getChild(i)!=null){
|
||||
list.addAll(FindByContainsText(info.getChild(i),text));
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
/**
|
||||
* 获取当前页面上的所有控件信息
|
||||
*/
|
||||
public List<AccessibilityNodeInfo> GetAllNodes() {
|
||||
AccessibilityNodeInfo nodeInfo = getRootNodeInfo();
|
||||
if (nodeInfo != null) {
|
||||
return GetAllNodes(nodeInfo);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* 获取当前页面上的所有控件信息
|
||||
*/
|
||||
public List<AccessibilityNodeInfo> GetAllNodes(AccessibilityNodeInfo info) {
|
||||
List<AccessibilityNodeInfo> list=new ArrayList<AccessibilityNodeInfo>();
|
||||
if (info.getChildCount() == 0) {
|
||||
list.add(info);
|
||||
} else {
|
||||
for (int i = 0; i < info.getChildCount(); i++) {
|
||||
list.add(info);
|
||||
if(info.getChild(i)!=null){
|
||||
list.addAll(GetAllNodes(info.getChild(i)));
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
/**
|
||||
* 获取当前页面上的所有没有子控件的控件信息
|
||||
*/
|
||||
public List<AccessibilityNodeInfo> GetAllNoChildsNodes() {
|
||||
AccessibilityNodeInfo nodeInfo = getRootNodeInfo();
|
||||
if (nodeInfo != null) {
|
||||
return GetAllNoChildsNodes(nodeInfo);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* 获取当前页面上的所有没有子控件的控件信息
|
||||
*/
|
||||
public List<AccessibilityNodeInfo> GetAllNoChildsNodes(AccessibilityNodeInfo info) {
|
||||
List<AccessibilityNodeInfo> list=new ArrayList<AccessibilityNodeInfo>();
|
||||
if (info.getChildCount() == 0) {
|
||||
list.add(info);
|
||||
} else {
|
||||
for (int i = 0; i < info.getChildCount(); i++) {
|
||||
if(info.getChild(i)!=null){
|
||||
list.addAll(GetAllNodes(info.getChild(i)));
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
/**
|
||||
* 根据View的ID搜索符合条件的节点,精确搜索方式;
|
||||
* 这个只适用于自己写的界面,因为ID可能重复
|
||||
* api要求18及以上
|
||||
* @param viewId
|
||||
*/
|
||||
public List<AccessibilityNodeInfo> findNodesById(String viewId) {
|
||||
AccessibilityNodeInfo nodeInfo = getRootNodeInfo();
|
||||
if (nodeInfo != null) {
|
||||
if (Build.VERSION.SDK_INT >= 18) {
|
||||
return nodeInfo.findAccessibilityNodeInfosByViewId(viewId);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* 按文本来点击
|
||||
* @param text
|
||||
* @return 是否点击成功
|
||||
*/
|
||||
public boolean clickByText(String text) {
|
||||
return performClick(findNodesByText(text));
|
||||
}
|
||||
/**
|
||||
* 按文本来点击
|
||||
* @param text
|
||||
* @return 是否点击成功
|
||||
*/
|
||||
public boolean clickByText(String[] text) {
|
||||
return performClick(findNodesByText(text));
|
||||
}
|
||||
/**
|
||||
* 按文本来点击,忽略黑名单中的控件
|
||||
* @param text
|
||||
* @return 是否点击成功
|
||||
*/
|
||||
public boolean clickByText(String[] text,Rect[] blackrect) {
|
||||
runOnUiThread(new Runnable(){
|
||||
public void run(){
|
||||
List<AccessibilityNodeInfo> list=findNodesByText(text);
|
||||
if(list==null)
|
||||
{
|
||||
//Toast("界面查找出错...");
|
||||
result_bool=false;
|
||||
}
|
||||
else {
|
||||
for (int i = list.size() - 1; i >= 0; i--) {
|
||||
AccessibilityNodeInfo node = list.get(i);
|
||||
Rect rect = new Rect();
|
||||
node.getBoundsInScreen(rect);
|
||||
for (int r = 0; r < blackrect.length; r++) {
|
||||
if (isIntersect(rect, blackrect[r])) {
|
||||
list.remove(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
result_bool = performClick(list);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return result_bool;
|
||||
}
|
||||
private boolean isIntersect(Rect a, Rect b) {
|
||||
return a.left <= b.right && b.left <= a.right && a.top <= b.bottom
|
||||
&& b.top <= a.bottom;
|
||||
}
|
||||
/**
|
||||
* 根据View的ID搜索符合条件的节点,精确搜索方式;
|
||||
* 这个只适用于自己写的界面,因为ID可能重复
|
||||
* api要求18及以上
|
||||
* @param viewId
|
||||
* @return 是否点击成功
|
||||
*/
|
||||
public boolean clickById(String viewId) {
|
||||
return performClick(findNodesById(viewId));
|
||||
}
|
||||
|
||||
public boolean performClick(List<AccessibilityNodeInfo> nodeInfos) {
|
||||
if (nodeInfos != null && !nodeInfos.isEmpty()) {
|
||||
AccessibilityNodeInfo node;
|
||||
for (int i = 0; i < nodeInfos.size(); i++) {
|
||||
node = nodeInfos.get(i);
|
||||
// 获得点击View的类型
|
||||
AccessibilityLog.printLog("View类型:" + node.getClassName());
|
||||
// 进行模拟点击
|
||||
if (node.isEnabled()) {
|
||||
return ClickByNode(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* 从指定坐标1滑动到指定坐标2
|
||||
* @return 是否点击成功
|
||||
*/
|
||||
public boolean Gesture(int x1,int y1,int x2,int y2,long duration){//仿滑动
|
||||
if(IsExit){return false;}
|
||||
if(mAccessibilityService==null){Toast("辅助服务已失效"); return false;}
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
|
||||
runOnUiThread(new Runnable(){
|
||||
public void run(){
|
||||
Path path = new Path();
|
||||
path.moveTo(x1, y1);//滑动起点
|
||||
path.lineTo(x2, y2);//滑动终点
|
||||
GestureDescription.Builder builder = new GestureDescription.Builder();
|
||||
GestureDescription description = builder.addStroke(new GestureDescription.StrokeDescription(path, 0, duration)).build();
|
||||
//100L 第一个是开始的时间,第二个是持续时间
|
||||
result_bool= mAccessibilityService.dispatchGesture(description, new MyCallBack(), null);
|
||||
}
|
||||
});
|
||||
return result_bool;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* 从指定坐标1滑动到指定坐标2
|
||||
* @return 是否点击成功
|
||||
*/
|
||||
public boolean Gesture(Path path,long startTime,long duration){//仿滑动
|
||||
if(IsExit){return false;}
|
||||
if(mAccessibilityService==null){return false;}
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
|
||||
GestureDescription.Builder builder = new GestureDescription.Builder();
|
||||
GestureDescription description = builder.addStroke(new GestureDescription.StrokeDescription(path, startTime, duration)).build();
|
||||
//100L 第一个是开始的时间,第二个是持续时间
|
||||
return mAccessibilityService.dispatchGesture(description, new MyCallBack(), null);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* 获取控件矩形参数
|
||||
* @return 返回矩形
|
||||
*/
|
||||
public Rect GetBounds(AccessibilityNodeInfo node){
|
||||
Rect rect = new Rect();
|
||||
if(node!=null)
|
||||
{
|
||||
node.getBoundsInScreen(rect);
|
||||
}
|
||||
return rect;
|
||||
}
|
||||
/**
|
||||
* 点击指定控件
|
||||
* @return 是否点击成功
|
||||
*/
|
||||
public boolean ClickByNode(AccessibilityNodeInfo node){//点击
|
||||
if(node!=null)
|
||||
{
|
||||
Rect rect = new Rect();
|
||||
node.getBoundsInScreen(rect);
|
||||
int x=(rect.left+rect.right)/2;
|
||||
int y = (rect.top + rect.bottom) / 2;
|
||||
//设置随机位移,防止作弊被发现
|
||||
int width_d=RandomInt(0,((int)rect.width()/2)-2);
|
||||
int height_d=RandomInt(0,((int)rect.height()/2)-2);
|
||||
int add=RandomInt(0,1);
|
||||
if(add==0)
|
||||
{
|
||||
x=x-width_d;
|
||||
y=y-height_d;
|
||||
}
|
||||
else{
|
||||
x=x+width_d;
|
||||
y=y+height_d;
|
||||
}
|
||||
return Click(x,y);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* 生成随机数
|
||||
* @return
|
||||
*/
|
||||
public int RandomInt(int min,int max)
|
||||
{
|
||||
return (new Random()).nextInt((max - min) + 1) + min;
|
||||
}
|
||||
/**
|
||||
* 生成随机数
|
||||
* @return
|
||||
*/
|
||||
public long RandomLong(long min,long max)
|
||||
{
|
||||
Random random = new Random();
|
||||
return ( long )random.nextDouble()*(max-min) + min;
|
||||
}
|
||||
/**
|
||||
* 点击指定坐标
|
||||
* @return 是否点击成功
|
||||
*/
|
||||
public boolean Click(int x,int y){//点击
|
||||
return Press(x,y,150);
|
||||
}
|
||||
|
||||
/**
|
||||
* 长点击指定坐标
|
||||
* @return 是否点击成功
|
||||
*/
|
||||
public boolean LongClick(int x,int y){//点击
|
||||
return Press(x,y,700);
|
||||
}
|
||||
/**
|
||||
* 点击指定坐标
|
||||
* @return 是否点击成功
|
||||
*/
|
||||
public boolean Press(int x,int y,long delay){//点击
|
||||
return Gesture(x,y,x,y,delay);
|
||||
}
|
||||
/**
|
||||
* 运行app
|
||||
* @return 是否成功
|
||||
*/
|
||||
public boolean LaunchApp(String packageName)
|
||||
{
|
||||
if(IsExit){return false;}
|
||||
Intent intent =mContext.getPackageManager().getLaunchIntentForPackage(packageName);
|
||||
if (intent != null) {
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
mContext.startActivity(intent);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* 安装应用
|
||||
* @param Path
|
||||
*/
|
||||
private void _InstallApk(String Path) {
|
||||
|
||||
Uri uri;
|
||||
File apkFile;
|
||||
try {
|
||||
apkFile = new File(Path);
|
||||
if(!apkFile.exists()){return;}
|
||||
Intent intentInstall = new Intent(Intent.ACTION_VIEW);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
|
||||
|
||||
Uri contentUri = FileProvider.getUriForFile(mContext, "com.rfid.application.MyApplication.provider", apkFile);
|
||||
intentInstall.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intentInstall.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
intentInstall.setDataAndType(contentUri, "application/vnd.android.package-archive");
|
||||
|
||||
}else{
|
||||
intentInstall.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intentInstall.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
|
||||
|
||||
}
|
||||
mContext.startActivity(intentInstall);
|
||||
}
|
||||
catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 休眠多少毫秒
|
||||
*/
|
||||
public void Sleep(long millis) {
|
||||
Date date=new Date();
|
||||
long addtime= date.getTime()+millis;
|
||||
while(addtime>=(new Date()).getTime() && !IsExit) {
|
||||
try {
|
||||
Thread.sleep(10);
|
||||
}
|
||||
catch (Exception e){e.printStackTrace();}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 休眠多少毫秒
|
||||
*/
|
||||
public void Sleep(long millis_min,long millis_max) {
|
||||
long R_millis=RandomLong(millis_min,millis_max);
|
||||
Sleep(R_millis);
|
||||
}
|
||||
/**
|
||||
*Toast提示
|
||||
*/
|
||||
public void Toast(String text)
|
||||
{
|
||||
runOnUiThread(new Runnable(){
|
||||
public void run(){
|
||||
Toast.makeText(mContext.getApplicationContext(), text, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
public final void runOnUiThread(Runnable action) {
|
||||
if(UIHandler==null) {
|
||||
action.run();
|
||||
}else
|
||||
{
|
||||
UIHandler.post(action);
|
||||
}
|
||||
}
|
||||
/**
|
||||
*点击返回键
|
||||
*/
|
||||
public boolean clickBackKey() {
|
||||
return performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);
|
||||
}
|
||||
|
||||
private boolean performGlobalAction(int action) {
|
||||
if(IsExit){return false;}
|
||||
if(mAccessibilityService==null){return false;}
|
||||
runOnUiThread(new Runnable(){
|
||||
public void run(){
|
||||
result_bool= mAccessibilityService.performGlobalAction(action);
|
||||
}
|
||||
});
|
||||
return result_bool;
|
||||
}
|
||||
}
|
59
app/src/main/java/com/itrycn/ta/AccessibilityTaService.java
Normal file
59
app/src/main/java/com/itrycn/ta/AccessibilityTaService.java
Normal file
|
@ -0,0 +1,59 @@
|
|||
package com.itrycn.ta;
|
||||
|
||||
import android.accessibilityservice.AccessibilityService;
|
||||
import android.accessibilityservice.AccessibilityServiceInfo;
|
||||
import android.annotation.TargetApi;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.itrycn.ta.utils.AccessibilityLog;
|
||||
import com.itrycn.tellmenotice.NoticeService;
|
||||
|
||||
/**
|
||||
* Created by popfisher on 2017/7/6.
|
||||
*/
|
||||
|
||||
@TargetApi(25)
|
||||
public class AccessibilityTaService extends AccessibilityService {
|
||||
|
||||
@Override
|
||||
protected void onServiceConnected() {
|
||||
super.onServiceConnected();
|
||||
// 通过代码可以动态配置,但是可配置项少一点
|
||||
// AccessibilityServiceInfo accessibilityServiceInfo = new AccessibilityServiceInfo();
|
||||
// accessibilityServiceInfo.eventTypes = AccessibilityEvent.TYPE_WINDOWS_CHANGED
|
||||
// | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
|
||||
// | AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
|
||||
// | AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED;
|
||||
// accessibilityServiceInfo.feedbackType = AccessibilityServiceInfo.FEEDBACK_ALL_MASK;
|
||||
// accessibilityServiceInfo.notificationTimeout = 0;
|
||||
// accessibilityServiceInfo.flags = AccessibilityServiceInfo.DEFAULT;
|
||||
// setServiceInfo(accessibilityServiceInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAccessibilityEvent(AccessibilityEvent event) {
|
||||
// 此方法是在主线程中回调过来的,所以消息是阻塞执行的
|
||||
// 获取包名
|
||||
if(event.getPackageName()==null)
|
||||
{
|
||||
//Toast.makeText(this, "获取不到包名", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
String pkgName = event.getPackageName().toString();
|
||||
int eventType = event.getEventType();
|
||||
AccessibilityOperator.getInstance().updateEvent(this, event);
|
||||
// try {
|
||||
// Thread.sleep(200);
|
||||
// } catch (Exception e) {}
|
||||
//Toast.makeText(this, "eventType: " + eventType + " pkgName: " + pkgName, Toast.LENGTH_SHORT).show();
|
||||
NoticeService.CurPackageName=pkgName;
|
||||
AccessibilityLog.printLog("eventType: " + eventType + " pkgName: " + pkgName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInterrupt() {
|
||||
|
||||
}
|
||||
}
|
27
app/src/main/java/com/itrycn/ta/MyCallBack.java
Normal file
27
app/src/main/java/com/itrycn/ta/MyCallBack.java
Normal file
|
@ -0,0 +1,27 @@
|
|||
package com.itrycn.ta;
|
||||
|
||||
import android.accessibilityservice.AccessibilityService;
|
||||
import android.accessibilityservice.GestureDescription;
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
//模拟手势的监听
|
||||
@RequiresApi(api = Build.VERSION_CODES.N)
|
||||
public class MyCallBack extends AccessibilityService.GestureResultCallback {
|
||||
public MyCallBack() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCompleted(GestureDescription gestureDescription) {
|
||||
super.onCompleted(gestureDescription);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancelled(GestureDescription gestureDescription) {
|
||||
super.onCancelled(gestureDescription);
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package com.itrycn.ta;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
/**
|
||||
* Created by popfisher on 2017/7/6.
|
||||
*/
|
||||
|
||||
public class OpenAccessibilitySettingHelper {
|
||||
private static final String ACTION = "action";
|
||||
private static final String ACTION_START_ACCESSIBILITY_SETTING = "action_start_accessibility_setting";
|
||||
|
||||
public static void jumpToSettingPage(Context context) {
|
||||
try {
|
||||
Intent intent = new Intent(context, AccessibilityOpenHelperActivity.class);
|
||||
intent.putExtra(ACTION, ACTION_START_ACCESSIBILITY_SETTING);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
context.startActivity(intent);
|
||||
} catch (Exception ignore) {}
|
||||
}
|
||||
}
|
158
app/src/main/java/com/itrycn/ta/script/ScriptSystemInfo.java
Normal file
158
app/src/main/java/com/itrycn/ta/script/ScriptSystemInfo.java
Normal file
|
@ -0,0 +1,158 @@
|
|||
package com.itrycn.ta.script;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.media.AudioManager;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Size;
|
||||
|
||||
import com.itrycn.ta.AccessibilityOperator;
|
||||
|
||||
public class ScriptSystemInfo {
|
||||
private Context mContext;
|
||||
private static ScriptSystemInfo mInstance = new ScriptSystemInfo();
|
||||
|
||||
private ScriptSystemInfo() {
|
||||
}
|
||||
|
||||
public static ScriptSystemInfo getInstance() {
|
||||
return mInstance;
|
||||
}
|
||||
|
||||
public void init(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取屏幕分辨率
|
||||
*
|
||||
* @return 返回分辨率
|
||||
*/
|
||||
public Size GetScreen() {
|
||||
DisplayMetrics dm = new DisplayMetrics();
|
||||
dm = mContext.getResources().getDisplayMetrics();
|
||||
return new Size(dm.widthPixels, dm.heightPixels);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前手机系统版本号
|
||||
*
|
||||
* @return 系统版本号
|
||||
*/
|
||||
public String getSystemVersion() {
|
||||
return android.os.Build.VERSION.RELEASE;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取手机型号
|
||||
*
|
||||
* @return 手机型号
|
||||
*/
|
||||
public String getSystemModel() {
|
||||
return android.os.Build.MODEL;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取手机厂商
|
||||
*
|
||||
* @return 手机厂商
|
||||
*/
|
||||
public String getDeviceBrand() {
|
||||
return android.os.Build.BRAND;
|
||||
}
|
||||
|
||||
public int getVersion(String packageName) {
|
||||
try {
|
||||
PackageManager manager = mContext.getPackageManager();
|
||||
PackageInfo info = manager.getPackageInfo(packageName, 0);
|
||||
return info.versionCode;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 设置媒体音量
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public void setMusicVolume(int value)
|
||||
{
|
||||
AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
|
||||
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, value, AudioManager.FLAG_PLAY_SOUND);
|
||||
}
|
||||
/**
|
||||
* 获取媒体音量
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getMusicVolume()
|
||||
{
|
||||
AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
|
||||
return audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
|
||||
}
|
||||
/**
|
||||
* 设置闹钟音量
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public void setAlarmVolume(int value)
|
||||
{
|
||||
AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
|
||||
audioManager.setStreamVolume(AudioManager.STREAM_ALARM, value, AudioManager.FLAG_PLAY_SOUND);
|
||||
}
|
||||
/**
|
||||
* 获取闹钟音量
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getAlarmVolume()
|
||||
{
|
||||
AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
|
||||
return audioManager.getStreamVolume(AudioManager.STREAM_ALARM);
|
||||
}
|
||||
/**
|
||||
* 设置通知音量
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public void setNotificationVolume(int value)
|
||||
{
|
||||
AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
|
||||
audioManager.setStreamVolume(AudioManager.STREAM_NOTIFICATION, value, AudioManager.FLAG_PLAY_SOUND);
|
||||
}
|
||||
/**
|
||||
* 获取通知音量
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getNotificationVolume()
|
||||
{
|
||||
AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
|
||||
return audioManager.getStreamVolume(AudioManager.STREAM_NOTIFICATION);
|
||||
}
|
||||
/**
|
||||
* 设置电话铃声音量
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public void setRingVolume(int value)
|
||||
{
|
||||
AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
|
||||
audioManager.setStreamVolume(AudioManager.STREAM_RING, value, AudioManager.FLAG_PLAY_SOUND);
|
||||
}
|
||||
/**
|
||||
* 获取电话铃声音量
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getRingVolume()
|
||||
{
|
||||
AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
|
||||
return audioManager.getStreamVolume(AudioManager.STREAM_RING);
|
||||
}
|
||||
}
|
15
app/src/main/java/com/itrycn/ta/utils/AccessibilityLog.java
Normal file
15
app/src/main/java/com/itrycn/ta/utils/AccessibilityLog.java
Normal file
|
@ -0,0 +1,15 @@
|
|||
package com.itrycn.ta.utils;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* Created by popfisher on 2017/7/11.
|
||||
*/
|
||||
|
||||
public class AccessibilityLog {
|
||||
|
||||
private static final String TAG = "AccessibilityService";
|
||||
public static void printLog(String logMsg) {
|
||||
//if (!BuildConfig.DEBUG) return;
|
||||
//Log.d(TAG, logMsg);
|
||||
}
|
||||
}
|
59
app/src/main/java/com/itrycn/ta/utils/AccessibilityUtil.java
Normal file
59
app/src/main/java/com/itrycn/ta/utils/AccessibilityUtil.java
Normal file
|
@ -0,0 +1,59 @@
|
|||
package com.itrycn.ta.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.itrycn.ta.AccessibilityTaService;
|
||||
|
||||
/**
|
||||
* 辅助功能相关检查的帮助类
|
||||
*/
|
||||
public class AccessibilityUtil {
|
||||
private static final String ACCESSIBILITY_SERVICE_PATH = AccessibilityTaService.class.getCanonicalName();
|
||||
/**
|
||||
* 判断是否有辅助功能权限
|
||||
*
|
||||
* @param context
|
||||
* @return
|
||||
*/
|
||||
public static boolean isAccessibilitySettingsOn(Context context) {
|
||||
if (context == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int accessibilityEnabled = 0;
|
||||
try {
|
||||
accessibilityEnabled = Settings.Secure.getInt(context.getApplicationContext().getContentResolver(), Settings.Secure.ACCESSIBILITY_ENABLED);
|
||||
} catch (Settings.SettingNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
String packageName = context.getPackageName();
|
||||
final String serviceStr = packageName + "/" + ACCESSIBILITY_SERVICE_PATH;
|
||||
AccessibilityLog.printLog("serviceStr: " + serviceStr);
|
||||
if (accessibilityEnabled == 1) {
|
||||
TextUtils.SimpleStringSplitter mStringColonSplitter = new TextUtils.SimpleStringSplitter(':');
|
||||
|
||||
String settingValue = Settings.Secure.getString(context.getApplicationContext().getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
|
||||
if (settingValue != null) {
|
||||
TextUtils.SimpleStringSplitter splitter = mStringColonSplitter;
|
||||
splitter.setString(settingValue);
|
||||
while (splitter.hasNext()) {
|
||||
String accessabilityService = splitter.next();
|
||||
|
||||
if (accessabilityService.equalsIgnoreCase(serviceStr)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static Intent getAccessibilitySettingPageIntent(Context context) {
|
||||
// 一些品牌的手机可能不是这个Intent,需要适配
|
||||
return new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
|
||||
}
|
||||
}
|
|
@ -11,14 +11,20 @@ import android.net.Uri;
|
|||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.itrycn.ta.AccessibilityOperator;
|
||||
import com.itrycn.ta.OpenAccessibilitySettingHelper;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
ScreenListener screenlistener;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public static Context mContext;
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
@ -27,6 +33,12 @@ public class MainActivity extends AppCompatActivity {
|
|||
{
|
||||
gotoNotificationAccessSetting(MainActivity.this);
|
||||
}
|
||||
AccessibilityOperator.getInstance().init(this);
|
||||
OpenAccessibilitySettingHelper.jumpToSettingPage(this);
|
||||
if (!Settings.canDrawOverlays(this)) {
|
||||
Toast.makeText(this,"请授权app的悬浮框权限", Toast.LENGTH_SHORT).show();
|
||||
startActivityForResult(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName())), 0);
|
||||
}
|
||||
Intent intent2 = new Intent(MainActivity.this,NoticeService.class);
|
||||
startService(intent2);
|
||||
startFloatingButtonService();
|
||||
|
@ -57,9 +69,9 @@ public class MainActivity extends AppCompatActivity {
|
|||
AudioManager audioManager = (AudioManager) MainActivity.this.getSystemService(Context.AUDIO_SERVICE);
|
||||
int NoticeVolume= audioManager.getStreamVolume(AudioManager.STREAM_NOTIFICATION);
|
||||
int NoticeMaxVolume= audioManager.getStreamMaxVolume(AudioManager.STREAM_NOTIFICATION);
|
||||
if(NoticeVolume<NoticeMaxVolume)
|
||||
if(NoticeVolume<100)
|
||||
{
|
||||
audioManager.setStreamVolume(AudioManager.STREAM_NOTIFICATION, NoticeMaxVolume, AudioManager.FLAG_VIBRATE);
|
||||
audioManager.setStreamVolume(AudioManager.STREAM_NOTIFICATION, 100, AudioManager.FLAG_VIBRATE);
|
||||
}
|
||||
//endregion
|
||||
//Log.e("onScreenOff", "onScreenOff");
|
||||
|
@ -67,6 +79,14 @@ public class MainActivity extends AppCompatActivity {
|
|||
});
|
||||
}
|
||||
@Override
|
||||
protected void onStart() {
|
||||
if(!AccessibilityOperator.getInstance().isServiceRunning())
|
||||
{
|
||||
Toast.makeText(this,"辅助服务没有在运行。", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
super.onStart();
|
||||
}
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
screenlistener.unregisterListener();
|
||||
super.onDestroy();
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
package com.itrycn.tellmenotice;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.Application;
|
||||
import android.app.Notification;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Color;
|
||||
|
@ -12,12 +16,17 @@ import android.media.AudioAttributes;
|
|||
import android.media.AudioManager;
|
||||
import android.media.MediaPlayer;
|
||||
import android.media.SoundPool;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.NetworkInfo;
|
||||
import android.net.wifi.WifiInfo;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.provider.Settings;
|
||||
import android.service.notification.NotificationListenerService;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
|
@ -37,11 +46,12 @@ import java.util.ArrayList;
|
|||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class NoticeService extends NotificationListenerService {
|
||||
public static boolean isStarted = false;
|
||||
|
||||
public static String CurPackageName = "";
|
||||
private WindowManager windowManager;
|
||||
private WindowManager.LayoutParams layoutParams;
|
||||
@Override
|
||||
|
@ -64,6 +74,8 @@ public class NoticeService extends NotificationListenerService {
|
|||
MP3_Ring= sp.load(this,R.raw.ring,1);
|
||||
MP3_kuaidi= sp.load(this,R.raw.kuaidi,1);
|
||||
MP3_Dingding= sp.load(this,R.raw.dingding,1);
|
||||
MP3_TaoCode= sp.load(this,R.raw.taocode,1);
|
||||
MP3_Buy0= sp.load(this,R.raw.buy0,1);
|
||||
//windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
|
||||
//layoutParams = new WindowManager.LayoutParams();
|
||||
//if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
|
@ -86,6 +98,8 @@ public class NoticeService extends NotificationListenerService {
|
|||
sp.unload(MP3_Ring);
|
||||
sp.unload(MP3_kuaidi);
|
||||
sp.unload(MP3_Dingding);
|
||||
sp.unload(MP3_TaoCode);
|
||||
sp.unload(MP3_Buy0);
|
||||
super.onDestroy();
|
||||
}
|
||||
@Override
|
||||
|
@ -101,6 +115,8 @@ public class NoticeService extends NotificationListenerService {
|
|||
int MP3_Ring;
|
||||
int MP3_kuaidi;
|
||||
int MP3_Dingding;
|
||||
int MP3_TaoCode;
|
||||
int MP3_Buy0;
|
||||
String Last_packageName="";
|
||||
String Last_Title="";
|
||||
String Last_Content="";
|
||||
|
@ -125,7 +141,33 @@ public class NoticeService extends NotificationListenerService {
|
|||
if(hour>=23 || hour<7) {return; } //23点到早上7点,免打扰时间段
|
||||
//if(hour>=23 && hour<7) {return; }
|
||||
}
|
||||
AudioManager audioManager = (AudioManager) getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
|
||||
int NoticeVolume= audioManager.getStreamVolume(AudioManager.STREAM_NOTIFICATION);
|
||||
int NoticeMaxVolume= audioManager.getStreamMaxVolume(AudioManager.STREAM_NOTIFICATION);
|
||||
audioManager.setStreamVolume(AudioManager.STREAM_NOTIFICATION, 100, AudioManager.FLAG_VIBRATE);
|
||||
sp.play(SoundId, 1f, 1.0f,1,loop,1);
|
||||
//audioManager.setStreamVolume(AudioManager.STREAM_NOTIFICATION, NoticeVolume, AudioManager.FLAG_VIBRATE);
|
||||
}
|
||||
//在进程中去寻找当前APP的信息,判断是否在前台运行
|
||||
private boolean isAppOnForeground(String packageName) {
|
||||
return NoticeService.CurPackageName.equals(packageName);
|
||||
}
|
||||
private boolean IsGameMode()
|
||||
{
|
||||
if(isAppOnForeground("com.tencent.tmgp.sgame"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* 获取wifi名称(必须要有GPS定位权限)
|
||||
*/
|
||||
private String getWifiName()
|
||||
{
|
||||
WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(WIFI_SERVICE);
|
||||
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
|
||||
return wifiInfo.getSSID();
|
||||
}
|
||||
private long LastDoorRingTime=0;
|
||||
@Override
|
||||
|
@ -169,8 +211,10 @@ public class NoticeService extends NotificationListenerService {
|
|||
for (int i = 0; i < strArr.length; ++i){
|
||||
if(Content.contains(strArr[i]))
|
||||
{
|
||||
FloatView fv=new FloatView(this);
|
||||
fv.showFloatingWindow(notice,Title,Content);
|
||||
if(!IsGameMode()) {
|
||||
FloatView fv = new FloatView(this);
|
||||
fv.showFloatingWindow(notice, Title, Content);
|
||||
}
|
||||
//showFloatingWindow(notice,Title,Content);
|
||||
PlaySound(MP3_mm,0,false);
|
||||
haveInfo=true;
|
||||
|
@ -179,22 +223,52 @@ public class NoticeService extends NotificationListenerService {
|
|||
}
|
||||
}
|
||||
//endregion
|
||||
//region 0元购
|
||||
if(!haveInfo)
|
||||
{
|
||||
if(Title.contains("球球") || Content.contains("球球")) {
|
||||
String[] strArr2 = "球球独家;口令;拍下;http;拍第;体验;福利;一单;元抢;内部;复制打开;漏洞;好评;0元;抢到;免单;独家".split(";");
|
||||
for (int i = 0; i < strArr2.length; ++i) {
|
||||
if (Content.contains(strArr2[i])) {
|
||||
if(!IsGameMode()) {
|
||||
FloatView fv = new FloatView(this);
|
||||
fv.showFloatingWindow(notice, Title, Content, Color.parseColor("#FF0000"));
|
||||
}
|
||||
//showFloatingWindow(notice,Title,Content);
|
||||
int hour = c.get(Calendar.HOUR_OF_DAY); // 时
|
||||
if(getWifiName().indexOf("当游")<0) {
|
||||
PlaySound(MP3_Buy0, 0, false);
|
||||
}
|
||||
else {
|
||||
PlaySound(MP3_Dingding, 0, false);
|
||||
}
|
||||
haveTip=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//endregion
|
||||
//region 淘口令
|
||||
if(!haveInfo)
|
||||
{
|
||||
String[] strArr2 = "tb.cn;淘tao;/宝;".split(";");
|
||||
for (int i = 0; i < strArr2.length; ++i) {
|
||||
if (Content.contains(strArr2[i])) {
|
||||
if(!IsGameMode()) {
|
||||
FloatView fv = new FloatView(this);
|
||||
fv.showFloatingWindow(notice, Title, Content, Color.parseColor("#FF0000"));
|
||||
}
|
||||
int hour = c.get(Calendar.HOUR_OF_DAY); // 时
|
||||
if(getWifiName().indexOf("当游")<0) {
|
||||
PlaySound(MP3_TaoCode, 0, false);
|
||||
}
|
||||
haveTip=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//endregion
|
||||
}
|
||||
else if(packageName.equals("com.xiaomi.smarthome")) //如果是米家app
|
||||
{
|
||||
|
@ -204,24 +278,25 @@ public class NoticeService extends NotificationListenerService {
|
|||
{
|
||||
if(LastDoorRingTime+60000>=NowTime){return;} //如果1分钟内有新的门铃提醒,则自动忽略
|
||||
LastDoorRingTime=c.getTime().getTime();
|
||||
FloatView fv=new FloatView(this);
|
||||
fv.showFloatingWindow(notice,Content,Title, Color.parseColor("#02BD9D"));
|
||||
PlaySound(MP3_Ring,2,false);
|
||||
if(!IsGameMode()) {
|
||||
FloatView fv = new FloatView(this);
|
||||
fv.showFloatingWindow(notice, Content, Title, Color.parseColor("#02BD9D"));
|
||||
}
|
||||
PlaySound(MP3_Ring,1,false);
|
||||
haveTip=true;
|
||||
}
|
||||
else
|
||||
{
|
||||
FloatView fv=new FloatView(this);
|
||||
if(Title.equals("自动化通知"))
|
||||
{
|
||||
fv.showFloatingWindow(notice,Title, Content, Color.parseColor("#02BD9D"));
|
||||
}
|
||||
else {
|
||||
if(Title.length()>=Content.length()) {
|
||||
if(!IsGameMode()) {
|
||||
FloatView fv = new FloatView(this);
|
||||
if (Title.equals("自动化通知")) {
|
||||
fv.showFloatingWindow(notice, Title, Content, Color.parseColor("#02BD9D"));
|
||||
} else {
|
||||
if (Title.length() >= Content.length()) {
|
||||
fv.showFloatingWindow(notice, Content, Title, Color.parseColor("#02BD9D"));
|
||||
} else {
|
||||
fv.showFloatingWindow(notice, Title, Content, Color.parseColor("#02BD9D"));
|
||||
}
|
||||
else {
|
||||
fv.showFloatingWindow(notice,Title, Content, Color.parseColor("#02BD9D"));
|
||||
}
|
||||
}
|
||||
haveTip=true;
|
||||
|
@ -236,8 +311,10 @@ public class NoticeService extends NotificationListenerService {
|
|||
for (int i = 0; i < strArr.length; ++i){
|
||||
if(Title.contains(strArr[i]) || Content.contains(strArr[i]))
|
||||
{
|
||||
FloatView fv=new FloatView(this);
|
||||
fv.showFloatingWindow(notice,Title,Content);
|
||||
if(!IsGameMode()) {
|
||||
FloatView fv = new FloatView(this);
|
||||
fv.showFloatingWindow(notice, Title, Content);
|
||||
}
|
||||
PlaySound(MP3_kuaidi,0,false);
|
||||
haveTip=true;
|
||||
break;
|
||||
|
@ -252,27 +329,23 @@ public class NoticeService extends NotificationListenerService {
|
|||
if(Title.contains("正在运行")){return;}
|
||||
if(Title.contains("哈啰顺风车运行中") || Content.contains("哈啰顺风车运行中")){return;}
|
||||
if(Title.contains("顺风车出行中") || Content.contains("顺风车出行中")){return;}
|
||||
if(!IsGameMode()) {
|
||||
//region 如果是顺风车线路
|
||||
FloatView fv=new FloatView(this);
|
||||
if(packageName.equals("com.jingyao.easybike"))
|
||||
{
|
||||
fv.showFloatingWindow(notice,Title, Content, Color.parseColor("#0391FF"));
|
||||
}
|
||||
else if(packageName.equals("com.sdu.didi.psnger"))
|
||||
{
|
||||
fv.showFloatingWindow(notice,Title, Content, Color.parseColor("#F8934C"));
|
||||
}
|
||||
else if(packageName.equals("com.didapinche.booking"))
|
||||
{
|
||||
fv.showFloatingWindow(notice,Title, Content, Color.parseColor("#FED051"));
|
||||
}
|
||||
else {
|
||||
FloatView fv = new FloatView(this);
|
||||
if (packageName.equals("com.jingyao.easybike")) {
|
||||
fv.showFloatingWindow(notice, Title, Content, Color.parseColor("#0391FF"));
|
||||
} else if (packageName.equals("com.sdu.didi.psnger")) {
|
||||
fv.showFloatingWindow(notice, Title, Content, Color.parseColor("#F8934C"));
|
||||
} else if (packageName.equals("com.didapinche.booking")) {
|
||||
fv.showFloatingWindow(notice, Title, Content, Color.parseColor("#FED051"));
|
||||
} else {
|
||||
fv.showFloatingWindow(notice, Title, Content);
|
||||
}
|
||||
haveTip=true;
|
||||
PlaySound(MP3_Dingding,0,false);
|
||||
haveTip = true;
|
||||
PlaySound(MP3_Dingding, 0, false);
|
||||
//endregion
|
||||
}
|
||||
}
|
||||
else if(packageName.equals("com.taobao.taobao")
|
||||
|| packageName.equals("com.jingdong.app.mall")
|
||||
|| packageName.equals("com.xunmeng.pinduoduo")) //如果是淘宝或京东或拼多多
|
||||
|
@ -282,8 +355,10 @@ public class NoticeService extends NotificationListenerService {
|
|||
for (int i = 0; i < strArr.length; ++i){
|
||||
if(Title.contains(strArr[i]) || Content.contains(strArr[i]))
|
||||
{
|
||||
FloatView fv=new FloatView(this);
|
||||
fv.showFloatingWindow(notice,Title,Content, Color.parseColor("#FD5C02"));
|
||||
if(!IsGameMode()) {
|
||||
FloatView fv = new FloatView(this);
|
||||
fv.showFloatingWindow(notice, Title, Content, Color.parseColor("#FD5C02"));
|
||||
}
|
||||
PlaySound(MP3_Dingding,0,false);
|
||||
haveTip=true;
|
||||
break;
|
||||
|
|
BIN
app/src/main/res/raw/buy0.mp3
Normal file
BIN
app/src/main/res/raw/buy0.mp3
Normal file
Binary file not shown.
BIN
app/src/main/res/raw/taocode.mp3
Normal file
BIN
app/src/main/res/raw/taocode.mp3
Normal file
Binary file not shown.
|
@ -1,4 +1,6 @@
|
|||
<resources>
|
||||
<string name="app_name">智能管家</string>
|
||||
<string name="app_state">睿元智能管家,你的私人管家。\n1.可以帮你监控系统通知,自动筛选对你有用的内容。\n2.不同通知展现不同的提醒界面和声音。</string>
|
||||
<string name="accessibility_tip">Ta辅助</string>
|
||||
<string name="accessibility_desc">开启辅助功能,让你的手机更智能一点</string>
|
||||
</resources>
|
8
app/src/main/res/xml/accessibility_config.xml
Normal file
8
app/src/main/res/xml/accessibility_config.xml
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:accessibilityEventTypes="typeAllMask"
|
||||
android:accessibilityFeedbackType="feedbackGeneric"
|
||||
android:canRetrieveWindowContent="true"
|
||||
android:description="@string/accessibility_desc"
|
||||
android:canPerformGestures="true"
|
||||
android:notificationTimeout="1000" />
|
Loading…
Reference in New Issue
Block a user