当前位置:   article > 正文

Android原生态实现分享转发功能(分享图片到其他APP)_android 微信分享的图片到第三方怎么弄

android 微信分享的图片到第三方怎么弄

导读:

之前刚学安卓时,写过一篇“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

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:background="@drawable/shape_dialog_bg"
  6. android:orientation="vertical" >
  7. <TextView
  8. android:layout_width="match_parent"
  9. android:layout_height="wrap_content"
  10. android:padding="16dp"
  11. android:text="分享到..." />
  12. <HorizontalScrollView
  13. android:layout_width="match_parent"
  14. android:layout_height="wrap_content"
  15. android:scrollbars="none" >
  16. <LinearLayout
  17. android:layout_width="match_parent"
  18. android:layout_height="match_parent" >
  19. <GridView
  20. android:id="@+id/sharePopupWindow_gridView"
  21. android:layout_width="match_parent"
  22. android:layout_height="match_parent"
  23. android:scrollbars="none" />
  24. </LinearLayout>
  25. </HorizontalScrollView>
  26. <View
  27. android:layout_width="match_parent"
  28. android:layout_height="1px"
  29. android:alpha="0.3"
  30. android:background="#666" />
  31. <TextView
  32. android:id="@+id/sharePopupWindow_close"
  33. android:layout_width="match_parent"
  34. android:layout_height="wrap_content"
  35. android:gravity="center"
  36. android:padding="20dp"
  37. android:text="取消"
  38. android:textSize="16sp" />
  39. </LinearLayout>

2、res/layout目录下创建appinfo_item.xml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="wrap_content"
  5. android:gravity="center"
  6. android:orientation="vertical"
  7. android:paddingBottom="8dp"
  8. android:paddingLeft="16dp"
  9. android:paddingRight="16dp"
  10. android:paddingTop="8dp">
  11. <ImageView
  12. android:id="@+id/appinfo_item_icon"
  13. android:layout_width="48dp"
  14. android:layout_height="48dp"
  15. android:scaleType="centerCrop"
  16. android:src="@drawable/logo"/>
  17. <TextView
  18. android:id="@+id/appinfo_item_name"
  19. android:layout_width="wrap_content"
  20. android:layout_height="wrap_content"
  21. android:layout_marginTop="2dp"
  22. android:ellipsize="end"
  23. android:singleLine="true"
  24. android:textSize="12sp"
  25. android:text="分享到……"/>
  26. </LinearLayout>

