diff --git a/README.md b/README.md
index d428146..240d9ca 100644
--- a/README.md
+++ b/README.md
@@ -74,6 +74,9 @@ V免签为完全开源项目,开源项目意味着作者没有任何收入来
+ 微信收款商业版店员到账收款通知
## 更新记录
+ + v1.7(2019.05.17)
+ + 删除辅助功能依赖,改为使用通知使用权进行监听,修复一大堆bug,建议更新到该版本
+
+ v1.6.2(2019.05.17)
+ 增加微信收款商业版到账支持
diff --git a/app/app-release.apk b/app/app-release.apk
index 91f1314..cdeffbf 100644
Binary files a/app/app-release.apk and b/app/app-release.apk differ
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 290dc29..7e35af6 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -10,7 +10,6 @@
-
-
-
-
-
-
{
-
- private int code;
- private String msg;
- private V data;
-
- public int getCode() {
- return code;
- }
-
- public void setCode(int code) {
- this.code = code;
- }
-
- public String getMsg() {
- return msg;
- }
-
- public void setMsg(String msg) {
- this.msg = msg;
- }
-
- public V getData() {
- return data;
- }
-
- public void setData(V data) {
- this.data = data;
- }
-}
diff --git a/app/src/main/java/com/vone/vmq/MainActivity.java b/app/src/main/java/com/vone/vmq/MainActivity.java
index 126fae2..2c695be 100644
--- a/app/src/main/java/com/vone/vmq/MainActivity.java
+++ b/app/src/main/java/com/vone/vmq/MainActivity.java
@@ -47,18 +47,16 @@
import okhttp3.Response;
public class MainActivity extends AppCompatActivity{
- Button btnQrCode;
- Button btnStart;
- Button btnInput;
- TextView txthost; // 结果
- TextView txtkey; // 结果
- boolean isOk = false;
- public static String TAG = "MainActivity";
+ private TextView txthost;
+ private TextView txtkey;
- public static String host;
- public static String key;
+ private boolean isOk = false;
+ private static String TAG = "MainActivity";
+
+ private static String host;
+ private static String key;
int id = 0;
@@ -68,28 +66,19 @@ protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
- //初始化界面
- btnQrCode = (Button) findViewById(R.id.btn_qrcode);//扫码配置
- btnInput = (Button) findViewById(R.id.btn_input);//手动配置
- btnStart = (Button) findViewById(R.id.btn_start);//开启服务
txthost = (TextView) findViewById(R.id.txt_host);
txtkey = (TextView) findViewById(R.id.txt_key);
- //检测服务是否在线
- if(isAccessibilitySettingsOn(this)){
- btnStart.setText("检测服务状态");
- }
+ //检测通知使用权是否启用
if (!isNotificationListenersEnabled()) {
+ //跳转到通知使用权页面
gotoNotificationAccessSetting();
}
-
-// if (!isNotificationListenerServiceEnabled(this)){
-//
-// }
+ //重启监听服务
toggleNotificationListenerService(this);
@@ -108,6 +97,9 @@ protected void onCreate(Bundle savedInstanceState) {
}
+
+
+
//扫码配置
public void startQrCode(View v) {
// 申请相机权限
@@ -146,20 +138,15 @@ public void onClick(DialogInterface dialog, int which) {
String t = String.valueOf(new Date().getTime());
String sign = md5(t+tmp[1]);
- //1.创建OkHttpClient对象
+
OkHttpClient okHttpClient = new OkHttpClient();
- //2.创建Request对象,设置一个url地址(百度地址),设置请求方式。
Request request = new Request.Builder().url("http://"+tmp[0]+"/appHeart?t="+t+"&sign="+sign).method("GET",null).build();
- //3.创建一个call对象,参数就是Request请求对象
Call call = okHttpClient.newCall(request);
- //4.请求加入调度,重写回调方法
call.enqueue(new Callback() {
- //请求失败执行的方法
@Override
public void onFailure(Call call, IOException e) {
}
- //请求成功执行的方法
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.d(TAG, "onResponse: "+response.body().string());
@@ -178,12 +165,9 @@ public void onResponse(Call call, Response response) throws IOException {
host = tmp[0];
key = tmp[1];
- //步骤2-1:创建一个SharedPreferences.Editor接口对象,lock表示要写入的XML文件名,MODE_WORLD_WRITEABLE写操作
SharedPreferences.Editor editor = getSharedPreferences("vone", MODE_PRIVATE).edit();
- //步骤2-2:将获取过来的值放入文件
editor.putString("host", host);
editor.putString("key", key);
- //步骤3:提交
editor.commit();
}
@@ -191,143 +175,37 @@ public void onResponse(Call call, Response response) throws IOException {
builder.show();
}
- //启动服务
+ //检测心跳
public void doStart(View view) {
if (isOk==false){
Toast.makeText(MainActivity.this, "请您先配置!", Toast.LENGTH_SHORT).show();
return;
}
- if (!isAccessibilitySettingsOn(this)) {
- Toast.makeText(MainActivity.this, "辅助功能未开启,请您前往开启!", Toast.LENGTH_SHORT).show();
- Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
- startActivity(intent);
- return;
- }
-
-// if(!notificationListenerEnable()){
-// Toast.makeText(MainActivity.this, "通知使用权权限未授予,请您前往授权!", Toast.LENGTH_SHORT).show();
-// gotoNotificationAccessSetting(this);
-// return;
-// }
-
- if (btnStart.getText().equals("开启服务")){
- btnStart.setText("检测服务状态");
- Toast.makeText(MainActivity.this, "开启成功!", Toast.LENGTH_SHORT).show();
- }else{
-
- String t = String.valueOf(new Date().getTime());
- String sign = md5(t+key);
-
- //1.创建OkHttpClient对象
- OkHttpClient okHttpClient = new OkHttpClient();
- //2.创建Request对象,设置一个url地址(百度地址),设置请求方式。
- Request request = new Request.Builder().url("http://"+host+"/appHeart?t="+t+"&sign="+sign).method("GET",null).build();
- //3.创建一个call对象,参数就是Request请求对象
- Call call = okHttpClient.newCall(request);
- //4.请求加入调度,重写回调方法
- call.enqueue(new Callback() {
- //请求失败执行的方法
- @Override
- public void onFailure(Call call, IOException e) {
- Looper.prepare();
- Toast.makeText(MainActivity.this, "心跳状态错误,请检查配置是否正确!", Toast.LENGTH_SHORT).show();
- Looper.loop();
- }
- //请求成功执行的方法
- @Override
- public void onResponse(Call call, Response response) throws IOException {
- //Log.d(TAG, "onResponse heard: "+response.body().string());
- Looper.prepare();
- Toast.makeText(MainActivity.this, "程序运行正常,心跳返回:"+response.body().string(), Toast.LENGTH_LONG).show();
- Looper.loop();
- }
- });
-
-
-
- }
- }
+ String t = String.valueOf(new Date().getTime());
+ String sign = md5(t+key);
- private boolean isAccessibilitySettingsOn(Context mContext) {
- int accessibilityEnabled = 0;
- // TestService为对应的服务
- final String service = getPackageName() + "/" + NeNotificationService.class.getCanonicalName();
- Log.i(TAG, "service:" + service);
- // com.z.buildingaccessibilityservices/android.accessibilityservice.AccessibilityService
- try {
- accessibilityEnabled = Settings.Secure.getInt(mContext.getApplicationContext().getContentResolver(),
- android.provider.Settings.Secure.ACCESSIBILITY_ENABLED);
- Log.v(TAG, "accessibilityEnabled = " + accessibilityEnabled);
- } catch (Settings.SettingNotFoundException e) {
- Log.e(TAG, "Error finding setting, default accessibility to not found: " + e.getMessage());
- }
- TextUtils.SimpleStringSplitter mStringColonSplitter = new TextUtils.SimpleStringSplitter(':');
-
- if (accessibilityEnabled == 1) {
- Log.v(TAG, "***ACCESSIBILITY IS ENABLED*** -----------------");
- String settingValue = Settings.Secure.getString(mContext.getApplicationContext().getContentResolver(),
- Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
- // com.z.buildingaccessibilityservices/com.z.buildingaccessibilityservices.TestService
- if (settingValue != null) {
- mStringColonSplitter.setString(settingValue);
- while (mStringColonSplitter.hasNext()) {
- String accessibilityService = mStringColonSplitter.next();
-
- Log.v(TAG, "-------------- > accessibilityService :: " + accessibilityService + " " + service);
- if (accessibilityService.equalsIgnoreCase(service)) {
- Log.v(TAG, "We've found the correct setting - accessibility is switched on!");
- return true;
- }
- }
+ OkHttpClient okHttpClient = new OkHttpClient();
+ Request request = new Request.Builder().url("http://"+host+"/appHeart?t="+t+"&sign="+sign).method("GET",null).build();
+ Call call = okHttpClient.newCall(request);
+ call.enqueue(new Callback() {
+ @Override
+ public void onFailure(Call call, IOException e) {
+ Looper.prepare();
+ Toast.makeText(MainActivity.this, "心跳状态错误,请检查配置是否正确!", Toast.LENGTH_SHORT).show();
+ Looper.loop();
}
- } else {
- Log.v(TAG, "***ACCESSIBILITY IS DISABLED***");
- }
- return false;
- }
-
-
- private boolean notificationListenerEnable() {
- boolean enable = false;
- String packageName = getPackageName();
- String flat= Settings.Secure.getString(getContentResolver(),"enabled_notification_listeners");
- if (flat != null) {
- enable= flat.contains(packageName);
- }
- return enable;
- }
- private boolean gotoNotificationAccessSetting(Context context) {
- try {
- Intent intent = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- context.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");
- context.startActivity(intent);
- return true;
- } catch(Exception ex) {
- ex.printStackTrace();
+ @Override
+ public void onResponse(Call call, Response response) throws IOException {
+ Looper.prepare();
+ Toast.makeText(MainActivity.this, "心跳返回:"+response.body().string(), Toast.LENGTH_LONG).show();
+ Looper.loop();
}
- return false;
- }
+ });
}
-
-
-
-
+ //检测监听
public void checkPush(View v){
-// if (!btnStart.getText().equals("检测服务状态")){
-// Toast.makeText(MainActivity.this, "请先开启服务!", Toast.LENGTH_SHORT).show();
-// return;
-// }
Notification mNotification;
NotificationManager mNotificationManager;
@@ -335,41 +213,27 @@ public void checkPush(View v){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- //ChannelId为"1",ChannelName为"Channel1"
NotificationChannel channel = new NotificationChannel("1",
"Channel1", NotificationManager.IMPORTANCE_DEFAULT);
- channel.enableLights(true); //是否在桌面icon右上角展示小红点
- channel.setLightColor(Color.GREEN); //小红点颜色
- channel.setShowBadge(true); //是否在久按桌面图标时显示此渠道的通知
+ channel.enableLights(true);
+ channel.setLightColor(Color.GREEN);
+ channel.setShowBadge(true);
mNotificationManager.createNotificationChannel(channel);
- Notification.Builder builder = new Notification.Builder(this,"1"); //与channelId对应
+ Notification.Builder builder = new Notification.Builder(this,"1");
mNotification = builder
- // 设置小图标
.setSmallIcon(R.mipmap.ic_launcher)
.setTicker("这是一条测试推送信息,如果程序正常,则会提示监听权限正常")
- // 设置标题
.setContentTitle("V免签测试推送")
- // 设置内容
.setContentText("这是一条测试推送信息,如果程序正常,则会提示监听权限正常")
.build();
}else{
mNotification = new Notification.Builder(MainActivity.this)
- // 设置小图标
.setSmallIcon(R.mipmap.ic_launcher)
.setTicker("这是一条测试推送信息,如果程序正常,则会提示监听权限正常")
- // 设置标题
.setContentTitle("V免签测试推送")
- // 设置内容
.setContentText("这是一条测试推送信息,如果程序正常,则会提示监听权限正常")
-
- // 设置Notification提示铃声为系统默认铃声
- .setSound(
- RingtoneManager.getActualDefaultRingtoneUri(
- getBaseContext(),
- RingtoneManager.TYPE_NOTIFICATION))
-
.build();
}
@@ -381,14 +245,12 @@ public void checkPush(View v){
}
- private static boolean isNotificationListenerServiceEnabled(Context context) {
- Set packageNames = NotificationManagerCompat.getEnabledListenerPackages(context);
- if (packageNames.contains(context.getPackageName())) {
- return true;
- }
- return false;
- }
+
+
+
+
+ //各种权限的判断
private void toggleNotificationListenerService(Context context) {
PackageManager pm = context.getPackageManager();
pm.setComponentEnabledSetting(new ComponentName(context, NeNotificationService2.class),
@@ -399,33 +261,6 @@ private void toggleNotificationListenerService(Context context) {
Toast.makeText(MainActivity.this, "监听服务启动中...", Toast.LENGTH_SHORT).show();
}
-
-
-
-
- public static String md5(String string) {
- if (TextUtils.isEmpty(string)) {
- return "";
- }
- MessageDigest md5 = null;
- try {
- md5 = MessageDigest.getInstance("MD5");
- byte[] bytes = md5.digest(string.getBytes());
- String result = "";
- for (byte b : bytes) {
- String temp = Integer.toHexString(b & 0xff);
- if (temp.length() == 1) {
- temp = "0" + temp;
- }
- result += temp;
- }
- return result;
- } catch (NoSuchAlgorithmException e) {
- e.printStackTrace();
- }
- return "";
- }
-
public boolean isNotificationListenersEnabled() {
String pkgName = getPackageName();
final String flat = Settings.Secure.getString(getContentResolver(), "enabled_notification_listeners");
@@ -468,6 +303,32 @@ protected boolean gotoNotificationAccessSetting() {
}
+
+ public static String md5(String string) {
+ if (TextUtils.isEmpty(string)) {
+ return "";
+ }
+ MessageDigest md5 = null;
+ try {
+ md5 = MessageDigest.getInstance("MD5");
+ byte[] bytes = md5.digest(string.getBytes());
+ String result = "";
+ for (byte b : bytes) {
+ String temp = Integer.toHexString(b & 0xff);
+ if (temp.length() == 1) {
+ temp = "0" + temp;
+ }
+ result += temp;
+ }
+ return result;
+ } catch (NoSuchAlgorithmException e) {
+ e.printStackTrace();
+ }
+ return "";
+ }
+
+
+
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
@@ -485,20 +346,15 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
String t = String.valueOf(new Date().getTime());
String sign = md5(t+tmp[1]);
- //1.创建OkHttpClient对象
+
OkHttpClient okHttpClient = new OkHttpClient();
- //2.创建Request对象,设置一个url地址(百度地址),设置请求方式。
Request request = new Request.Builder().url("http://"+tmp[0]+"/appHeart?t="+t+"&sign="+sign).method("GET",null).build();
- //3.创建一个call对象,参数就是Request请求对象
Call call = okHttpClient.newCall(request);
- //4.请求加入调度,重写回调方法
call.enqueue(new Callback() {
- //请求失败执行的方法
@Override
public void onFailure(Call call, IOException e) {
}
- //请求成功执行的方法
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.d(TAG, "onResponse: "+response.body().string());
@@ -506,23 +362,20 @@ public void onResponse(Call call, Response response) throws IOException {
}
});
+
//将扫描出的信息显示出来
txthost.setText(" 通知地址:"+tmp[0]);
txtkey.setText(" 通讯密钥:"+tmp[1]);
host = tmp[0];
key = tmp[1];
- //步骤2-1:创建一个SharedPreferences.Editor接口对象,lock表示要写入的XML文件名,MODE_WORLD_WRITEABLE写操作
SharedPreferences.Editor editor = getSharedPreferences("vone", MODE_PRIVATE).edit();
- //步骤2-2:将获取过来的值放入文件
editor.putString("host", host);
editor.putString("key", key);
- //步骤3:提交
editor.commit();
}
}
-
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
diff --git a/app/src/main/java/com/vone/vmq/MyData.java b/app/src/main/java/com/vone/vmq/MyData.java
deleted file mode 100644
index 29c816d..0000000
--- a/app/src/main/java/com/vone/vmq/MyData.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.vone.vmq;
-
-import android.app.Application;
-
-public class MyData extends Application {
- private String host;
- private String key;
-
- public String getHost() {
- return host;
- }
-
- public void setHost(String host) {
- this.host = host;
- }
-
- public String getKey() {
- return key;
- }
-
- public void setKey(String key) {
- this.key = key;
- }
-}
diff --git a/app/src/main/java/com/vone/vmq/NeNotificationService.java b/app/src/main/java/com/vone/vmq/NeNotificationService.java
deleted file mode 100644
index 10875b5..0000000
--- a/app/src/main/java/com/vone/vmq/NeNotificationService.java
+++ /dev/null
@@ -1,336 +0,0 @@
-package com.vone.vmq;
-
-import android.accessibilityservice.AccessibilityService;
-import android.accessibilityservice.AccessibilityServiceInfo;
-import android.annotation.SuppressLint;
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.PowerManager;
-import android.text.TextUtils;
-import android.util.Log;
-import android.view.accessibility.AccessibilityEvent;
-import android.widget.Toast;
-
-import java.io.IOException;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.Date;
-import java.util.List;
-
-import okhttp3.Call;
-import okhttp3.Callback;
-import okhttp3.OkHttpClient;
-import okhttp3.Request;
-import okhttp3.Response;
-
-public class NeNotificationService extends AccessibilityService {
-
- public static String TAG = "NeNotificationService";
-
- private String host = "";
- private String key = "";
-
- private Thread newThread = null; //心跳线程
-
- PowerManager.WakeLock mWakeLock = null;
-
- //申请设备电源锁
- @SuppressLint("InvalidWakeLockTag")
- public void acquireWakeLock(Context context)
- {
- if (null == mWakeLock)
- {
- PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
- mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK|PowerManager.ON_AFTER_RELEASE, "WakeLock");
- if (null != mWakeLock)
- {
- mWakeLock.acquire();
- }
- }
- }
- //释放设备电源锁
- public void releaseWakeLock()
- {
- if (null != mWakeLock)
- {
- mWakeLock.release();
- mWakeLock = null;
- }
- }
-
-
-
- @Override
- public void onAccessibilityEvent(AccessibilityEvent event) {
- Log.d(TAG, "onAccessibilityEvent: "+event);
-
- if (event.getEventType() == AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED) {
- Log.d(TAG, "onAccessibilityEvent: 监控到新的推送");
- //应用包名:com.eg.android.AlipayGphone 推送内容: [vone通过扫码向你付款0.01元] //支付宝
- //应用包名:com.tencent.mm 推送内容: [微信支付: 微信支付收款0.01元(朋友到店)] //微信
-
- Log.d(TAG,"onAccessibilityEvent: 应用包名:" + event.getPackageName());
- Log.d(TAG,"onAccessibilityEvent: 推送内容:" + event.getText());
-
- /*
-
- List texts = event.getText();
-
- if (event.getPackageName().equals("com.eg.android.AlipayGphone")){
- if (!texts.isEmpty()) {
- for (CharSequence ctext : texts) {
- String text = ctext.toString();
- if (text!=null){
- if (text.indexOf(":")==-1){
- if (text.indexOf("通过扫码向你付款")!=-1){
- String money = getSubString(text,"通过扫码向你付款","元");
- Log.d(TAG, "onAccessibilityEvent: 匹配成功: 支付宝 到账 "+money);
- appPush(2,Double.valueOf(money));
-
- }else if (text.indexOf("成功收款")!=-1){
- String money = getSubString(text,"成功收款","元");
- Log.d(TAG, "onAccessibilityEvent: 匹配成功: 支付宝 到账 "+money);
- appPush(2,Double.valueOf(money));
-
- }
- }
- }
- }
- }
-
-
-
- }else if(event.getPackageName().equals("com.tencent.mm")){
- if (!texts.isEmpty()) {
- for (CharSequence ctext : texts) {
- String text = ctext.toString();
- if (text!=null){
- //微信支付: 微信支付收款0.01元(朋友到店)
- String[] tmp = text.split(":");
- if (tmp.length==2){
- if (tmp[0].equals("微信支付") || tmp[0].equals("微信收款助手") ){
- if (text.indexOf("微信支付收款")!=-1){
- String money = getSubString(text,"微信支付收款","元");
- Log.d(TAG, "onAccessibilityEvent: 匹配成功: 微信 到账 "+money);
- appPush(1,Double.valueOf(money));
- }else if (text.indexOf("店员消息")!=-1){
-
- String money = getSubString(text,"[店员消息]收款到账","元");
- Log.d(TAG, "onAccessibilityEvent: 匹配成功: 微信店员 到账 "+money);
-
- appPush(1,Double.valueOf(money));
- }
- }
- }
- }
- }
- }
-
- }else if(event.getPackageName().equals("com.vone.qrcode")){
- //测试推送
- if (!texts.isEmpty()) {
- for (CharSequence ctext : texts) {
- String text = ctext.toString();
- if (text.equals("这是一条测试推送信息,如果程序正常,则会提示监听权限正常")){
- Handler handlerThree=new Handler(Looper.getMainLooper());
- handlerThree.post(new Runnable(){
- public void run(){
- Toast.makeText(getApplicationContext() ,"监听权限正常!",Toast.LENGTH_SHORT).show();
- }
- });
- }
- }
- }
- }
- */
-
- }
-
- }
-
-
- @Override
- protected void onServiceConnected() {
- //设置监听配置
- AccessibilityServiceInfo info = new AccessibilityServiceInfo();
- info.eventTypes = AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED |
- AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED |
- AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;
- info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
-
- info.notificationTimeout = 10;
- setServiceInfo(info);
-
- //读入保存的配置数据并显示
- SharedPreferences read = getSharedPreferences("vone", MODE_PRIVATE);
- host = read.getString("host", "");
- key = read.getString("key", "");
-
-
- //开启心跳线程
- initAppHeart();
-
-
- Handler handlerThree = new Handler(Looper.getMainLooper());
- handlerThree.post(new Runnable(){
- public void run(){
- Toast.makeText(getApplicationContext() ,"监听服务开启成功!",Toast.LENGTH_LONG).show();
- }
- });
-
- }
-
- @Override
- public void onInterrupt() {
- Log.d("", "onInterrupt");
-
- }
-
-
-
- public void initAppHeart(){
- Log.d(TAG, "run: init");
- if (newThread!=null){
- return;
- }
- acquireWakeLock(this);
- newThread = new Thread(new Runnable() {
- @Override
- public void run() {
- Log.d(TAG, "run: 123123");
- while (true){
- //这里写入子线程需要做的工作
- String t = String.valueOf(new Date().getTime());
- String sign = md5(t+key);
-
-
- OkHttpClient okHttpClient = new OkHttpClient();
- Request request = new Request.Builder().url("http://"+host+"/appHeart?t="+t+"&sign="+sign).method("GET",null).build();
- Call call = okHttpClient.newCall(request);
- call.enqueue(new Callback() {
- @Override
- public void onFailure(Call call, IOException e) {
- final String error = e.getMessage();
- Handler handlerThree=new Handler(Looper.getMainLooper());
- handlerThree.post(new Runnable(){
- public void run(){
- Toast.makeText(getApplicationContext() ,"心跳状态错误,请检查配置是否正确!"+error,Toast.LENGTH_LONG).show();
- }
- });
- }
- //请求成功执行的方法
- @Override
- public void onResponse(Call call, Response response) throws IOException {
- Log.d(TAG, "onResponse heard: "+response.body().string());
- }
- });
- try {
- Thread.sleep(30*1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
-
- }
- });
-
- newThread.start(); //启动线程
- }
-
-
- public void appPush(int type,double price){
- //步骤1:创建一个SharedPreferences接口对象
- SharedPreferences read = getSharedPreferences("vone", MODE_WORLD_READABLE);
- //步骤2:获取文件中的值
- host = read.getString("host", "");
- key = read.getString("key", "");
-
- Log.d(TAG, "onResponse push: 开始:"+type+" "+price);
-
- String t = String.valueOf(new Date().getTime());
- String sign = md5(type+""+ price + t + key);
- String url = "http://"+host+"/appPush?t="+t+"&type="+type+"&price="+price+"&sign="+sign;
- Log.d(TAG, "onResponse push: 开始:"+url);
-
- //1.创建OkHttpClient对象
- OkHttpClient okHttpClient = new OkHttpClient();
- //2.创建Request对象,设置一个url地址,设置请求方式。
- Request request = new Request.Builder().url(url).method("GET",null).build();
- //3.创建一个call对象,参数就是Request请求对象
- Call call = okHttpClient.newCall(request);
- //4.请求加入调度,重写回调方法
- call.enqueue(new Callback() {
- //请求失败执行的方法
- @Override
- public void onFailure(Call call, IOException e) {
- Log.d(TAG, "onResponse push: 请求失败");
-
- }
- //请求成功执行的方法
- @Override
- public void onResponse(Call call, Response response) throws IOException {
-
- Log.d(TAG, "onResponse push: "+response.body().string());
-
- }
- });
- }
-
- /**
- * 取两个文本之间的文本值
- *
- * @param text
- * @param left
- * @param right
- * @return
- */
- public static String getSubString(String text, String left, String right) {
- String result = "";
- int zLen;
- if (left == null || left.isEmpty()) {
- zLen = 0;
- } else {
- zLen = text.indexOf(left);
- if (zLen > -1) {
- zLen += left.length();
- } else {
- zLen = 0;
- }
- }
- int yLen = text.indexOf(right, zLen);
- if (yLen < 0 || right == null || right.isEmpty()) {
- yLen = text.length();
- }
- result = text.substring(zLen, yLen);
- return result;
- }
-
-
- public static String md5(String string) {
- if (TextUtils.isEmpty(string)) {
- return "";
- }
- MessageDigest md5 = null;
- try {
- md5 = MessageDigest.getInstance("MD5");
- byte[] bytes = md5.digest(string.getBytes());
- String result = "";
- for (byte b : bytes) {
- String temp = Integer.toHexString(b & 0xff);
- if (temp.length() == 1) {
- temp = "0" + temp;
- }
- result += temp;
- }
- return result;
- } catch (NoSuchAlgorithmException e) {
- e.printStackTrace();
- }
- return "";
- }
-
-
-
-}
diff --git a/app/src/main/java/com/vone/vmq/NeNotificationService2.java b/app/src/main/java/com/vone/vmq/NeNotificationService2.java
index 2badbd9..a9988e8 100644
--- a/app/src/main/java/com/vone/vmq/NeNotificationService2.java
+++ b/app/src/main/java/com/vone/vmq/NeNotificationService2.java
@@ -2,17 +2,15 @@
import android.annotation.SuppressLint;
import android.app.Notification;
-import android.content.Intent;
+import android.content.Context;
import android.content.SharedPreferences;
-import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
+import android.os.PowerManager;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
-import android.support.annotation.RequiresApi;
import android.support.v4.app.NotificationCompat;
-import android.support.v4.content.LocalBroadcastManager;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;
@@ -20,10 +18,9 @@
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
-import java.text.SimpleDateFormat;
import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import okhttp3.Call;
import okhttp3.Callback;
@@ -35,7 +32,91 @@ public class NeNotificationService2 extends NotificationListenerService {
private String TAG = "NeNotificationService2";
private String host = "";
private String key = "";
+ private Thread newThread = null;
+ private PowerManager.WakeLock mWakeLock = null;
+
+
+ //申请设备电源锁
+ @SuppressLint("InvalidWakeLockTag")
+ public void acquireWakeLock(Context context) {
+ if (null == mWakeLock)
+ {
+ PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
+ mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK|PowerManager.ON_AFTER_RELEASE, "WakeLock");
+ if (null != mWakeLock)
+ {
+ mWakeLock.acquire();
+ }
+ }
+ }
+ //释放设备电源锁
+ public void releaseWakeLock() {
+ if (null != mWakeLock)
+ {
+ mWakeLock.release();
+ mWakeLock = null;
+ }
+ }
+ //心跳进程
+ public void initAppHeart(){
+ Log.d(TAG, "开始启动心跳线程");
+ if (newThread!=null){
+ return;
+ }
+ acquireWakeLock(this);
+ newThread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ Log.d(TAG, "心跳线程启动!");
+ while (true){
+
+ SharedPreferences read = getSharedPreferences("vone", MODE_PRIVATE);
+ host = read.getString("host", "");
+ key = read.getString("key", "");
+
+ //这里写入子线程需要做的工作
+ String t = String.valueOf(new Date().getTime());
+ String sign = md5(t+key);
+
+
+ OkHttpClient okHttpClient = new OkHttpClient();
+ Request request = new Request.Builder().url("http://"+host+"/appHeart?t="+t+"&sign="+sign).method("GET",null).build();
+ Call call = okHttpClient.newCall(request);
+ call.enqueue(new Callback() {
+ @Override
+ public void onFailure(Call call, IOException e) {
+ final String error = e.getMessage();
+ Handler handlerThree=new Handler(Looper.getMainLooper());
+ handlerThree.post(new Runnable(){
+ public void run(){
+ Toast.makeText(getApplicationContext() ,"心跳状态错误,请检查配置是否正确!"+error,Toast.LENGTH_LONG).show();
+ }
+ });
+ }
+ //请求成功执行的方法
+ @Override
+ public void onResponse(Call call, Response response) throws IOException {
+ Log.d(TAG, "onResponse heard: "+response.body().string());
+ }
+ });
+ try {
+ Thread.sleep(30*1000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ }
+ });
+
+ newThread.start(); //启动线程
+ }
+
+
+
+ //当收到一条消息的时候回调,sbn是收到的消息
+ @Override
public void onNotificationPosted(StatusBarNotification sbn) {
Log.d(TAG, "接受到通知消息");
SharedPreferences read = getSharedPreferences("vone", MODE_PRIVATE);
@@ -46,108 +127,87 @@ public void onNotificationPosted(StatusBarNotification sbn) {
Notification notification = sbn.getNotification();
String pkg = sbn.getPackageName();
if (notification != null) {
- String notitime = new SimpleDateFormat("yyyy-MM-dd HH:mm").format(new Date(notification.when));
Bundle extras = notification.extras;
if (extras != null) {
String title = extras.getString(NotificationCompat.EXTRA_TITLE, "");
String content = extras.getString(NotificationCompat.EXTRA_TEXT, "");
Log.d(TAG, "**********************");
Log.d(TAG, "包名:" + pkg);
- Log.d(TAG, "title:" + title);
- Log.d(TAG, "content:" + content);
+ Log.d(TAG, "标题:" + title);
+ Log.d(TAG, "内容:" + content);
Log.d(TAG, "**********************");
if (pkg.equals("com.eg.android.AlipayGphone")){
- String text = content;
- if (text!=null){
- if (text.indexOf(":")==-1){
- if (text.indexOf("通过扫码向你付款")!=-1){
- String money = getSubString(text,"通过扫码向你付款","元");
- Log.d(TAG, "onAccessibilityEvent: 匹配成功: 支付宝 到账 "+money);
- appPush(2,Double.valueOf(money));
-
- }else if (text.indexOf("成功收款")!=-1){
- String money = getSubString(text,"成功收款","元");
- Log.d(TAG, "onAccessibilityEvent: 匹配成功: 支付宝 到账 "+money);
- appPush(2,Double.valueOf(money));
-
+ if (content!=null && !content.equals("")) {
+ if (content.indexOf("通过扫码向你付款")!=-1 || content.indexOf("成功收款")!=-1){
+ String money = getMoney(content);
+ if (money!=null){
+ Log.d(TAG, "onAccessibilityEvent: 匹配成功: 支付宝 到账 " + money);
+ appPush(2, Double.valueOf(money));
}
}
- }
-
+ }
}else if(pkg.equals("com.tencent.mm")){
- String text = content;
-
- if (text!=null){
- //微信支付: 微信支付收款0.01元(朋友到店)
- String[] tmp = text.split(":");
- if (tmp.length==2){
- if (tmp[0].equals("微信支付") || tmp[0].equals("微信收款助手") || tmp[0].equals("微信收款商业版")){
- if (text.indexOf("微信支付收款")!=-1){
- String money = getSubString(text,"微信支付收款","元");
- if (money.indexOf("支付")!=-1){
- money = getSubString(money+"元","微信支付收款","元");
- }
-
- Log.d(TAG, "onAccessibilityEvent: 匹配成功: 微信 到账 "+money);
- appPush(1,Double.valueOf(money));
- }else if (text.indexOf("店员消息")!=-1){
-
- String money = getSubString(text,"[店员消息]收款到账","元");
- Log.d(TAG, "onAccessibilityEvent: 匹配成功: 微信店员 到账 "+money);
- appPush(1,Double.valueOf(money));
- }else if (text.indexOf("微信收款商业版")!=-1){
-
- String money = getSubString(text,"商业版: 收款","元");
- Log.d(TAG, "onAccessibilityEvent: 匹配成功: 微信商业 到账 "+money);
-
- appPush(1,Double.valueOf(money));
- }
+ if (content!=null && !content.equals("")){
+ if (title.equals("微信支付") || title.equals("微信收款助手") || title.equals("微信收款商业版")){
+ String money = getMoney(content);
+ if (money!=null){
+ Log.d(TAG, "onAccessibilityEvent: 匹配成功: 微信到账 "+ money);
+ appPush(1,Double.valueOf(money));
}
+
}
}
}else if(pkg.equals("com.vone.qrcode")){
- //测试推送
- String text = content;
- if (text.equals("这是一条测试推送信息,如果程序正常,则会提示监听权限正常")){
+
+ if (content.equals("这是一条测试推送信息,如果程序正常,则会提示监听权限正常")){
Handler handlerThree=new Handler(Looper.getMainLooper());
handlerThree.post(new Runnable(){
public void run(){
- Toast.makeText(getApplicationContext() ,"监听权限正常!",Toast.LENGTH_SHORT).show();
+ Toast.makeText(getApplicationContext() ,"监听正常!",Toast.LENGTH_SHORT).show();
}
});
}
}
+
+
+
}
}
}
+ //当移除一条消息的时候回调,sbn是被移除的消息
+ @Override
+ public void onNotificationRemoved(StatusBarNotification sbn) {
+ }
+ //当连接成功时调用,一般在开启监听后会回调一次该方法
@Override
public void onListenerConnected() {
- //当连接成功时调用,一般在开启监听后会回调一次该方法
- Handler handlerThree=new Handler(Looper.getMainLooper());
+ //开启心跳线程
+ initAppHeart();
+
+ Handler handlerThree = new Handler(Looper.getMainLooper());
handlerThree.post(new Runnable(){
public void run(){
Toast.makeText(getApplicationContext() ,"监听服务开启成功!",Toast.LENGTH_SHORT).show();
}
});
- }
- @Override
- public void onNotificationRemoved(StatusBarNotification sbn) {
- //当移除一条消息的时候回调,sbn是被移除的消息
+
}
+
+
+
+
public void appPush(int type,double price){
- //步骤1:创建一个SharedPreferences接口对象
- SharedPreferences read = getSharedPreferences("vone", MODE_WORLD_READABLE);
- //步骤2:获取文件中的值
+ SharedPreferences read = getSharedPreferences("vone", MODE_PRIVATE);
host = read.getString("host", "");
key = read.getString("key", "");
@@ -158,21 +218,15 @@ public void appPush(int type,double price){
String url = "http://"+host+"/appPush?t="+t+"&type="+type+"&price="+price+"&sign="+sign;
Log.d(TAG, "onResponse push: 开始:"+url);
- //1.创建OkHttpClient对象
OkHttpClient okHttpClient = new OkHttpClient();
- //2.创建Request对象,设置一个url地址,设置请求方式。
Request request = new Request.Builder().url(url).method("GET",null).build();
- //3.创建一个call对象,参数就是Request请求对象
Call call = okHttpClient.newCall(request);
- //4.请求加入调度,重写回调方法
call.enqueue(new Callback() {
- //请求失败执行的方法
@Override
public void onFailure(Call call, IOException e) {
Log.d(TAG, "onResponse push: 请求失败");
}
- //请求成功执行的方法
@Override
public void onResponse(Call call, Response response) throws IOException {
@@ -182,36 +236,23 @@ public void onResponse(Call call, Response response) throws IOException {
});
}
- /**
- * 取两个文本之间的文本值
- *
- * @param text
- * @param left
- * @param right
- * @return
- */
- public static String getSubString(String text, String left, String right) {
- String result = "";
- int zLen;
- if (left == null || left.isEmpty()) {
- zLen = 0;
- } else {
- zLen = text.indexOf(left);
- if (zLen > -1) {
- zLen += left.length();
- } else {
- zLen = 0;
- }
- }
- int yLen = text.indexOf(right, zLen);
- if (yLen < 0 || right == null || right.isEmpty()) {
- yLen = text.length();
+ public static String getMoney(String content){
+
+ int index = content.indexOf("]");
+ if (index!=-1){
+ content = content.substring(index+1);
}
- result = text.substring(zLen, yLen);
- return result;
- }
+ Pattern p = Pattern.compile("([0-9]\\d*\\.?\\d*)|(0\\.\\d*[0-9])");
+ Matcher m = p.matcher(content);
+ boolean result = m.find();
+ String find_result = null;
+ if (result) {
+ find_result = m.group(1);
+ }
+ return find_result;
+ }
public static String md5(String string) {
if (TextUtils.isEmpty(string)) {
return "";
@@ -235,4 +276,5 @@ public static String md5(String string) {
return "";
}
+
}
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 78432ad..6139f22 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -50,13 +50,13 @@
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:onClick="doStart"
- android:text="开启服务" />
+ android:text="检测心跳" />
+ android:text="检测监听" />