导读:

之前刚学安卓时,写过一篇“Android调用系统shareAPI实现分享转发功能”的文章,随着安卓版本的迭代更新以及其他APP的优化,安卓的这个shareAPI好像失效了,不怎么好使,已经获取不到有分享功能的APP列表,点击分享也会直接崩溃。并不是说我之前那篇文章的代码有错,只能说是时代有了变化,旧的方法已经不能满足新的需求,我并不打算删掉原来的那篇文章,旧文章地址如下(仅作参考):

Android调用系统shareAPI实现分享转发功能_美奇软件开发工作室-CSDN博客需求分析:在开发APP过程中,一般都需要实现分享转发,比如分享到QQ、微信等,这里我使用的是安卓系统自带的shareAPI,可以直接通过ResolveInfo获取手机中所有提供分享接口的应用,从而实现分享功能。首先给大家看一下手机上的效果图:Demo源代码下载地址:https://download.csdn.net/download/qq15577969/10670207一、x...https://blog.csdn.net/qq15577969/article/details/82725897

最近开发一个收款APP,想把分享功能加入进去,然后发现旧的方法已经不行,这就难过了,网上一些大佬建议用第三方APP自带的分享SDK,但是我觉得用第三方的SDK太麻烦了,每个 APP都要申请接口账号和接口密钥,即便是使用其他人封装好的分享框架,也是需要去申请账号密钥的,一点也不方便,还是喜欢安卓原生态写法,简单便捷、一劳永逸。

经过我几番研究,最终完美实现了,效果图如下:

一、xml布局文件

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" ><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:padding="16dp"android:text="分享到..." /><HorizontalScrollViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:scrollbars="none" ><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent" ><GridViewandroid:id="@+id/sharePopupWindow_gridView"android:layout_width="match_parent"android:layout_height="match_parent"android:scrollbars="none" /></LinearLayout></HorizontalScrollView><Viewandroid:layout_width="match_parent"android:layout_height="1px"android:alpha="0.3"android:background="#666" /><TextViewandroid: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"><ImageViewandroid:id="@+id/appinfo_item_icon"android:layout_width="48dp"android:layout_height="48dp"android:scaleType="centerCrop"android:src="@drawable/logo"/><TextViewandroid: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>

二、创建一个实体类 AppInfo.java,用来保存应用信息

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;}
}

三、重写PopupWindow控件SharePopupWindow.java,自定义分享的弹窗

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);//适配GridViewmAdapter=new AppInfoAdapter(context, mAppinfoList);mGridView.setAdapter(mAdapter);//修改GridViewchangeGridView(context);mGridView.setOnItemClickListener(new OnItemClickListener() {@Overridepublic 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() {@Overridepublic void onClick(View arg0) {// TODO Auto-generated method stubdismiss();}});//设置SelectPicPopupWindow的Viewthis.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);}}

四、使用provider

1、在清单文件AndroidManifest.xml
的<application>标签内添加provider

<providerandroid:name="androidx.core.content.FileProvider"android:authorities="fileprovider"android:exported="false"android:grantUriPermissions="true"><meta-dataandroid: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-pathname="int_root"path="/" /><!--2、对应应用默认缓存根目录:Context.getCacheDir()--><cache-pathname="app_cache"path="/" /><!--3、对应外部内存卡根目录:Environment.getExternalStorageDirectory()--><external-pathname="ext_root"path="Documents/" /><!--4、对应外部内存卡根目录下的APP公共目录:Context.getExternalFileDir(Environment.DIRECTORY_PICTURES)--><external-files-pathname="ext_pub"path="/" /><!--5、对应外部内存卡根目录下的APP缓存目录:Context.getExternalCacheDir()--><external-cache-pathname="ext_cache"path="/" />
</paths>

四、写一个工具类 
ShareUtil.java

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));//如果非系统应用,则添加至appListif ((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();}
}