3、在res/values/styles.xml 中,添加以下代码,用来实现弹出窗背景效果:

  1. <style name="circleDialog" parent="android:style/Theme.Dialog">
  2. <!-- 背景透明,设置圆角对话框必须设置背景透明,否则四角会有背景色小块-->
  3. <item name="android:windowBackground">@android:color/transparent</item>
  4. <!-- 没有标题 -->
  5. <item name="android:windowNoTitle">true</item>
  6. <!-- 背景模糊 -->
  7. <item name="android:backgroundDimEnabled">true</item>
  8. </style>

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

  1. package net.zy13.skhelper.entity;
  2. import android.graphics.drawable.Drawable;
  3. /**
  4. * APP信息实体类
  5. */
  6. public class AppInfo {
  7. private String appName;
  8. private String packageName;
  9. private String versionName;
  10. private int versionCode;
  11. private String launchClassName;
  12. private Drawable appIcon;
  13. public String getAppName() {
  14. return appName;
  15. }
  16. public void setAppName(String appName) {
  17. this.appName = appName;
  18. }
  19. public String getPackageName() {
  20. return packageName;
  21. }
  22. public void setPackageName(String packageName) {
  23. this.packageName = packageName;
  24. }
  25. public String getVersionName() {
  26. return versionName;
  27. }
  28. public void setVersionName(String versionName) {
  29. this.versionName = versionName;
  30. }
  31. public int getVersionCode() {
  32. return versionCode;
  33. }
  34. public void setVersionCode(int versionCode) {
  35. this.versionCode = versionCode;
  36. }
  37. public String getLaunchClassName() {
  38. return launchClassName;
  39. }
  40. public void setLaunchClassName(String launchClassName) {
  41. this.launchClassName = launchClassName;
  42. }
  43. public Drawable getAppIcon() {
  44. return appIcon;
  45. }
  46. public void setAppIcon(Drawable appIcon) {
  47. this.appIcon = appIcon;
  48. }
  49. }

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

  1. package net.zy13.skhelper.view;
  2. import java.io.File;
  3. import java.util.List;
  4. import android.app.ActionBar.LayoutParams;
  5. import android.content.ComponentName;
  6. import android.content.Context;
  7. import android.content.Intent;
  8. import android.graphics.Bitmap;
  9. import android.graphics.drawable.ColorDrawable;
  10. import android.net.Uri;
  11. import android.view.LayoutInflater;
  12. import android.view.View;
  13. import android.view.View.OnClickListener;
  14. import android.widget.AdapterView;
  15. import android.widget.AdapterView.OnItemClickListener;
  16. import android.widget.GridView;
  17. import android.widget.LinearLayout;
  18. import android.widget.PopupWindow;
  19. import android.widget.TextView;
  20. import androidx.core.content.FileProvider;
  21. import net.zy13.skhelper.R;
  22. import net.zy13.skhelper.adapter.AppInfoAdapter;
  23. import net.zy13.skhelper.entity.AppInfo;
  24. import net.zy13.skhelper.utils.LogUtil;
  25. import net.zy13.skhelper.utils.MapTable;
  26. import net.zy13.skhelper.utils.ShareUtil;
  27. public class SharePopupWindow extends PopupWindow {
  28. //每行显示多少个
  29. private static final int NUM = 5;
  30. private View mMenuView;
  31. private GridView mGridView;
  32. private TextView mTextViewClose;
  33. private AppInfoAdapter mAdapter;
  34. private List<AppInfo> mAppinfoList;
  35. private String imgpath;
  36. private String shareTitle;
  37. private String shareContent;
  38. public void setImgpath(String imgpath) {
  39. this.imgpath = imgpath;
  40. }
  41. public void setShareTitle(String shareTitle) {
  42. this.shareTitle = shareTitle;
  43. }
  44. public void setShareContent(String shareContent) {
  45. this.shareContent = shareContent;
  46. }
  47. /**
  48. * 构造函数
  49. * @param context
  50. */
  51. public SharePopupWindow(final Context context) {
  52. super(context);
  53. LayoutInflater inflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  54. mMenuView = inflater.inflate(R.layout.share_dialog, null);
  55. //获取控件
  56. mGridView=(GridView) mMenuView.findViewById(R.id.sharePopupWindow_gridView);
  57. mTextViewClose=(TextView) mMenuView.findViewById(R.id.sharePopupWindow_close);
  58. //获取所有的非系统应用
  59. mAppinfoList = ShareUtil.getAllApps(context);
  60. //适配GridView
  61. mAdapter=new AppInfoAdapter(context, mAppinfoList);
  62. mGridView.setAdapter(mAdapter);
  63. //修改GridView
  64. changeGridView(context);
  65. mGridView.setOnItemClickListener(new OnItemClickListener() {
  66. @Override
  67. public void onItemClick(AdapterView<?> parent, View view, int position,
  68. long id) {
  69. // TODO Auto-generated method stub
  70. //使用其他APP打开文件
  71. Intent intent = new Intent();
  72. intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  73. intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
  74. intent.setAction(Intent.ACTION_VIEW);
  75. //LogUtil.debug("图片地址:"+imgpath);
  76. //我这里分享的是图片,如果你要分享链接和文本,可以在这里自行发挥
  77. Uri uri = FileProvider.getUriForFile(context, "fileprovider", new File(imgpath));
  78. intent.setDataAndType(uri, MapTable.getMIMEType(imgpath));
  79. context.startActivity(intent);
  80. }
  81. });
  82. //取消按钮
  83. mTextViewClose.setOnClickListener(new OnClickListener() {
  84. @Override
  85. public void onClick(View arg0) {
  86. // TODO Auto-generated method stub
  87. dismiss();
  88. }
  89. });
  90. //设置SelectPicPopupWindow的View
  91. this.setContentView(mMenuView);
  92. //设置SelectPicPopupWindow弹出窗体的宽
  93. this.setWidth(LayoutParams.FILL_PARENT);
  94. //设置SelectPicPopupWindow弹出窗体的高
  95. this.setHeight(LayoutParams.WRAP_CONTENT);
  96. //设置SelectPicPopupWindow弹出窗体可点击
  97. this.setFocusable(true);
  98. //设置窗口外也能点击(点击外面时,窗口可以关闭)
  99. this.setOutsideTouchable(true);
  100. //设置SelectPicPopupWindow弹出窗体动画效果
  101. this.setAnimationStyle(R.style.circleDialog);
  102. //实例化一个ColorDrawable颜色为半透明
  103. ColorDrawable dw = new ColorDrawable(0x00000000);
  104. //设置SelectPicPopupWindow弹出窗体的背景
  105. this.setBackgroundDrawable(dw);
  106. }
  107. /**
  108. * 将GridView改成单行横向布局
  109. */
  110. private void changeGridView(Context context) {
  111. // item宽度
  112. int itemWidth = dip2px(context, 90);
  113. // item之间的间隔
  114. int itemPaddingH = dip2px(context, 1);
  115. //计算一共显示多少行;
  116. int size = mAppinfoList.size();
  117. //int row=(size<=NUM) ? 1 :( (size%NUM>0) ? size/NUM+1 : size/NUM );
  118. //每行真正显示多少个
  119. int rowitem = (size<NUM)?size:NUM;
  120. // 计算GridView宽度
  121. int gridviewWidth = rowitem * (itemWidth + itemPaddingH);
  122. LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
  123. gridviewWidth, LinearLayout.LayoutParams.MATCH_PARENT);
  124. mGridView.setLayoutParams(params);
  125. mGridView.setColumnWidth(itemWidth);
  126. mGridView.setHorizontalSpacing(itemPaddingH);
  127. mGridView.setStretchMode(GridView.NO_STRETCH);
  128. mGridView.setNumColumns(rowitem);
  129. }
  130. /**
  131. * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
  132. * @param context 上下文
  133. * @param dpValue dp值
  134. * @return px值
  135. */
  136. public static int dip2px(Context context, float dpValue) {
  137. final float scale = context.getResources().getDisplayMetrics().density;
  138. return (int) (dpValue * scale + 0.5f);
  139. }
  140. }

