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分享轉發功能內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- GridView實現桌面圖標顯示案例
- Android 控件GridView使用案例講解
- Android ListView仿微信聊天界面
- Android Gridview佈局出現滾動條或組件沖突解決方法
- Android入門之實現自定義可復用的BaseAdapter