赞
踩
之前刚学安卓时,写过一篇“Android调用系统shareAPI实现分享转发功能”的文章,随着安卓版本的迭代更新以及其他APP的优化,安卓的这个shareAPI好像失效了,不怎么好使,已经获取不到有分享功能的APP列表,点击分享也会直接崩溃。并不是说我之前那篇文章的代码有错,只能说是时代有了变化,旧的方法已经不能满足新的需求,我并不打算删掉原来的那篇文章,旧文章地址如下(仅作参考):
最近开发一个收款APP,想把分享功能加入进去,然后发现旧的方法已经不行,这就难过了,网上一些大佬建议用第三方APP自带的分享SDK,但是我觉得用第三方的SDK太麻烦了,每个 APP都要申请接口账号和接口密钥,即便是使用其他人封装好的分享框架,也是需要去申请账号密钥的,一点也不方便,还是喜欢安卓原生态写法,简单便捷、一劳永逸。
经过我几番研究,最终完美实现了,效果图如下:
1、res/layout目录下创建share_dialog.xml
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="@drawable/shape_dialog_bg"
- android:orientation="vertical" >
-
- <TextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:padding="16dp"
- android:text="分享到..." />
-
- <HorizontalScrollView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:scrollbars="none" >
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent" >
-
- <GridView
- android:id="@+id/sharePopupWindow_gridView"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:scrollbars="none" />
- </LinearLayout>
- </HorizontalScrollView>
-
- <View
- android:layout_width="match_parent"
- android:layout_height="1px"
- android:alpha="0.3"
- android:background="#666" />
-
- <TextView
- android:id="@+id/sharePopupWindow_close"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:padding="20dp"
- android:text="取消"
- android:textSize="16sp" />
-
- </LinearLayout>
2、res/layout目录下创建appinfo_item.xml
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:orientation="vertical"
- android:paddingBottom="8dp"
- android:paddingLeft="16dp"
- android:paddingRight="16dp"
- android:paddingTop="8dp">
-
- <ImageView
- android:id="@+id/appinfo_item_icon"
- android:layout_width="48dp"
- android:layout_height="48dp"
- android:scaleType="centerCrop"
- android:src="@drawable/logo"/>
-
- <TextView
- android:id="@+id/appinfo_item_name"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="2dp"
- android:ellipsize="end"
- android:singleLine="true"
- android:textSize="12sp"
- android:text="分享到……"/>
- </LinearLayout>
3、在res/values/styles.xml 中,添加以下代码,用来实现弹出窗背景效果:
- <style name="circleDialog" parent="android:style/Theme.Dialog">
- <!-- 背景透明,设置圆角对话框必须设置背景透明,否则四角会有背景色小块-->
- <item name="android:windowBackground">@android:color/transparent</item>
- <!-- 没有标题 -->
- <item name="android:windowNoTitle">true</item>
- <!-- 背景模糊 -->
- <item name="android:backgroundDimEnabled">true</item>
- </style>
- package net.zy13.skhelper.entity;
-
- import android.graphics.drawable.Drawable;
-
- /**
- * APP信息实体类
- */
- public class AppInfo {
- private String appName;
- private String packageName;
- private String versionName;
- private int versionCode;
- private String launchClassName;
- private Drawable appIcon;
-
- public String getAppName() {
- return appName;
- }
-
- public void setAppName(String appName) {
- this.appName = appName;
- }
-
- public String getPackageName() {
- return packageName;
- }
-
- public void setPackageName(String packageName) {
- this.packageName = packageName;
- }
-
- public String getVersionName() {
- return versionName;
- }
-
- public void setVersionName(String versionName) {
- this.versionName = versionName;
- }
-
- public int getVersionCode() {
- return versionCode;
- }
-
- public void setVersionCode(int versionCode) {
- this.versionCode = versionCode;
- }
-
- public String getLaunchClassName() {
- return launchClassName;
- }
-
- public void setLaunchClassName(String launchClassName) {
- this.launchClassName = launchClassName;
- }
-
- public Drawable getAppIcon() {
- return appIcon;
- }
-
- public void setAppIcon(Drawable appIcon) {
- this.appIcon = appIcon;
- }
- }
- package net.zy13.skhelper.view;
-
- import java.io.File;
- import java.util.List;
-
- import android.app.ActionBar.LayoutParams;
- import android.content.ComponentName;
- import android.content.Context;
- import android.content.Intent;
- import android.graphics.Bitmap;
- import android.graphics.drawable.ColorDrawable;
- import android.net.Uri;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.widget.AdapterView;
- import android.widget.AdapterView.OnItemClickListener;
- import android.widget.GridView;
- import android.widget.LinearLayout;
- import android.widget.PopupWindow;
- import android.widget.TextView;
-
- import androidx.core.content.FileProvider;
-
- import net.zy13.skhelper.R;
- import net.zy13.skhelper.adapter.AppInfoAdapter;
- import net.zy13.skhelper.entity.AppInfo;
- import net.zy13.skhelper.utils.LogUtil;
- import net.zy13.skhelper.utils.MapTable;
- import net.zy13.skhelper.utils.ShareUtil;
-
- public class SharePopupWindow extends PopupWindow {
-
- //每行显示多少个
- private static final int NUM = 5;
-
- private View mMenuView;
- private GridView mGridView;
- private TextView mTextViewClose;
- private AppInfoAdapter mAdapter;
-
- private List<AppInfo> mAppinfoList;
-
- private String imgpath;
- private String shareTitle;
- private String shareContent;
- public void setImgpath(String imgpath) {
- this.imgpath = imgpath;
- }
- public void setShareTitle(String shareTitle) {
- this.shareTitle = shareTitle;
- }
- public void setShareContent(String shareContent) {
- this.shareContent = shareContent;
- }
-
- /**
- * 构造函数
- * @param context
- */
- public SharePopupWindow(final Context context) {
- super(context);
- LayoutInflater inflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- mMenuView = inflater.inflate(R.layout.share_dialog, null);
- //获取控件
- mGridView=(GridView) mMenuView.findViewById(R.id.sharePopupWindow_gridView);
- mTextViewClose=(TextView) mMenuView.findViewById(R.id.sharePopupWindow_close);
- //获取所有的非系统应用
- mAppinfoList = ShareUtil.getAllApps(context);
- //适配GridView
- mAdapter=new AppInfoAdapter(context, mAppinfoList);
- mGridView.setAdapter(mAdapter);
-
- //修改GridView
- changeGridView(context);
-
- mGridView.setOnItemClickListener(new OnItemClickListener() {
-
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position,
- long id) {
- // TODO Auto-generated method stub
- //使用其他APP打开文件
- Intent intent = new Intent();
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
- intent.setAction(Intent.ACTION_VIEW);
- //LogUtil.debug("图片地址:"+imgpath);
- //我这里分享的是图片,如果你要分享链接和文本,可以在这里自行发挥
- Uri uri = FileProvider.getUriForFile(context, "fileprovider", new File(imgpath));
- intent.setDataAndType(uri, MapTable.getMIMEType(imgpath));
- context.startActivity(intent);
- }
- });
- //取消按钮
- mTextViewClose.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View arg0) {
- // TODO Auto-generated method stub
- dismiss();
- }
- });
- //设置SelectPicPopupWindow的View
- this.setContentView(mMenuView);
- //设置SelectPicPopupWindow弹出窗体的宽
- this.setWidth(LayoutParams.FILL_PARENT);
- //设置SelectPicPopupWindow弹出窗体的高
- this.setHeight(LayoutParams.WRAP_CONTENT);
- //设置SelectPicPopupWindow弹出窗体可点击
- this.setFocusable(true);
- //设置窗口外也能点击(点击外面时,窗口可以关闭)
- this.setOutsideTouchable(true);
- //设置SelectPicPopupWindow弹出窗体动画效果
- this.setAnimationStyle(R.style.circleDialog);
- //实例化一个ColorDrawable颜色为半透明
- ColorDrawable dw = new ColorDrawable(0x00000000);
- //设置SelectPicPopupWindow弹出窗体的背景
- this.setBackgroundDrawable(dw);
- }
-
- /**
- * 将GridView改成单行横向布局
- */
- private void changeGridView(Context context) {
- // item宽度
- int itemWidth = dip2px(context, 90);
- // item之间的间隔
- int itemPaddingH = dip2px(context, 1);
- //计算一共显示多少行;
- int size = mAppinfoList.size();
- //int row=(size<=NUM) ? 1 :( (size%NUM>0) ? size/NUM+1 : size/NUM );
- //每行真正显示多少个
- int rowitem = (size<NUM)?size:NUM;
- // 计算GridView宽度
- int gridviewWidth = rowitem * (itemWidth + itemPaddingH);
- LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
- gridviewWidth, LinearLayout.LayoutParams.MATCH_PARENT);
- mGridView.setLayoutParams(params);
- mGridView.setColumnWidth(itemWidth);
- mGridView.setHorizontalSpacing(itemPaddingH);
- mGridView.setStretchMode(GridView.NO_STRETCH);
- mGridView.setNumColumns(rowitem);
- }
-
- /**
- * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
- * @param context 上下文
- * @param dpValue dp值
- * @return px值
- */
- public static int dip2px(Context context, float dpValue) {
- final float scale = context.getResources().getDisplayMetrics().density;
- return (int) (dpValue * scale + 0.5f);
- }
-
- }
1、在清单文件AndroidManifest.xml
的<application>标签内添加provider
- <provider
- 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/filepaths"/>
- </provider>
注意:要与activity标签同级
2、在res/xml目录添加filepaths.xml,代码如下:
- <?xml version="1.0" encoding="utf-8"?>
- <paths xmlns:android="http://schemas.android.com/apk/res/android">
- <!--
- 1、name对应的属性值,开发者可以自由定义;
- 2、path对应的属性值,当前external-path标签下的相对路径
- -->
- <!--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="Documents/" />
- <!--4、对应外部内存卡根目录下的APP公共目录:Context.getExternalFileDir(Environment.DIRECTORY_PICTURES)-->
- <external-files-path
- name="ext_pub"
- path="/" />
- <!--5、对应外部内存卡根目录下的APP缓存目录:Context.getExternalCacheDir()-->
- <external-cache-path
- name="ext_cache"
- path="/" />
- </paths>
- package net.zy13.skhelper.utils;
-
- import android.content.Context;
- import android.content.Intent;
- import android.content.pm.ApplicationInfo;
- import android.content.pm.PackageInfo;
- import android.content.pm.PackageManager;
- import android.content.pm.ResolveInfo;
- import android.graphics.Bitmap;
-
- import net.zy13.skhelper.MainApplication;
- import net.zy13.skhelper.entity.AppInfo;
-
- import java.io.BufferedOutputStream;
- import java.io.File;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.util.ArrayList;
- import java.util.List;
-
- public class ShareUtil {
- /**
- * 查询手机内所有的应用列表
- * @param context
- * @return
- */
- public static List<AppInfo> getAllApps(Context context) {
- List<AppInfo> appList = new ArrayList<AppInfo>();
- PackageManager pm=context.getPackageManager();
- List<PackageInfo> packages = pm.getInstalledPackages(0);
- for (int i = 0;i< packages.size();i++) {
- PackageInfo packageInfo = packages.get(i);
- AppInfo tmpInfo = new AppInfo();
- tmpInfo.setAppName(packageInfo.applicationInfo.loadLabel(pm).toString());
- tmpInfo.setPackageName(packageInfo.packageName);
- tmpInfo.setVersionName(packageInfo.versionName);
- tmpInfo.setVersionCode(packageInfo.versionCode);
- tmpInfo.setAppIcon(packageInfo.applicationInfo.loadIcon(pm));
- //如果非系统应用,则添加至appList
- if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
- //排除当前应用(替换成你的应用包名即可)
- if(!packageInfo.packageName.equals("net.zy13.skhelper")) {
- appList.add(tmpInfo);
- }
- }
- }
- return appList;
- }
- /**
- * 保存图片到缓存里
- * @param bitmap
- * @return
- */
- public static String SaveTitmapToCache(Bitmap bitmap){
- // 默认保存在应用缓存目录里 Context.getCacheDir()
- File file=new File(MainApplication.getAppContext().getCacheDir(),System.currentTimeMillis()+".png");
- try {
- BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
- bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
- bos.flush();
- bos.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- return file.getPath();
- }
- }
- package net.zy13.skhelper.adapter;
-
- import android.annotation.SuppressLint;
- import android.content.Context;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.AdapterView.OnItemClickListener;
- import android.widget.BaseAdapter;
- import android.widget.ImageView;
- import android.widget.TextView;
-
- import net.zy13.skhelper.R;
- import net.zy13.skhelper.entity.AppInfo;
-
- import java.util.List;
-
- public class AppInfoAdapter extends BaseAdapter {
-
- private Context context;
- private List<AppInfo> mAppinfoList;
- private OnItemClickListener mOnItemClickLitener;
-
- public AppInfoAdapter(Context context, List<AppInfo> mAppinfoList) {
- super();
- this.context = context;
- this.mAppinfoList = mAppinfoList;
- }
-
- @Override
- public int getCount() {
- // TODO Auto-generated method stub
- return mAppinfoList.size();
- }
-
- @Override
- public Object getItem(int arg0) {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public long getItemId(int arg0) {
- // TODO Auto-generated method stub
- return 0;
- }
-
- @SuppressLint("NewApi")
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- // TODO Auto-generated method stub
- AppInfo appInfo = mAppinfoList.get(position);
- // 加载布局
- View view;
- ViewHolder viewHolder;
- if (convertView == null) {
- view = LayoutInflater.from(context).inflate(R.layout.appinfo_item, null);
- viewHolder = new ViewHolder(view);
- // 将ViewHolder存储在View中
- view.setTag(viewHolder);
- } else {
- view = convertView;
- // 重新获取ViewHolder
- viewHolder = (ViewHolder) view.getTag();
-
- }
- //设置控件的值
- viewHolder.imageViewIcon.setImageDrawable(appInfo.getAppIcon());
- String name=appInfo.getAppName();
- viewHolder.textViewName.setText(name);
- return view;
- }
-
- class ViewHolder {
- ImageView imageViewIcon;
- TextView textViewName;
-
- public ViewHolder(View view) {
- this.imageViewIcon = (ImageView) view.findViewById(R.id.appinfo_item_icon);
- this.textViewName = (TextView) view.findViewById(R.id.appinfo_item_name);
- }
- }
-
- }
- private LinearLayout mLayoutRoot;
- private ImageView mImageView;
-
- //获取根布局
- mLayoutRoot=(LinearLayout)view.findViewById(R.id.LayoutRoot);
- //获取图片控件
- mImageView=(ImageView)view.findViewById(R.id.image_qrcode);
-
-
- // 获取ImageView图片
- mImageView.setDrawingCacheEnabled(true);
- Bitmap bitmap =Bitmap.createBitmap(mImageViewQrcode.getDrawingCache());
- mImageView.setDrawingCacheEnabled(false);
- String imgpath=ShareUtil.SaveTitmapToCache(bitmap);
- //实例化分享窗口
- SharePopupWindow spw = new SharePopupWindow(mContext);
- spw.setImgpath(imgpath);
- // 显示窗口
- spw.showAtLocation(mLayoutRoot, Gravity.BOTTOM, 0, 0);
Android11以上版本增加了包可见性,因此需要在AndroidManifest.xml清单文件中,申请查询所有的应用的权限:
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" tools:ignore="QueryAllPackagesPermission" />
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。