四、使用provider

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

  1. <provider
  2. android:name="androidx.core.content.FileProvider"
  3. android:authorities="fileprovider"
  4. android:exported="false"
  5. android:grantUriPermissions="true">
  6. <meta-data
  7. android:name="android.support.FILE_PROVIDER_PATHS"
  8. android:resource="@xml/filepaths"/>
  9. </provider>

注意:要与activity标签同级 

 2、在res/xml目录添加filepaths.xml,代码如下:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <paths xmlns:android="http://schemas.android.com/apk/res/android">
  3. <!--
  4. 1、name对应的属性值,开发者可以自由定义;
  5. 2、path对应的属性值,当前external-path标签下的相对路径
  6. -->
  7. <!--1、对应内部内存卡根目录:Context.getFileDir()-->
  8. <files-path
  9. name="int_root"
  10. path="/" />
  11. <!--2、对应应用默认缓存根目录:Context.getCacheDir()-->
  12. <cache-path
  13. name="app_cache"
  14. path="/" />
  15. <!--3、对应外部内存卡根目录:Environment.getExternalStorageDirectory()-->
  16. <external-path
  17. name="ext_root"
  18. path="Documents/" />
  19. <!--4、对应外部内存卡根目录下的APP公共目录:Context.getExternalFileDir(Environment.DIRECTORY_PICTURES)-->
  20. <external-files-path
  21. name="ext_pub"
  22. path="/" />
  23. <!--5、对应外部内存卡根目录下的APP缓存目录:Context.getExternalCacheDir()-->
  24. <external-cache-path
  25. name="ext_cache"
  26. path="/" />
  27. </paths>

四、写一个工具类 
ShareUtil.java

  1. package net.zy13.skhelper.utils;
  2. import android.content.Context;
  3. import android.content.Intent;
  4. import android.content.pm.ApplicationInfo;
  5. import android.content.pm.PackageInfo;
  6. import android.content.pm.PackageManager;
  7. import android.content.pm.ResolveInfo;
  8. import android.graphics.Bitmap;
  9. import net.zy13.skhelper.MainApplication;
  10. import net.zy13.skhelper.entity.AppInfo;
  11. import java.io.BufferedOutputStream;
  12. import java.io.File;
  13. import java.io.FileOutputStream;
  14. import java.io.IOException;
  15. import java.util.ArrayList;
  16. import java.util.List;
  17. public class ShareUtil {
  18. /**
  19. * 查询手机内所有的应用列表
  20. * @param context
  21. * @return
  22. */
  23. public static List<AppInfo> getAllApps(Context context) {
  24. List<AppInfo> appList = new ArrayList<AppInfo>();
  25. PackageManager pm=context.getPackageManager();
  26. List<PackageInfo> packages = pm.getInstalledPackages(0);
  27. for (int i = 0;i< packages.size();i++) {
  28. PackageInfo packageInfo = packages.get(i);
  29. AppInfo tmpInfo = new AppInfo();
  30. tmpInfo.setAppName(packageInfo.applicationInfo.loadLabel(pm).toString());
  31. tmpInfo.setPackageName(packageInfo.packageName);
  32. tmpInfo.setVersionName(packageInfo.versionName);
  33. tmpInfo.setVersionCode(packageInfo.versionCode);
  34. tmpInfo.setAppIcon(packageInfo.applicationInfo.loadIcon(pm));
  35. //如果非系统应用,则添加至appList
  36. if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
  37. //排除当前应用(替换成你的应用包名即可)
  38. if(!packageInfo.packageName.equals("net.zy13.skhelper")) {
  39. appList.add(tmpInfo);
  40. }
  41. }
  42. }
  43. return appList;
  44. }
  45. /**
  46. * 保存图片到缓存里
  47. * @param bitmap
  48. * @return
  49. */
  50. public static String SaveTitmapToCache(Bitmap bitmap){
  51. // 默认保存在应用缓存目录里 Context.getCacheDir()
  52. File file=new File(MainApplication.getAppContext().getCacheDir(),System.currentTimeMillis()+".png");
  53. try {
  54. BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
  55. bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
  56. bos.flush();
  57. bos.close();
  58. } catch (IOException e) {
  59. e.printStackTrace();
  60. }
  61. return file.getPath();
  62. }
  63. }

