(1) DEVICE_ID
假设我们确实需要用到真实设备的标识,可能就需要用到DEVICE_ID。在以前,我们的Android设备是手机,这个DEVICE_ID可以同通过TelephonyManager.getDeviceId()获取,它根据不同的手机设备返回IMEI,MEID或者ESN码,但它在使用的过程中会遇到很多问题:
a. 非手机设备: 如果只带有Wifi的设备或者音乐播放器没有通话的硬件功能的话就没有这个DEVICE_ID
b. 权限: 获取DEVICE_ID需要READ_PHONE_STATE权限,但如果我们只为了获取它,没有用到其他的通话功能,那这个权限有点大才小用
c. bug:在少数的一些手机设备上,该实现有漏洞,会返回垃圾,如:zeros或者asterisks的产品
来源: http://blog.csdn.net/qq_24531461/article/details/53096534
(2)MAC ADDRESS
可以使用手机Wifi或蓝牙的MAC地址作为设备标识,但是并不推荐这么做,原因有以下两点:
a. 硬件限制:并不是所有的设备都有Wifi和蓝牙硬件,硬件不存在自然也就得不到这一信息。
b. 获取的限制:如果Wifi没有打开过,是无法获取其Mac地址的;而蓝牙是只有在打开的时候才能获取到其Mac地址。
获取Wifi Mac地址:
权限:<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
WifiInfo info = wifi.getConnectionInfo();
String Wifi_Mac = info.getMacAddress();
(3)Sim Serial Number
装有SIM卡的设备,可以通过下面的方法获取到Sim Serial Number:
TelephonyManager tm = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
String SimSerialNumber = tm.getSimSerialNumber();
(4)ANDROID_ID
在设备首次启动时,系统会随机生成一个64位的数字,并把这个数字以16进制字符串的形式保存下来,这个16进制的字符串就是ANDROID_ID,当设备被wipe后该值会被重置。可以通过下面的方法获取:
import android.provider.Settings;
String ANDROID_ID = Settings.System.getString(getContentResolver(), Settings.System.ANDROID_ID);
ANDROID_ID可以作为设备标识,但需要注意:
a. 厂商定制系统的Bug:不同的设备可能会产生相同的ANDROID_ID:9774d56d682e549c。
b. 厂商定制系统的Bug:有些设备返回的值为null。
c. 设备差异:对于CDMA设备,ANDROID_ID和TelephonyManager.getDeviceId() 返回相同的值。
2.获取桌面应用列表信息
/**
* 获取到桌面的应用程序
*/
public static List<ResolveInfo> getLauncherApp(Context context) {
// 桌面应用的启动在INTENT中需要包含ACTION_MAIN 和CATEGORY_HOME.
Intent intent = new Intent();
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setAction(Intent.ACTION_MAIN);
PackageManager manager = context.getPackageManager();
List<ResolveInfo> resolveInfoList = manager.queryIntentActivities(intent, 0);
return resolveInfoList;
}
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> appTasks = activityManager.getRunningTasks(1);
if (null != appTasks && !appTasks.isEmpty()) {
return appTasks.get(0).topActivity.getPackageName();
}
但是,在5.1的版本发布后getRunningAppProcesses()已经获取不到正在运行的服务...
那还有什么办法呢?原来,Android在5.0版本Google提供了一个UsageStatsManager类,通过这个类可以获取到应用程序的运行情况,该类的使用方法如下:
(1)在AndroidManifest文件中添加权限:
-
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
(2)启动授权页面,需要用户授权
-
Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
context.startActivity(intent);
(3)如果用户给你授权了,调用相关代码获取正在运行的服务:
-
UsageStatsManager usm = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
Calendar calendar = Calendar.getInstance();
long endTime = calendar.getTimeInMillis();
calendar.add(Calendar.YEAR, -1);
long startTime = calendar.getTimeInMillis();
List<UsageStats> usageStatsList = usm.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, startTime, endTime);
/**
* 获取栈顶运行的进程
* @param context
* @return
*/
public static String getLauncherTopApp(Context context) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> appTasks = activityManager.getRunningTasks(1);
if (null != appTasks && !appTasks.isEmpty()) {
return appTasks.get(0).topActivity.getPackageName();
}
} else {
long endTime = System.currentTimeMillis();
long beginTime = endTime - 1000;
if (sUsageStatsManager == null) {
sUsageStatsManager = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
}
String result = "";
UsageEvents.Event event = new UsageEvents.Event();
UsageEvents usageEvents = sUsageStatsManager.queryEvents(beginTime, endTime);
while (usageEvents.hasNextEvent()) {
usageEvents.getNextEvent(event);
//监测app由后台转前台
if (event.getEventType() == UsageEvents.Event.MOVE_TO_FOREGROUND) {
result = event.getPackageName();
}
//监测app由前台转后台
// if (event.getEventType() == UsageEvents.Event.MOVE_TO_BACKGROUND) {
// result = event.getPackageName();
// }
}
if (!android.text.TextUtils.isEmpty(result)) {
return result;
}
}
return "";
}
/**
* 判断指定进程是否由前台转后台
* @param context
* @return
*/
public static boolean IsLauncherToBack(Context context,String pkgName) {
boolean isRunning = false;
long endTime = System.currentTimeMillis();
long beginTime = endTime - 1000;
if (sUsageStatsManager == null) {
sUsageStatsManager = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
}
String result = "";
UsageEvents.Event event = new UsageEvents.Event();
UsageEvents usageEvents = sUsageStatsManager.queryEvents(beginTime, endTime);
while (usageEvents.hasNextEvent()) {
usageEvents.getNextEvent(event);
//监测app由前台转后台
if (event.getEventType() == UsageEvents.Event.MOVE_TO_BACKGROUND) {
result = event.getPackageName();
}
}
if (!android.text.TextUtils.isEmpty(result)&&pkgName.equals(result)) {
isRunning = true;
}
return isRunning;
}
/**
* 监测手机上是否存在允许查看应用使用情况
* @return
*/
private boolean isNoOption() {
PackageManager packageManager = getApplicationContext()
.getPackageManager();
//打开允许获取应用使用情况的界面
Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
List<ResolveInfo> list = packageManager.queryIntentActivities(intent,
PackageManager.MATCH_DEFAULT_ONLY);
return list.size() > 0;
}
/**
* 监测允许查看应用使用情况是否打开
* @return
*/
private boolean isNoSwitch() {
long ts = System.currentTimeMillis();
UsageStatsManager usageStatsManager = (UsageStatsManager) getApplicationContext()
.getSystemService(USAGE_STATS_SERVICE);
List<UsageStats> queryUsageStats = usageStatsManager.queryUsageStats(
UsageStatsManager.INTERVAL_BEST, 0, ts);
if (queryUsageStats == null || queryUsageStats.isEmpty()) {
return false;
}
return true;
}