仿QQ获取设备中APK并分享

news/2024/11/24 11:29:22/

探索Android软键盘的疑难杂症
深入探讨Android异步精髓Handler
详解Android主流框架不可或缺的基石
站在源码的肩膀上全解Scroller工作机制


Android多分辨率适配框架(1)— 核心基础
Android多分辨率适配框架(2)— 原理剖析
Android多分辨率适配框架(3)— 使用指南


自定义View系列教程00–推翻自己和过往,重学自定义View
自定义View系列教程01–常用工具介绍
自定义View系列教程02–onMeasure源码详尽分析
自定义View系列教程03–onLayout源码详尽分析
自定义View系列教程04–Draw源码分析及其实践
自定义View系列教程05–示例分析
自定义View系列教程06–详解View的Touch事件处理
自定义View系列教程07–详解ViewGroup分发Touch事件
自定义View系列教程08–滑动冲突的产生及其处理


我和郭霖

13年,郭霖开始写技术博客。我在CSDN的博客频道逛着玩,刚好看到他的文章,于是点击进去阅读。看完之后最大的感受就是:代码整齐,技术深厚;文章写得图文并茂,有条有理。从那时起,我就成了郭霖的一个粉丝,每周四早晨都等着看他的更新。诚实地说:没有脑残地追过星,但这么实在地喜欢看一个人写的技术博客,这还是头一回。其实,从他每篇文章的点击量和评论数也可以看出:大家对郭霖非常的认可。他也常出现在CSDN的首页,有时还无耻地连续出现几次。去年,部门经理交给我十几个大学毕业生,老大问我:他们适合从哪里学起?我基本没有过脑子地说:每个人买一本《第一行代码》,快去吧,京西十一点前下单下午就能送到。从那以后,部门来的新手,公司都会让他们照着这本书夯实一下基础。

嗯哼,期待郭大婶带给我们更多的分享。

书归正传。


前几天看到同事里有一个界面绚丽的应用,觉得有点意思,就让他把APK发给我,我想反编译看看里面的代码。结果,这哥们在手机里找了好一阵子,最后给我说:手机没有root,找不到APK文件在哪里。我再让他试试其他机子,结果都差不多:要不然找起来很麻烦,要不然根本都找不到。这时,测试的妹子说:手机QQ有这个功能。我打开手机QQ一看,果然有,平时都没有注意到啊。

这里写图片描述

这个功能点稍作总结:
- 每个item包括:应用的icon,名字,安装文件的大小,最后更新时间
- 点击item分享其对应的APK文件

看到这里,心里怪痒痒的,我们也能做这么个类似的东西么?
能的!必须能!否则在测试的妹子面前怎么能抬起头!?

我们先获取手机中已经安装的应用:

List<PackageInfo> packageInfoList = mPackageManager.getInstalledPackages(0);

这些应用已经都躺在这里了,我们现在就一步一步地来找出每个应用的相关信息。

(1) 获取应用的名称

    /*** 获取应用的名称*/public String getApplicationName(String packageName,PackageManager packageManager) {String applicationName=null;try {ApplicationInfo applicationInfo = packageManager.getApplicationInfo(packageName, 0);applicationName = (String) packageManager.getApplicationLabel(applicationInfo);} catch (PackageManager.NameNotFoundException e) {}return applicationName;}

嗯哼,这个不难,刚上路的小司机也可以轻松的搞定。

(2) 获取应用的icon

应用的名字我们容易获得,那它的icon又在哪里呢?
既然获得应用名字用的是:

packageManager.getApplicationLabel(applicationInfo);

那么是不是有类似的getApplicationIcon方法呢?赶紧试着敲一下代码,AS提示果然有我们想要的东西:

packageManager.getApplicationIcon(ApplicationInfo info)

嗯哼,真愉快,我们猜对啦。把代码运行起来瞅瞅,我的华为手机没有问题。换个三星试试,也对呢;再用HTC跑跑,获取到的居然是个小绿人——系统默认的图标!再从测试妹子那里拿个小米过来,一样啊,没有正确获取到应用对应的图标。

不开心了,喝口水,默默地打开度娘找答案。看到这样的方式:

//.........Class pkgParserCls = Class.forName(PATH_PackageParser);Class[] typeArgs = new Class[1];typeArgs[0] = String.class;Constructor pkgParserCt = pkgParserCls.getConstructor(typeArgs);Object[] valueArgs = new Object[1];valueArgs[0] = apkPath;Object pkgParser = pkgParserCt.newInstance(valueArgs);
//.........

居然用的是反射,复杂就不说了而且还影响效率。所以,在不得已的情况下还是不要这么做了。看来想通过PackageManager获取应用的Icon是不行了,那就换个角度从PackageInfo入手试试,看到一个字段:

public ApplicationInfo applicationInfo;

官方文档的解释是: Information collected from the application。也就是说这个字段包含了App的众多信息。所以,接着看ApplicationInfo里面有啥东西,扫了一眼,看到一个东西:

//Retrieve the current graphical icon associated with this item.public Drawable loadIcon(PackageManager pm) {return pm.loadItemIcon(this, getApplicationInfo());}

利用该方法才可以避免在某些机型上无法获取应用的icon的bug。手边的机子试了一遍,都没问题。这个小问题解决了,就接着往下走。

(3) 获取应用的最后更新时间
这个也挺容易的,PackageInfo中有相应的字段:

public long lastUpdateTime;

当然这个值是个毫秒值,需要利用SimpleDateFormat将其转换成项目需要的日期格式。
有些情况下还需要获取应用的第一次安装时间,PackageInfo中也有相应的字段:

