假设我们确实需要用到真实设备的标识,可能就需要用到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
TelephonyManager TelephonyMgr = (TelephonyManager)context.getSystemService(TELEPHONY_SERVICE);String szImei = TelephonyMgr.getDeviceId();(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(); 来源: http://www.itnose.net/detail/6373703.htm(3)Sim Serial Number
装有SIM卡的设备,可以通过下面的方法获取到Sim Serial Number:
TelephonyManager tm = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);String SimSerialNumber = tm.getSimSerialNumber(); 注意:对于CDMA(包括平板电脑这些没有sim卡的设备)设备,返回的是一个空值!(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;} 3.获取系统栈顶的进程 在5.0以前google给我们提供的API是ActivityManager类中通过getRunningTasks()获取当前打开的所有应用程序 ,所以,如果想要获取当前的栈顶Activity和进程,可以使用以下方法: 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();} 但是,随着系统版本的升级,Google对权限控制更加严谨了,这为我们这项项目开发需求造成了一定的困扰。5.0版本之后google废弃了getRunningTasks()方法,意味着我们在5.0以后不能通过该方法获取正在运行的应用程序,但5.0又提供类新的Api,那就是getRunningAppProcesses(),通过ActivityManager的getRunningAppProcesses()方法也可以获取正在运行的应用程序。但是,在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); 来源: http://blog.csdn.net/ballonge/article/details/51085953 综上所述, 根据版本获取应用列表:/*** 获取栈顶运行的进程* @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;} 4. 获取指定应用运行的时间 查找资料发现Android本身提供了获取应用使用时间的api(来源:http://blog.csdn.net/pierce0young/article/details/22292603),但是自己试了发现两个主要的类都找不到,不知道为什么,如果大家发现什么,请一定给我留下解释,谢谢!那么接下来我就是间接的获取时间,即监听指定app的安装成功及启动,开始计时,再配合判断应用在前台以及后台,计算时间的长短来获取运行时间。 5.允许获取应用使用情况 以上步骤大多基于用户已打开,允许该应用获取其他应用使用情况,这个前提,接下来是判断手机上是否存在这个打开界面、是否已打开这个开关以及打开这个界面的代码:/*** 监测手机上是否存在允许查看应用使用情况* @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;}
新闻热点
疑难解答