Android原生态实现分享转发功能实例
导读:
之前刚学安卓时,写过一篇“Android调用系统shareAPI实现分享转发功能”的文章,随着安卓版本的迭代更新以及其他APP的优化,安卓的这个shareAPI好像失效了,不怎么好使,已经获取不到有分享功能的APP列表,点击分享也会直接崩溃。并不是说我之前那篇文章的代码有错,只能说是时代有了变化,旧的方法已经不能满足新的需求
最近开发一个收款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" > <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>
二、创建一个实体类 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); //适配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); } }
四、使用provider
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>
五、写一个工具类
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)); //如果非系统应用,则添加至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(); } }
六、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; } @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); } } }
七、自定义分享窗口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);
到此这篇关于Android原生态实现分享转发功能实例的文章就介绍到这了,更多相关Android分享转发功能内容请搜索猪先飞以前的文章或继续浏览下面的相关文章希望大家以后多多支持猪先飞!
原文出处:https://blog.csdn.net/qq15577969/article/details/121745540
相关文章
- 今天小编在这里就来给Photoshop的这一款软件的使用者们来说下火龙变冰龙的制作教程,各位想知道具体的制作步骤的使用者们,那么下面就快来跟着小编一起看看制作教程吧。...2016-09-14
- 下面我们来看一篇关于Android子控件超出父控件的范围显示出来方法,希望这篇文章能够帮助到各位朋友,有碰到此问题的朋友可以进来看看哦。 <RelativeLayout xmlns:an...2016-10-02
Illustrator渐变网格工具绘制可爱的卡通小猪教程分享
今天小编在这里就来给Illustrator的这一款软件的使用者们来说一说渐变网格工具绘制可爱的卡通小猪的教程,各位想知道具体制作方法的使用者们,那么下面就快来跟着小编一...2016-09-14Android开发中findViewById()函数用法与简化
findViewById方法在android开发中是获取页面控件的值了,有没有发现我们一个页面控件多了会反复研究写findViewById呢,下面我们一起来看它的简化方法。 Android中Fin...2016-09-20- 不知不觉功夫熊猫这部电影已经出到3了,今天小编在这里要教大家的是用Photoshop制作功夫熊猫3的海报,各位想知道制作方法的,那么下面就来跟着小编一起看看吧。 给各...2016-09-14
- 如果我们的项目需要做来电及短信的功能,那么我们就得在Android模拟器开发这些功能,本来就来告诉我们如何在Android模拟器上模拟来电及来短信的功能。 在Android模拟...2016-09-20
- 夜神android模拟器如何设置代理呢?对于这个问题其实操作起来是非常的简单,下面小编来为各位详细介绍夜神android模拟器设置代理的方法,希望例子能够帮助到各位。 app...2016-09-20
- 为了增强android应用的用户体验,我们可以在一些Button按钮上自定义动态的设置一些样式,比如交互时改变字体、颜色、背景图等。 今天来看一个通过重写Button来动态实...2016-09-20
- 如果我们要在Android应用APP中加载html5页面,我们可以使用WebView,本文我们分享两个WebView加载html5页面实例应用。 实例一:WebView加载html5实现炫酷引导页面大多...2016-09-20
- 今天小编在这里就来给photoshop的这一款软件的使用者们来说一说日系小清新通透人像的调色教程,各位想知道具体的调色步骤的使用者们,那么下面就快来跟着小编一起看一看...2016-09-14
- 深入理解Android中View和ViewGroup从组成架构上看,似乎ViewGroup在View之上,View需要继承ViewGroup,但实际上不是这样的。View是基类,ViewGroup是它的子类。本教程我们深...2016-09-20
- 下面我们来看一篇关于Android自定义WebView网络视频播放控件开发例子,这个文章写得非常的不错下面给各位共享一下吧。 因为业务需要,以下代码均以Youtube网站在线视...2016-10-02
- java开发的Android应用,性能一直是一个大问题,,或许是Java语言本身比较消耗内存。本文我们来谈谈Android 性能优化之MemoryFile文件读写。 Android匿名共享内存对外A...2016-09-20
- TextView默认是横着显示了,今天我们一起来看看Android设置TextView竖着显示如何来实现吧,今天我们就一起来看看操作细节,具体的如下所示。 在开发Android程序的时候,...2016-10-02
android.os.BinderProxy cannot be cast to com解决办法
本文章来给大家介绍关于android.os.BinderProxy cannot be cast to com解决办法,希望此文章对各位有帮助呀。 Android在绑定服务的时候出现java.lang.ClassCastExc...2016-09-20- 下面来给大家分享两个关于php威盾解密的例子,一个是批量解密一个是超级算法的解密都非常的好,大家有举的进入参考。 例子,批量解密 代码如下 复制代码 ...2016-11-25
- mysqli封装了诸如事务等一些高级操作,同时封装了DB操作过程中的很多可用的方法。应用比较多的地方是 mysqli的事务。...2013-10-02
- 这篇文章主要介绍了Android 实现钉钉自动打卡功能的步骤,帮助大家更好的理解和学习使用Android,感兴趣的朋友可以了解下...2021-03-15
- 下面我们来看一篇关于Android 开发之布局细节对比:RTL模式 ,希望这篇文章对各位同学会带来帮助,具体的细节如下介绍。 前言 讲真,好久没写博客了,2016都过了一半了,赶紧...2016-10-02
- 核心代码: 复制代码 代码如下:<!--?php$html2RTFCom = new COM("HTML2RTF.Converter");$html2RTFCom--->PreserveImages = true;$html2RTFCom->PageNumbers = 1;$html2RTFCom->PageNumbersAlignH = 1;$html2RTFCom->Pa...2014-06-07