五、GridView的适配器 AppInfoAdapter.java

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;}@Overridepublic int getCount() {// TODO Auto-generated method stubreturn mAppinfoList.size();}@Overridepublic Object getItem(int arg0) {// TODO Auto-generated method stubreturn null;}@Overridepublic long getItemId(int arg0) {// TODO Auto-generated method stubreturn 0;}@SuppressLint("NewApi")@Overridepublic View getView(int position, View convertView, ViewGroup parent) {// TODO Auto-generated method stubAppInfo 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;// 重新获取ViewHolderviewHolder = (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);}}}

六、自定义分享窗口SharePopupWindow的调用

 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权限申请

Android11以上版本增加了包可见性,因此需要在AndroidManifest.xml清单文件中,申请查询所有的应用的权限:

<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" tools:ignore="QueryAllPackagesPermission" />

Android原生态实现分享转发功能(分享图片到其他APP)相关推荐

  1. 微信小程序开发 自定义按钮实现分享转发功能

    文章目录 前言 一.详细步骤 前言 微信小程序,默认的分享功能是通过右上角的 "···" 按钮调用的,那么如何通过自定义按钮调用呢?本文将给出具体方法. 一.详细步骤 我采用了mp ...

  2. 企业微信的分享/转发功能

    一.首先呢肯定是要参考企业微信的客户端API 1.JS-SDK里面的使用说明 引入js文件<script src="//res.wx.qq.com/open/js/jweixin-1. ...

  3. 微信分享转发功能「PHP版」

    <script src="https://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script> <scr ...

  4. android 短信自动转发功能

    1.首先需要申请权限 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:andro ...

  5. 易分享商家活动分享转发链接分享朋友圈领红包

    请你认真想一想,你每天投入广告宣传,为你带来的效果如何? 假设你投了1千元的广告费,你赚了2千元,那么你的广告是成功的,因为你得到了一倍的利润. 如果还是同样的销售文案,使用红包拓客软件,就能赚10万 ...

  6. Android实现新浪微博SSO授权登录分享文字图片等功能(WEIBO_ANDROID_SDK V2.3.0 )

    新浪开发平台:http://open.weibo.com 新浪微博分享目前分为两种途径: 1,直接在自己的APP,弹出类似Dialog(sina集成)来完成授权,授权成功后可直接分享内容,全程都是在自 ...

  7. Android 微信分享与QQ分享功能(原生实现)

    微信分享与QQ分享功能现在都挺常见的,可以根据一些第三方社会化分功能快速实现,不过多多少少都不怎么纯净,最好都是自己看官方文档来实现就最好了~ 一.微信分享 微信分享功能需要先在微信开放平台注册应用并 ...

  8. android 分享二维码图片到微信QQ(url地址字符串生成二维码图片、分享二维码图片到微信QQ)

    主要用到的功能 1.url地址字符串生成二维码图片 2.分享二维码图片到微信QQ 所需的依赖包 implementation 'com.google.zxing:core:3.0.1' 代码 1.将U ...

  9. LINE分享android利用系统自带分享实现LINE分享功能

    android利用系统自带分享实现分享功能之LINE分享 最近公司向海外发展,提出了一个国外主流的社交APP分享需求.原来我使用的是第三方分享工具,但是太鸡肋,国内的APP支持的还是不错的,但是国外支 ...

  10. android分享分享到朋友圈图片,android7.0 通过代码 分享图片到朋友圈

    转载注明出处:简书-十个雨点 在Android7.0中,系统对scheme为file://的uri进行了限制,所以通过这种uri来进行分享的一些接口就不能用了,比如使用代码来调用分享朋友圈的接口. 此 ...

最新文章

  1. Spring MVC 的xml一些配置
  2. python io_python-IO
  3. 戴尔为例 浅谈电子商务时代客户关系管理
  4. 下列支持mysql中文字符_MySQL中文支持问题
  5. python语言程序设计难不难_零基础学Python编程开发难度大吗?从哪学起?
  6. 传世的关系模型,巧夺天工的分布式数据库设计
  7. 基础html的网页,[网页设计]HTML基础(五)——
  8. Oracle-1:的列操作(增加列,修改列,删除列),包括操作多列
  9. GIT在WINDOWS/LINUX下载的源码,回车换行有差异
  10. 正则表达式 RegExp【详解】
  11. STM32学习心得三十一:485通信原理及实验
  12. 【.NET程序员面试题----初级】第一卷
  13. 创建VSIX项目模板
  14. Alpha测试 / Beta测试 / 黑盒测试 /白盒测试概述
  15. CES2020即将完结!盘点这些脑洞产品,保证你看一眼就被种草
  16. linux 远程启动带gui程序,通过 ssh 运行 远程linux GUI 的方法.
  17. seo怎么优化:手把手的教你SEO优化代码
  18. 麻省理工计算机导论公开课,网易公开课给大一新生“量身订做”精品课程
  19. vue与C#实现自定义表单审批流程构建-后端
  20. 【算法讲10:自适应辛普森法】求平滑曲线积分近似 | 洛谷 P4526 | HDU1724 | QLU Youmu with Master spark

热门文章

  1. 浏览器打开默认为360主页,如何修改
  2. html导航栏所有页面通用,在所有页面中包含HTML导航栏
  3. 项目管理-----整合项目资源
  4. 用python实现基于PANN(retrained Audio Neural Networks)的声音检测方法
  5. 一个开源在线IDE项目
  6. Linux设置串口波特率等参数
  7. Postman设置请求cookie
  8. lol微信登录服务器,LOL开启微信登录功能测试 绑定微信登陆方法一览
  9. 云计算机运维是什么,云计算运维管理是什么?
  10. 软件测试优秀员工发言稿,2018软件测试国赛获奖感言|2018年优秀员工获奖感言