目的:获取当前设备所有安装应用,并将该应用的安装包通过社会化分享 分享到其他地方!
解决问题:在应用安装完成之后,系统会自动或者半自动的将安装包进行清除,当想用这个apk文件的时候反而就找不到了,就得重新网络下载,通过此功能可以解决此一部分的问题,功能就是这么功能,具体功能使用怎么延伸就看各自的需求了。
结果演示:
实现思路:
通过packageManger来获取当前系统安装的应用数量,再分别获取应用的图标、包名、应用名、安装时间,获取应用路径获取Uri然后后实现应用的分享。文字比较简洁,思路也就是这么个思路
实现过程:
在真正的开发之前,有必要了解一下packageManager、packageInfo等类有哪些方法,附上链接大家有兴趣的可以看看(你得看啊,不然你能学到啥啊~~~)下图就是贴了个局部
一、首先创建APKUtils工具类,不要问我权限申请为什么这么多,因为我还有其他用处,你可以只申请读写内存的权限即可
public class APKUtils {
/**
* 获取应用的名称
* @param packageName
* @param context
* @return
*/
public static String getApplicationName(String packageName, Context context) {
PackageManager packageManager = context.getPackageManager();
String label = null;
try {
ApplicationInfo applicationInfo = packageManager.getApplicationInfo(packageName, 0);
label = (String) packageManager.getApplicationLabel(applicationInfo);
} catch (PackageManager.NameNotFoundException e) {
}
return label;
}
/**
* 获取应用图标
* @param context
* @param packageName
* @return
*/
public static Drawable loadIcon(Context context, String packageName) {
PackageManager packageManager = context.getPackageManager();
try {
return packageManager.getApplicationIcon(packageName);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
return context.getResources().getDrawable(R.mipmap.ic_launcher);
}
}
/**
* 计算apk文件大小
* @param packageInfo
* @return
*/
public static String getSize(PackageInfo packageInfo) {
String result = null;
String sourceDir = packageInfo.applicationInfo.sourceDir;
File file = new File(sourceDir);
long l = file.length() / 1024;
if (l >= 1024) {
long size = l / 1024;
result = size + " M";
} else {
result = l + " K";
}
return result;
}
/**
* 权限申请
* @param activity
*/
public static void getPermission(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// Android M Permission check
if (activity.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
activity.requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.READ_PHONE_STATE},
1);
}
}
}
二、配置 FileProvider 因为android7.0以上必须通过provider的形式进行文件访问
res文件下面创建xml文件,在xml文件中创建file_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<!--
1、name对应的属性值,开发者可以自由定义;
2、path对应的属性值,当前external-path标签下的相对路径
比如:/storage/emulated/0/92Recycle-release.apk
sdcard路径:/storage/emulated/0
相对路径:/
-->
<!--1、对应内部内存卡根目录:Context.getFileDir()-->
<files-path
name="int_root"
path="/" />
<!--2、对应应用默认缓存根目录:Context.getCacheDir()-->
<cache-path
name="app_cache"
path="/" />
<!--3、对应外部内存卡根目录:Environment.getExternalStorageDirectory()-->
<external-path
name="ext_root"
path="/" />
<!--4、对应外部内存卡根目录下的APP公共目录:Context.getExternalFileDir(String)-->
<external-files-path
name="ext_pub"
path="/" />
<!--5、对应外部内存卡根目录下的APP缓存目录:Context.getExternalCacheDir()-->
<external-cache-path
name="ext_cache"
path="/" />
<root-path
name="r_root"
path="/" />
</paths>
创建好之后再清单文件AndroidManifest.xml的 application节点内添加provider
<provider
// v4包name 和androidx的FileProvider会有不同 v4的是 android.support.v4.content.FileProvider
android:name="androidx.core.content.FileProvider"
android:authorities="包名.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
三、布局我用的是recyclerView 适配器如下(很简单,不详细介绍了):
public class APKAdapter extends RecyclerView.Adapter<APKAdapter.ViewHolder> implements View.OnClickListener {
private List<PackageInfo> mList;
private Context mContext;
public APKAdapter(List<PackageInfo> list, Context context) {
mList = list;
mContext = context;
}
@NonNull
@Override
public APKAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
ViewHolder holder = null;
View inflate = null;
if (holder != null) {
return holder;
}else {
inflate = LayoutInflater.from(mContext).inflate(R.layout.apk_item, viewGroup, false);
holder = new ViewHolder(inflate);
}
inflate.setOnClickListener(this);
return holder;
}
@Override
public void onBindViewHolder(@NonNull APKAdapter.ViewHolder viewHolder, int i) {
PackageInfo packageInfo = mList.get(i);
long updateTime = packageInfo.lastUpdateTime;
String packageName = packageInfo.packageName;
viewHolder.iv_icon.setImageDrawable(APKUtils.loadIcon(mContext,packageName));
viewHolder.tv_name.setText(packageName);
viewHolder.tv_date.setText(NumUtil.getDateFormat(updateTime));
viewHolder.tv_size.setText(APKUtils.getSize(packageInfo));
viewHolder.tv_app.setText(APKUtils.getApplicationName(packageName,mContext));
viewHolder.itemView.setTag(i);
}
@Override
public int getItemCount() {
int size = mList.size();
if (size>0){
return size;
}
return 0;
}
@Override
public void onClick(View v) {
if (onItemClickListener!=null){
onItemClickListener.onItemClickListener((Integer) v.getTag());
}
}
public class ViewHolder extends RecyclerView.ViewHolder {
ImageView iv_icon;
TextView tv_app,tv_name,tv_size,tv_date;
public ViewHolder(@NonNull View itemView) {
super(itemView);
iv_icon = itemView.findViewById(R.id.iv_icon);
tv_name = itemView.findViewById(R.id.tv_name);
tv_size = itemView.findViewById(R.id.tv_size);
tv_date = itemView.findViewById(R.id.tv_date);
tv_app = itemView.findViewById(R.id.tv_app);
}
}
private OnItemClickListener onItemClickListener;
public interface OnItemClickListener{
void onItemClickListener(int position);
}
public void setOnItemClickListener(OnItemClickListener onItemClickListener){
this.onItemClickListener = onItemClickListener;
}
}
布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:background="@drawable/ll_shape"
android:padding="5dp">
<ImageView
android:id="@+id/iv_icon"
android:layout_width="80dp"
android:layout_height="80dp"
android:src="@mipmap/logo512"
/>
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
android:layout_marginLeft="5dp"
android:orientation="vertical"
android:paddingLeft="@dimen/dp_10"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv_app"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="@dimen/sp_18"
android:textColor="@android:color/black"
android:text="applicationname"/>
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="@dimen/sp_18"
android:text="appname"/>
<TextView
android:id="@+id/tv_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="@dimen/sp_14"
android:text="100M"/>
<TextView
android:id="@+id/tv_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="@dimen/sp_14"
android:text="2019年10月24日16:07:36"/>
</LinearLayout>
</LinearLayout>
四、activity功能实现
public class APKActivity extends BaseActivity {
private RecyclerView mRecyclerView;
private List<PackageInfo> list;
private PackageManager mPackageManager;
private APKAdapter mAdapter;
private LinearLayoutManager mLinearLayoutManager;
@Override
public void onClick(View v) {
}
@Override
public int getLayoutId() {
return R.layout.activity_apk;
}
@Override
public void initView() {
APKUtils.getPermission(this);
mRecyclerView = findViewById(R.id.recyleView);
}
@Override
public void initData() {
mPackageManager = getApplicationContext().getPackageManager();
list = mPackageManager.getInstalledPackages(0);
mLinearLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLinearLayoutManager);
mAdapter = new APKAdapter(list, APKActivity.this);
mRecyclerView.setAdapter(mAdapter);
mAdapter.setOnItemClickListener(new APKAdapter.OnItemClickListener() {
@Override
public void onItemClickListener(int position) {
PackageInfo packageInfo = list.get(position);
String sourceDir = packageInfo.applicationInfo.sourceDir;
File apkFile = new File(sourceDir);
Uri uri = null;
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.N){ // android 7.0+
uri = FileProvider.getUriForFile(APKActivity.this,"包名.fileprovider",apkFile);
}else { // android 7.0-
uri = Uri.fromFile(new File(sourceDir));
}
Intent in = new Intent(Intent.ACTION_SEND);
in.setType("*/*");
in.putExtra(Intent.EXTRA_STREAM, uri);
startActivity(in);
}
});
}
}
activity的布局就是一个recyclerView 没什么好贴的了,整体实现就是这个样子,代码也基本算是完整的,如果用的话注意将包名进行一下替换就可以了