五、GridView的适配器 AppInfoAdapter.java

  1. package net.zy13.skhelper.adapter;
  2. import android.annotation.SuppressLint;
  3. import android.content.Context;
  4. import android.view.LayoutInflater;
  5. import android.view.View;
  6. import android.view.ViewGroup;
  7. import android.widget.AdapterView.OnItemClickListener;
  8. import android.widget.BaseAdapter;
  9. import android.widget.ImageView;
  10. import android.widget.TextView;
  11. import net.zy13.skhelper.R;
  12. import net.zy13.skhelper.entity.AppInfo;
  13. import java.util.List;
  14. public class AppInfoAdapter extends BaseAdapter {
  15. private Context context;
  16. private List<AppInfo> mAppinfoList;
  17. private OnItemClickListener mOnItemClickLitener;
  18. public AppInfoAdapter(Context context, List<AppInfo> mAppinfoList) {
  19. super();
  20. this.context = context;
  21. this.mAppinfoList = mAppinfoList;
  22. }
  23. @Override
  24. public int getCount() {
  25. // TODO Auto-generated method stub
  26. return mAppinfoList.size();
  27. }
  28. @Override
  29. public Object getItem(int arg0) {
  30. // TODO Auto-generated method stub
  31. return null;
  32. }
  33. @Override
  34. public long getItemId(int arg0) {
  35. // TODO Auto-generated method stub
  36. return 0;
  37. }
  38. @SuppressLint("NewApi")
  39. @Override
  40. public View getView(int position, View convertView, ViewGroup parent) {
  41. // TODO Auto-generated method stub
  42. AppInfo appInfo = mAppinfoList.get(position);
  43. // 加载布局
  44. View view;
  45. ViewHolder viewHolder;
  46. if (convertView == null) {
  47. view = LayoutInflater.from(context).inflate(R.layout.appinfo_item, null);
  48. viewHolder = new ViewHolder(view);
  49. // 将ViewHolder存储在View中
  50. view.setTag(viewHolder);
  51. } else {
  52. view = convertView;
  53. // 重新获取ViewHolder
  54. viewHolder = (ViewHolder) view.getTag();
  55. }
  56. //设置控件的值
  57. viewHolder.imageViewIcon.setImageDrawable(appInfo.getAppIcon());
  58. String name=appInfo.getAppName();
  59. viewHolder.textViewName.setText(name);
  60. return view;
  61. }
  62. class ViewHolder {
  63. ImageView imageViewIcon;
  64. TextView textViewName;
  65. public ViewHolder(View view) {
  66. this.imageViewIcon = (ImageView) view.findViewById(R.id.appinfo_item_icon);
  67. this.textViewName = (TextView) view.findViewById(R.id.appinfo_item_name);
  68. }
  69. }
  70. }

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

  1. private LinearLayout mLayoutRoot;
  2. private ImageView mImageView;
  3. //获取根布局
  4. mLayoutRoot=(LinearLayout)view.findViewById(R.id.LayoutRoot);
  5. //获取图片控件
  6. mImageView=(ImageView)view.findViewById(R.id.image_qrcode);
  7. // 获取ImageView图片
  8. mImageView.setDrawingCacheEnabled(true);
  9. Bitmap bitmap =Bitmap.createBitmap(mImageViewQrcode.getDrawingCache());
  10. mImageView.setDrawingCacheEnabled(false);
  11. String imgpath=ShareUtil.SaveTitmapToCache(bitmap);
  12. //实例化分享窗口
  13. SharePopupWindow spw = new SharePopupWindow(mContext);
  14. spw.setImgpath(imgpath);
  15. // 显示窗口
  16. spw.showAtLocation(mLayoutRoot, Gravity.BOTTOM, 0, 0);

七、Android11权限申请

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

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/821896
推荐阅读
相关标签
  

闽ICP备14008679号