Android原生態(tài)實現(xiàn)分享轉(zhuǎn)發(fā)功能實例
導(dǎo)讀:
之前剛學(xué)安卓時,寫過一篇“Android調(diào)用系統(tǒng)shareAPI實現(xiàn)分享轉(zhuǎn)發(fā)功能”的文章,隨著安卓版本的迭代更新以及其他APP的優(yōu)化,安卓的這個shareAPI好像失效了,不怎么好使,已經(jīng)獲取不到有分享功能的APP列表,點擊分享也會直接崩潰。并不是說我之前那篇文章的代碼有錯,只能說是時代有了變化,舊的方法已經(jīng)不能滿足新的需求
?最近開發(fā)一個收款A(yù)PP,想把分享功能加入進去,然后發(fā)現(xiàn)舊的方法已經(jīng)不行,這就難過了,網(wǎng)上一些大佬建議用第三方APP自帶的分享SDK,但是我覺得用第三方的SDK太麻煩了,每個 APP都要申請接口賬號和接口密鑰,即便是使用其他人封裝好的分享框架,也是需要去申請賬號密鑰的,一點也不方便,還是喜歡安卓原生態(tài)寫法,簡單便捷、一勞永逸。
經(jīng)過我?guī)追芯?,最終完美實現(xiàn)了,效果圖如下:

?一、xml布局文件
1、res/layout目錄下創(chuàng)建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目錄下創(chuàng)建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?中,添加以下代碼,用來實現(xiàn)彈出窗背景效果:
<style name="circleDialog" parent="android:style/Theme.Dialog">
<!-- 背景透明,設(shè)置圓角對話框必須設(shè)置背景透明,否則四角會有背景色小塊-->
<item name="android:windowBackground">@android:color/transparent</item>
<!-- 沒有標(biāo)題 -->
<item name="android:windowNoTitle">true</item>
<!-- 背景模糊 -->
<item name="android:backgroundDimEnabled">true</item>
</style>
二、創(chuàng)建一個實體類?AppInfo.java,用來保存應(yīng)用信息
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;
}
/**
* 構(gòu)造函數(shù)
* @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);
//獲取所有的非系統(tǒng)應(yīng)用
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);
//我這里分享的是圖片,如果你要分享鏈接和文本,可以在這里自行發(fā)揮
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();
}
});
//設(shè)置SelectPicPopupWindow的View
this.setContentView(mMenuView);
//設(shè)置SelectPicPopupWindow彈出窗體的寬
this.setWidth(LayoutParams.FILL_PARENT);
//設(shè)置SelectPicPopupWindow彈出窗體的高
this.setHeight(LayoutParams.WRAP_CONTENT);
//設(shè)置SelectPicPopupWindow彈出窗體可點擊
this.setFocusable(true);
//設(shè)置窗口外也能點擊(點擊外面時,窗口可以關(guān)閉)
this.setOutsideTouchable(true);
//設(shè)置SelectPicPopupWindow彈出窗體動畫效果
this.setAnimationStyle(R.style.circleDialog);
//實例化一個ColorDrawable顏色為半透明
ColorDrawable dw = new ColorDrawable(0x00000000);
//設(shè)置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);
}
/**
* 根據(jù)手機的分辨率從 dp 的單位 轉(zhuǎn)成為 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>標(biāo)簽內(nèi)添加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標(biāo)簽同級?

?2、在res/xml目錄添加filepaths.xml,代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<!--
1、name對應(yīng)的屬性值,開發(fā)者可以自由定義;
2、path對應(yīng)的屬性值,當(dāng)前external-path標(biāo)簽下的相對路徑
-->
<!--1、對應(yīng)內(nèi)部內(nèi)存卡根目錄:Context.getFileDir()-->
<files-path
name="int_root"
path="/" />
<!--2、對應(yīng)應(yīng)用默認(rèn)緩存根目錄:Context.getCacheDir()-->
<cache-path
name="app_cache"
path="/" />
<!--3、對應(yīng)外部內(nèi)存卡根目錄:Environment.getExternalStorageDirectory()-->
<external-path
name="ext_root"
path="Documents/" />
<!--4、對應(yīng)外部內(nèi)存卡根目錄下的APP公共目錄:Context.getExternalFileDir(Environment.DIRECTORY_PICTURES)-->
<external-files-path
name="ext_pub"
path="/" />
<!--5、對應(yīng)外部內(nèi)存卡根目錄下的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 {
/**
* 查詢手機內(nèi)所有的應(yīng)用列表
* @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));
//如果非系統(tǒng)應(yīng)用,則添加至appList
if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
//排除當(dāng)前應(yīng)用(替換成你的應(yīng)用包名即可)
if(!packageInfo.packageName.equals("net.zy13.skhelper")) {
appList.add(tmpInfo);
}
}
}
return appList;
}
/**
* 保存圖片到緩存里
* @param bitmap
* @return
*/
public static String SaveTitmapToCache(Bitmap bitmap){
// 默認(rèn)保存在應(yīng)用緩存目錄里 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();
}
//設(shè)置控件的值
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的調(diào)用?
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);
到此這篇關(guān)于Android原生態(tài)實現(xiàn)分享轉(zhuǎn)發(fā)功能實例的文章就介紹到這了,更多相關(guān)Android分享轉(zhuǎn)發(fā)功能內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android實現(xiàn)短信驗證碼獲取自動填寫功能(詳細(xì)版)
這篇文章主要為大家詳細(xì)介紹了Android實現(xiàn)短信驗證碼獲取自動填寫功能,很實用的功能分享給大家,感興趣的小伙伴們可以參考一下2016-08-08
Android Studio升級到3.0 Terminal 中文顯示異常解決
本篇文章主要介紹了Android Studio升級到3.0 Terminal 中文顯示異常解決,非常具有實用價值,需要的朋友可以參考下2017-10-10
Android中利用SurfaceView制作抽獎轉(zhuǎn)盤的全流程攻略
這篇文章主要介紹了Android中利用SurfaceView制作抽獎轉(zhuǎn)盤的全流程,從圖案的繪制到轉(zhuǎn)盤的控制再到布局,真的非常全面,需要的朋友可以參考下2016-04-04
Android開發(fā)之Android.mk模板的實例詳解
這篇文章主要介紹了Android開發(fā)之Android.mk模板的實例詳解的相關(guān)資料,希望通過本文能幫助到大家,讓大家理解掌握這部分內(nèi)容,需要的朋友可以參考下2017-10-10
Android studio 實現(xiàn)手機掃描二維碼功能
這篇文章主要介紹了Android studio 實現(xiàn)手機掃描二維碼功能,需要的朋友可以參考下2019-10-10
Android?Activity通用懸浮可拖拽View封裝的思路詳解
這篇文章主要介紹了Android?Activity通用懸浮可拖拽View封裝,實現(xiàn)思路是通過封裝通用的基礎(chǔ)懸浮View,繼承通用View,本文通過實例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-07-07