public long firstInstallTime;

同理,也需要对其进行格式化。

(4) 获取Apk文件大小
要获取Apk文件大小,首先得找到Apk文件。就像我想周末和妹子去逛街,前提是我得有个妹子啊(打住,不说了,眼泪滴到键盘上了)
但是它到底在哪里呢?幻想着利用PackageManager是不行的,它根本没有类似于getApplicationApk( )的方法。
那怎么办呢?喔,还记得前面提到的PackageInfo中的ApplicationInfo字段么?我们继续去里面找,看看有没有啥收获,在源码501行发现一个字段:

public String sourceDir;

官方文档是这么描述的:Full path to the base APK for this application。嗯哼,bingo!找到了就是它,它代表了APK文件的完整路径。文件路径已经拿到了,啥都好办了(就像知道了妹子住哪里,就可以……..)

File apkFile = new File(packageInfo.applicationInfo.sourceDir);

我们将该路径封装成一个文件,再获取它的大小即可.

apkFile.length() / 1024 / 1024

在此处将文件大小转换成了MB单位,比如豌豆荚的APK文件为6.46MB

好了,想要的东西我们都找到了,我们用一个ListView把每个APK的相关信息作为item展示出来就行了。有个小问题请注意:获取手机中APK信息,这是一个耗时的过程,所以我们要在子线程中来做这个事情。

好了,看看做出来的效果

这里写图片描述

我们接着实现点击item分享Apk文件:

 private class ItemClickListenerImpl implements AdapterView.OnItemClickListener{@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position, long id) {File apkFile = mAppInfoList.get(position).getApkFile();Intent intent = new Intent();intent.setAction(Intent.ACTION_SEND);intent.setType("*/*");intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(apkFile));startActivity(intent);}}

在此处Apk文件放到intent中再调用系统自带的分享功能即可。

界面做出来了,功能也实现了,再回过头来看,其实不是很难。难点在于我们不知道——不知道它的icon和Apk文件到底放在哪里了。这让我想起了拉姆斯菲尔德的一段话:

We also know there are known unknowns; that is to say we know there
are some things we do not know. But there are also unknown unknowns –
the ones we don’t know we don’t know.

嘿嘿,我们不是不会,只是不知道罢了。

源码下载


http://www.ppmy.cn/news/368062.html

相关文章

【办公类-30-01】(Python)大班毕业证书批量打印(幼儿信息、性别、毕业日期、学校、公章、签名、证书日期)

背景需求 大班毕业在即&#xff0c;需要打印大班幼儿毕业证书。&#xff08;已有打印好的彩色证书&#xff09; 常规操作模式&#xff1a; 1&#xff0c;统一盖章&#xff0c;反复签字 200份证书&#xff0c;每张证书上需要盖园所章、园长签字200次 2. 每个班主任自己领取班…

letsencrypt certbot自动续订常用命令

查看证书信息 sudo certbot certificates返回 Found the following certs:Certificate Name: fileserver.kkappstore.comSerial Number: 31f31965a147edf46bdb32154d572201585Key Type: ECDSADomains: fileserver.kkappstore.comExpiry Date: 2023-08-02 03:02:3700:00 (VALI…

组合索引和单个索引的使用场景有什么不同

组合索引和单个索引在数据库查询中具有不同的使用场景。下面是它们的主要区别和适用场景&#xff1a; 单个索引&#xff1a; 单个索引是在单个列上创建的索引&#xff0c;用于加快对该列的查询和排序操作。适用于对单个列进行频繁的查询、排序或过滤操作的场景。适用于查询条…

Oracle 查询优化改写(第三章)

第三章 操作多个表 1.Union 与 OR 当在条件里面有or时&#xff0c;经常会改写为UNION&#xff0c;例如&#xff0c;我们在表emp中建立下面两个索引。 我们对比一下PLAN&#xff0c;会发现or走的FULLTABLE&#xff0c;而union使用的两列中的索引&#xff0c;从提高效率。 但在…

老版迅雷5.8无限制经典版

迅雷5.8不升级版是一款经典热门的P2P下载工具。迅雷5.8去广告绿色版已完全对弹出式广告进行屏蔽&#xff0c;并自动开启高速下载通道&#xff0c;支持磁力链接和网页下载&#xff0c;完美支持WIN8.1、WIN10&#xff0c;不定时检测去除无用组件&#xff0c;为用户提供绿色纯净的…

win7 sp1 x64 离线安装.net framework 4.6.1

在线安装vs2019出现如下问题&#xff0c;然后在线下载 .net framework 总是失败&#xff0c;具体如下图&#xff1a; 系统软硬件环境&#xff1a; win7 旗舰版 sp1 x64 &#xff1b;威强工控机 4G内存 。 然后去微软网站下载 .net framework 。 https:// support.microsoft.c…

精简迅雷绿色单文件版

精简迅雷绿色单文件版 精简迅雷绿色单文件版&#xff0c;是提取于某PE系统内&#xff0c;纯绿色单文件放在U盘里有备无患&#xff0c;需要的小伙伴们自行下载。 某些打不开的情况可能是缺少运行库&#xff1a;运行库 点击下载 上一篇&#xff1a;吃书百万自媒体作者凑字神器…

win7登录密码破解

win7下设置了用户和密码后&#xff0c;密码忘记了很头痛&#xff0c;下面我们来讲解一下如何破解密码&#xff1a; 1.首先搞一个U盘启动盘&#xff0c;然后插进到电脑中&#xff0c;把U盘设置为启动项&#xff0c;以戴尔optiplex 380一键U盘启动的方法为例&#xff0c;电脑开机…