和上次获取设备序列号一样,仍然是通过无障碍服务实现,在之前的代码基础上做了更新。代码和demo如下:
package com.zwxuf.lib.devicehelper;
import android.accessibilityservice.AccessibilityService;
import android.app.Activity;
import android.app.Application;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.provider.Settings;
import android.util.Log;
import android.widget.Toast;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class DeviceHelper implements Application.ActivityLifecycleCallbacks {
static final String TAG = "WADQ_DeviceHelper";
static final String ACTION_ACQUIRE_SERIAL_SUCCESS = "zwxuf.intent.action.ACQUIRE_SERIAL_SUCCESS";
static final String ACTION_ACQUIRE_PHONE_SUCCESS = "zwxuf.intent.action.ACQUIRE_PHONE_SUCCESS";
private static Handler mHandler = new Handler(Looper.getMainLooper());
private boolean isMsgReceiverEnabled;
private OnAcquireSerialListener mOnAcquireSerialListener;
private OnAcquirePhoneListener onAcquirePhoneListener;
private Activity mActivity;
private Application mApplication;
public DeviceHelper(Activity mActivity) {
this.mActivity = mActivity;
mApplication = mActivity.getApplication();
mApplication.registerActivityLifecycleCallbacks(this);
}
public void acquireSerial(OnAcquireSerialListener listener) {
mOnAcquireSerialListener = listener;
if (!isMsgReceiverEnabled) initMsgReceiver();
AcquireSerialService.isSerialFound = false;
AcquireSerialService.isStatusInfoFound = false;
Intent intent = new Intent(Settings.ACTION_DEVICE_INFO_SETTINGS);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mActivity.startActivity(intent);
}
public void acquirePhone(OnAcquirePhoneListener listener) {
onAcquirePhoneListener = listener;
if (!isMsgReceiverEnabled) initMsgReceiver();
Intent intent = new Intent();
intent.setClassName("com.android.phone", "com.android.phone.MSimMobileNetworkSettings");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
mActivity.startActivity(intent);
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(mActivity, e.toString(), Toast.LENGTH_SHORT).show();
}
}
private void releaseAcquireSerial() {
List<Service> services = getServices();
for (Service service : services) {
if (service instanceof AcquireSerialService) {
((AcquireSerialService) service).release();
break;
}
}
}
private void releaseAcquirePhone() {
List<Service> services = getServices();
for (Service service : services) {
if (service instanceof AcquirePhoneService) {
((AcquirePhoneService) service).release();
break;
}
}
}
private void initMsgReceiver() {
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_ACQUIRE_SERIAL_SUCCESS);
filter.addAction(ACTION_ACQUIRE_PHONE_SUCCESS);
mActivity.registerReceiver(mMsgReceiver, filter);
isMsgReceiverEnabled = true;
}
private BroadcastReceiver mMsgReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (ACTION_ACQUIRE_SERIAL_SUCCESS.equals(intent.getAction())) {
String serial = intent.getStringExtra("serial");
if (mOnAcquireSerialListener != null) {
mOnAcquireSerialListener.onAcquireSerial(serial);
}
} else if (ACTION_ACQUIRE_PHONE_SUCCESS.equals(intent.getAction())) {
ArrayList<String> phoneNumbers = intent.getStringArrayListExtra("phones");
if (onAcquirePhoneListener != null) {
onAcquirePhoneListener.onAcquirePhone(phoneNumbers);
}
}
releaseMsgReciever();
}
};
private void releaseMsgReciever() {
if (isMsgReceiverEnabled) {
mActivity.unregisterReceiver(mMsgReceiver);
isMsgReceiverEnabled = false;
}
}
public void release() {
releaseMsgReciever();
mApplication.unregisterActivityLifecycleCallbacks(this);
releaseAcquireSerial();
releaseAcquirePhone();
}
public boolean canAcquireSerial() {
return isServiceEnabled(mActivity, AcquireSerialService.class);
}
public boolean canAcquirePhone() {
return isServiceEnabled(mActivity, AcquirePhoneService.class);
}
public void openAccessibilitySettings(final int requestCode) {
Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
mActivity.startActivityForResult(intent, requestCode);
} catch (Exception e) {
e.printStackTrace();
}
}
private static boolean isServiceEnabled(Context context, Class<? extends AccessibilityService> serviceClass) {
if (serviceClass == null) {
return false;
}
String serviceName = context.getPackageName() + "/" + serviceClass.getName();
try {
int enabled = Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.ACCESSIBILITY_ENABLED);
if (enabled == 1) {
String service = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
Log.i(TAG, service);
return service != null && service.contains(serviceName);
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
static Handler getHandler() {
return mHandler;
}
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
}
@Override
public void onActivityStarted(Activity activity) {
}
@Override
public void onActivityResumed(Activity activity) {
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivityStopped(Activity activity) {
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
if (activity == mActivity) {
release();
}
}
private static List<Service> getServices() {
List<Service> services = new ArrayList<>();
Object mActivityThread = getActivityThread();
try {
Class mActivityThreadClass = mActivityThread.getClass();
Field mServicesField = mActivityThreadClass.getDeclaredField("mServices");
mServicesField.setAccessible(true);
Object mServices = mServicesField.get(mActivityThread);
if (mServices instanceof Map) {
Map<IBinder, Service> arrayMap = (Map) mServices;
for (Map.Entry<IBinder, Service> entry : arrayMap.entrySet()) {
Service service = entry.getValue();
if (service != null) {
services.add(service);
}
}
}
} catch (Throwable e) {
e.printStackTrace();
}
return services;
}
private static Object getActivityThread() {
try {
Class ActivityThread = Class.forName("android.app.ActivityThread");
Method currentActivityThread = ActivityThread.getMethod("currentActivityThread");
currentActivityThread.setAccessible(true);
return currentActivityThread.invoke(null);
} catch (Throwable e) {
e.printStackTrace();
}
return null;
}
}
获取手机号服务代码:
package com.zwxuf.lib.devicehelper;
import android.accessibilityservice.AccessibilityService;
import android.content.Intent;
import android.os.Build;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class AcquirePhoneService extends AccessibilityService {
private ArrayList<String> mPhoneNumbers = new ArrayList<>();
private boolean mAcquireSuccess;
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
if (event.getPackageName() == null || event.getClassName() == null) {
return;
}
String packageName = event.getPackageName().toString();
String className = event.getClassName().toString();
final AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
if (nodeInfo != null) {
if (!packageName.equals(getApplicationContext().getPackageName())) {
enumChildNodeInfo(nodeInfo, 0);
}
}
}
@Override
public void onInterrupt() {
}
private void enumChildNodeInfo(AccessibilityNodeInfo nodeInfo, int level) {
//Dbg.print(TAG, StringUtils.generateStr(" ", level), nodeInfo.getClassName(), getNodeText(nodeInfo), nodeInfo.getViewIdResourceName());
int count = nodeInfo.getChildCount();
//Dbg.print("count=" + count);
if (count > 0) {
for (int i = 0; i < count; i++) {
final AccessibilityNodeInfo childNodeInfo = nodeInfo.getChild(i);
if (childNodeInfo == null) continue;
/*if (childNodeInfo.isScrollable()) {
childNodeInfo.performAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
}*/
List<AccessibilityNodeInfo> nodeInfoList = childNodeInfo.findAccessibilityNodeInfosByViewId("android:id/title");
if (nodeInfoList != null && !nodeInfoList.isEmpty()) {
for (AccessibilityNodeInfo ni : nodeInfoList) {
String text = getNodeText(ni);
if (text == null) continue;
if (text.startsWith("卡 1") || text.startsWith("卡 2")) {
int start = text.lastIndexOf("(");
int end = text.indexOf(")", start);
if (start > 0 && start < end) {
String number = text.substring(start + 1, end);
if (number.startsWith("+86")) {
number = number.substring(3);
}
if (isPhoneNumber(number) && !mPhoneNumbers.contains(number)) {
mPhoneNumbers.add(number);
}
}
if (!mPhoneNumbers.isEmpty() && !mAcquireSuccess) {
mAcquireSuccess = true;
//延时获取第2个手机号
DeviceHelper.getHandler().postDelayed(new Runnable() {
@Override
public void run() {
Intent intent = new Intent(DeviceHelper.ACTION_ACQUIRE_PHONE_SUCCESS);
intent.putExtra("phones", mPhoneNumbers);
sendBroadcast(intent);
performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);
release();
}
}, 500);
}
break;
}
}
}
enumChildNodeInfo(childNodeInfo, level + 1);
}
}
nodeInfo.recycle();
}
private String getNodeText(AccessibilityNodeInfo nodeInfo) {
if (nodeInfo != null && nodeInfo.getText() != null) {
return nodeInfo.getText().toString();
} else {
return null;
}
}
static boolean isPhoneNumber(String mobiles) {
Pattern p = Pattern
.compile("^(0|86|17951)?(13[0-9]|15[0-9]|17[0-9]|18[0-9]|14[0-9]|16[0-9]|19[0-9])[0-9]{8}$");
Matcher m = p.matcher(mobiles);
return m.matches();
}
public void release() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
disableSelf();
}
}
}
下载地址: