android 实现微信分享

微信分享有2种方式:

  1. 集成微信分享SDK实现分享功能
  2. 调用系统原生的分享实现分享功能

集成微信分享SDK实现分享功能

微信开放平台

需要先注册开发这账号

创建应用
android 实现微信分享_第1张图片

创建应用注意事项

  1. 应用官网:可以随便写个正确格式的url。
    应用官网
  2. 上传移动应用图片大小要符合要求。
    android 实现微信分享_第2张图片
  3. 应用签名。
    android 实现微信分享_第3张图片
    把带签名 的apk文件安装至手机中。安装微信的签名生成工具,打开GenSignature应用程序,填写你App的包名,点击“Get Signature”即可得到签名。

点击下载 签名生成工具

android 实现微信分享_第4张图片

android 实现微信分享_第5张图片

Android接入指南

官方文档

1.申请你的 AppID

请到 开发者应用登记页面 进行登记,登记并选择移动应用进行设置后,将该应用提交审核,只有审核通过的应用才能进行开发。

2. 添加依赖

在app模块的build.gradle文件中

dependencies {
    api 'com.tencent.mm.opensdk:wechat-sdk-android-without-mta:+'
}

(从5.4.3版本开始,wechat-sdk-android-with-mta不再维护)

3.搭建开发环境

Android Studio 环境下:

在 Android Studio 中新建你的工程,并保证网络设置可以成功从 jcenter 下载微信 SDK 即可。

4. 添加权限

添加必要的权限支持(其中网络权限如果没有使用扫码登录功能非必要;后三个权限,如果没有使用 mta,也非必要,即使有使用 mta,去掉也不影响功能):

<uses-permission android:name="android.permission.INTERNET" />

<!-- for mta statistics, not necessary-->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

5. 注册到微信

要使你的程序启动后微信终端能响应你的程序,必须在代码中向微信终端注册你的 id。(可以在程序入口 Activity 的 onCreate 回调函数处,或其他合适的地方将你的应用 id 注册到微信。

public class ShareApplication extends Application {

    private static final String APP_ID = "wx88888888";

    // IWXAPI 是第三方app和微信通信的openApi接口
    private IWXAPI api;

    @Override
    public void onCreate() {
        super.onCreate();

        // 通过WXAPIFactory工厂,获取IWXAPI的实例
        // 三个参数分别是上下文、应用的appId、是否检查签名(默认为false)
        api = WXAPIFactory.createWXAPI(this, APP_ID, true);

        // 将应用的appId注册到微信
        api.registerApp(APP_ID);


        //建议动态监听微信启动广播进行注册到微信
       /* registerReceiver(new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {

                // 将该app注册到微信
                api.registerApp(APP_ID);
            }
        }, new IntentFilter(ConstantsAPI.ACTION_REFRESH_WXAPP));*/
    }
}

混淆代码

如果需要混淆代码,为了保证 sdk 的正常使用,需要在 proguard.cfg 加上下面两行配置:

-keep class com.tencent.mm.opensdk.** {
    *;
}

-keep class com.tencent.wxop.** {
    *;
}

-keep class com.tencent.mm.sdk.** {
    *;
}

获取分享到微信的回调

如果你的程序需要接收微信发送的请求,或者接收发送到微信请求的响应结果,需要下面 操作:

在你的包名相应目录下新建一个 wxapi 目录,并在该 wxapi 目录下新增一个 WXEntryActivity 类,该类继承自 Activity
android 实现微信分享_第6张图片
并在 manifest 文件里面加上 exported 属性,设置为 true,例如:


        
        <activity
            android:name=".wxapi.WXEntryActivity"
            android:exported="true"
            android:launchMode="singleTop"
            android:theme="@android:style/Theme.Translucent.NoTitleBar">activity>

WXEntryActivity

实现 IWXAPIEventHandler 接口,微信发送的请求将回调到 onReq 方法,发送到微信请求的响应结果将回调到 onResp 方法。

在 WXEntryActivity 中将接收到的 intent 及实现了 IWXAPIEventHandler 接口的对象传递给 IWXAPI 接口的 handleIntent 方法。

当微信发送请求到你的应用,将通过 IWXAPIEventHandler 接口的 onReq 方法进行回调,类似的,应用请求微信的响应结果将通过 onResp 回调。

/**
 * Cerated by xiaoyehai
 * Create date : 2019/11/15 17:31
 * description : 分享到微信和微信朋友圈的回调
 * 

* SendMessageToWX.Req.WXSceneSession(0):是分享到好友会话 * SendMessageToWX.Req.WXSceneTimeline(1):是分享到朋友圈 * 微信 4.2 以上版本支持才支持分享到朋友圈 */ public class WXEntryActivity extends AppCompatActivity implements IWXAPIEventHandler { //IWXAPI 是第三方app和微信通信的openApi接口 private IWXAPI iwxapi; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // setContentView(R.layout.activity_test); //如果没回调onResp,八成是这句没有写 iwxapi = WXAPIFactory.createWXAPI(this, Constants.WX_APP_ID, false); iwxapi.handleIntent(getIntent(), this); } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); setIntent(intent); iwxapi.handleIntent(intent, this); } /** * 微信发送的请求将回调到 onReq 方法 * * @param baseReq */ @Override public void onReq(BaseReq baseReq) { } /** * 发送到微信请求的响应结果将回调到 onResp 方法 * * @param resp */ @Override public void onResp(BaseResp resp) { String result; switch (resp.errCode) { case BaseResp.ErrCode.ERR_OK: result = "分享成功"; break; case BaseResp.ErrCode.ERR_USER_CANCEL: result = "取消分享"; break; case BaseResp.ErrCode.ERR_AUTH_DENIED: result = "分享被拒绝"; break; default: result = "发送返回"; break; } Toast.makeText(this, result, Toast.LENGTH_SHORT).show(); finish(); } }

WxShareHelper:封装分享功能

该类只封装了一些简单的分享功能,如果需要分享其他类型的数据,请参考官方文档

/**
 * Cerated by xiaoyehai
 * Create date : 2019/12/4 22:06
 * description :微信分享帮助类
 * 

* 分享到对话:SendMessageToWX.Req.WXSceneSession * 分享到朋友圈:SendMessageToWX.Req.WXSceneTimeline */ public class WxShareHelper { //分享到微信 public static final int WX_SCENE = SendMessageToWX.Req.WXSceneSession; //分享到朋友圈 public static final int TIMELINE_SCENE = SendMessageToWX.Req.WXSceneSession; private static WxShareHelper mInstance = new WxShareHelper(); private WxShareHelper() { } public static WxShareHelper getInstnce() { return mInstance; } /** * 判断是否安装微信 * * @param context */ private void checkInstallWx(Context context) { IWXAPI wxapi = WXAPIFactory.createWXAPI(context, Constants.WX_APP_ID); if (!wxapi.isWXAppInstalled()) { Toast.makeText(context, "对不起,您没有安装微信", Toast.LENGTH_SHORT).show(); return; } } /** * 分享文本到微信 * * @param context * @param scene */ public void shareTextToWX(Context context, int scene) { checkInstallWx(context); // 通过appId得到IWXAPI这个对象 IWXAPI wxapi = WXAPIFactory.createWXAPI(context, Constants.WX_APP_ID); //初始化一个 WXTextObject 对象,填写分享的文本内容 WXTextObject textObj = new WXTextObject(); textObj.text = "我是分享到微信的数据"; //用 WXTextObject 对象初始化一个 WXMediaMessage 对象 WXMediaMessage msg = new WXMediaMessage(); msg.mediaObject = textObj; msg.description = "描述"; SendMessageToWX.Req req = new SendMessageToWX.Req(); //req.transaction = String.valueOf(System.currentTimeMillis()); //transaction字段用与唯一标示一个请求 req.transaction = buildTransaction("text"); req.message = msg; req.scene = scene; //调用api接口,发送数据到微信 wxapi.sendReq(req); } /** * 分享网页类型至微信 * * @param context 上下文 * @param scene */ public void shareWebToWX(Context context, int scene) { checkInstallWx(context); IWXAPI wxapi = WXAPIFactory.createWXAPI(context, Constants.WX_APP_ID); // 初始化一个WXWebpageObject对象 WXWebpageObject webpageObject = new WXWebpageObject(); // 填写网页的url webpageObject.webpageUrl = "https://www.baidu.com/"; // 用WXWebpageObject对象初始化一个WXMediaMessage对象 WXMediaMessage msg = new WXMediaMessage(webpageObject); // 填写网页标题、描述、位图 msg.title = "网页标题"; msg.description = "网页描述"; //这块需要注意,图片的像素千万不要太大,不然的话会调不起来微信分享 Bitmap thumbBmp = BitmapFactory.decodeResource(context.getResources(), R.drawable.login_logo); // 如果没有位图,可以传null,会显示默认的图片 msg.setThumbImage(thumbBmp); // 构造一个Req SendMessageToWX.Req req = new SendMessageToWX.Req(); // transaction用于唯一标识一个请求(可自定义) req.transaction = buildTransaction("webpage"); // 上文的WXMediaMessage对象 req.message = msg; req.scene = scene; //req.userOpenId = getOpenId(); // 向微信发送请求 wxapi.sendReq(req); } /** * 分享图片到微信,朋友圈 * * @param context * @param scene */ public void shareBitmapToWX(Context context, int scene) { checkInstallWx(context); // 通过appId得到IWXAPI这个对象 IWXAPI wxapi = WXAPIFactory.createWXAPI(context, Constants.WX_APP_ID); Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.login_logo); //初始化 WXImageObject 和 WXMediaMessage 对象 WXImageObject imgObj = new WXImageObject(bitmap); WXMediaMessage msg = new WXMediaMessage(); msg.mediaObject = imgObj; //设置缩略图 Bitmap thumbBmp = Bitmap.createScaledBitmap(bitmap, 100, 100, true); bitmap.recycle(); msg.thumbData = bmpToByteArray(thumbBmp, true); //构造一个Req SendMessageToWX.Req req = new SendMessageToWX.Req(); req.transaction = buildTransaction("img"); req.message = msg; req.scene = scene; //req.userOpenId = getOpenId(); //调用api接口,发送数据到微信 wxapi.sendReq(req); } /** * 用于解析图片 * 分享的图片大小不能大于32KB, * * @param bmp * @param needRecycle * @return */ public byte[] bmpToByteArray(final Bitmap bmp, final boolean needRecycle) { ByteArrayOutputStream output = new ByteArrayOutputStream(); bmp.compress(Bitmap.CompressFormat.PNG, 100, output); if (needRecycle) { bmp.recycle(); } byte[] result = output.toByteArray(); try { output.close(); } catch (Exception e) { e.printStackTrace(); } return result; } /** * 生成transaction * * @param type * @return */ private String buildTransaction(final String type) { return (type == null) ? String.valueOf(System.currentTimeMillis()) : type + System.currentTimeMillis(); } }

使用

//分享文本
WxShareHelper.getInstnce().shareTextToWX(mContext,WxShareHelper.WX_SCENE);
  
// 分享网页    
WxShareHelper.getInstnce().shareWebToWX(mContext,WxShareHelper.WX_SCENE);
  //分享图片 
WxShareHelper.getInstnce().shareBitmapToWX(mContext,WxShareHelper.WX_SCENE);

Android调用系统原生的分享实现分享功能

备注:
①.这个不用导入微信的jar和注册微信的APP_ID 。
②. 实际上分享时是调用系统本地的分享功能,所以分享的图片必须要保存到本地。
③. 保存到本地是耗时操作 分享的代码需要在子线程执行 。

分享多张图片

微信平台没有提供分享多张的SDK,我们只能自己调用系统自带的分享功能实现。

在ShareHelper种加入下面代码:

 private static final String WX_PACKAGE_NAME = "com.tencent.mm"; //微信包名
    private static final String SHARE_IMG_UI = "com.tencent.mm.ui.tools.ShareImgUI"; //分享到微信好友
    private static final String SHARE_TO_TIMELINE_UI = "com.tencent.mm.ui.tools.ShareToTimeLineUI"; //分享到微信朋友圈

    /**
     * 微信7.0版本号,兼容处理微信7.0版本分享到朋友圈不支持多图片的问题
     */
    private static final int VERSION_CODE_FOR_WEI_XIN_VER7 = 1380;

    /**
     * Android调用系统分享的实现;分享单张图片到微信
     *
     * @param context
     * @param imageFile
     */
    public void shareSingleImageToWX(Context context, File imageFile) {

        //判断是否安装微信,如果没有安装微信 又没有判断就直达微信分享是会挂掉的
        if (!Tools.isWeixinAvilible(mContext)) {
            Toast.makeText(context, "您还没有安装微信", Toast.LENGTH_SHORT).show();
            return;
        }

        Intent intent = new Intent();
        //发送图片给好友
        ComponentName componentName = new ComponentName(WX_PACKAGE_NAME, SHARE_IMG_UI);
        intent.setComponent(componentName);
        intent.setAction(Intent.ACTION_SEND);
        intent.setType("image/*");
        intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(imageFile));
        context.startActivity(intent);
    }


    /**
     * Android调用系统分享的实现:分享多张图片到微信,分享单张图片也可以用该方法
     * 

* 昨天公司老大通知客户改需求了,原来的微信分享改成分享多张图片,然后屁颠屁颠跑到微信平台看了以后 * 心里千万只草泥马狂奔而过,微信平台没有提供分享多张的SDK有木有啊,我们只能自己调用系统自带的分享功能实现。 *

* 实际分享的时候因为是调用系统本地的分享功能,所以分享的图片也就必须要存到本地,不然就会提示获取资源失败,那就要把图片存到本地了 * 这个是直接调用微信的分享,所以调起分享的时候一定要判断手机里面是否已经安装了微信,如果没有安装还要掉微信分享就是直接崩溃掉。 * * @param context * @param imageFileList 保存到本地的图片 */ public void shareMultiImageToWX(Context context, List<File> imageFileList) { //判断是否安装微信,如果没有安装微信 又没有判断就直达微信分享是会挂掉的 if (!Tools.isWeixinAvilible(mContext)) { Toast.makeText(context, "您还没有安装微信", Toast.LENGTH_SHORT).show(); return; } ArrayList<Uri> imageUris = new ArrayList<>(); for (File file : imageFileList) { imageUris.add(Uri.fromFile(file)); } if (imageUris.size() == 0) { ToastUtil.showShortToast("获取图片失败"); return; } Intent intent = new Intent(); ComponentName componentName = new ComponentName(WX_PACKAGE_NAME, SHARE_IMG_UI); intent.setComponent(componentName); intent.setAction(Intent.ACTION_SEND_MULTIPLE); intent.setType("image/*"); intent.putExtra(Intent.EXTRA_STREAM, imageUris); context.startActivity(intent); } /** * Android调用系统分享的实现 * 分享多张图片到朋友圈:微信7.0及以上版本,朋友圈只支持单张图片分享 * * @param context * @param imageFileList */ public void shareMultiImageToWXTimeLine(Context context, List<File> imageFileList) { //判断是否安装微信,如果没有安装微信 又没有判断就直达微信分享是会挂掉的 if (!Tools.isWeixinAvilible(mContext)) { Toast.makeText(context, "您还没有安装微信", Toast.LENGTH_SHORT).show(); return; } ArrayList<Uri> imageUris = new ArrayList<>(); for (File file : imageFileList) { imageUris.add(Uri.fromFile(file)); } if (imageUris.size() == 0) { ToastUtil.showShortToast("获取图片失败"); return; } Intent intent = new Intent(); if (getVersionCode(context, WX_PACKAGE_NAME) < VERSION_CODE_FOR_WEI_XIN_VER7) { // 微信7.0以下版本 intent.setAction(Intent.ACTION_SEND_MULTIPLE); intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, imageUris); } else { // 微信7.0及以上版本,朋友圈只支持单张图片分享 intent.setAction(Intent.ACTION_SEND); intent.putExtra(Intent.EXTRA_STREAM, imageUris.get(0)); } ComponentName componentName = new ComponentName(WX_PACKAGE_NAME, SHARE_TO_TIMELINE_UI); intent.setComponent(componentName); intent.setType("image/*"); // intent.putExtra("kdescription", "分享描述"); //分享描述 context.startActivity(intent); } /** * 获取制定包名应用的版本的versionCode * * @param context * @param * @return */ public static int getVersionCode(Context context, String packageName) { try { PackageManager manager = context.getPackageManager(); PackageInfo info = manager.getPackageInfo(packageName, 0); int version = info.versionCode; return version; } catch (Exception e) { e.printStackTrace(); return 0; } }

ShareFragment

public class ShareFragment extends BaseFragment {

    private List<String> urlList = new ArrayList<>();

    @Override
    protected int getLayoutId() {
        return R.layout.fragment_share;
    }

    @Override
    protected void init() {
        urlList.add("https://img.alicdn.com/imgextra/i1/650413329/O1CN01SLxEmg1aSj43VIlHm_!!650413329.jpg");
        urlList.add("https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=2973069531,657782944&fm=26&gp=0.jpg");
        urlList.add("http://img.alicdn.com/imgextra/i2/2206462034816/O1CN01mZogLE1lRm0njgsRT_!!2206462034816.jpg");


    }

    @OnClick(R.id.btn_share)
    public void onViewClicked() {
        new ShareDialog(getActivity()).setOnItemClickListener(new ShareDialog.OnBottomDialogItemClickListener() {
            @Override
            public void onClick(Dialog dialog, int position) {
                switch (position) {
                    case 0: //微信
                        shareToWX();
                        break;
                    case 1: //朋友圈
                        shareToTimeLine();
                        break;
                    case 2: //qq
                        shareToQQ();
                        break;
                    case 3: //qq空间
                        shareToQQZone();
                        break;
                }
            }
        }).show();
    }

    private void shareToWX() {
        showLoading();
        DonwloadSaveImage.getImageList(urlList, new DonwloadSaveImage.OnImageFileListCallback() {
            @Override
            public void onimageFileList(ArrayList<File> imageFileList) {
                hideLoading();
                WxShareHelper.getInstnce().shareMultiImageToWX(mContext, imageFileList);
            }
        });
    }

    private void shareToTimeLine() {
        showLoading();
        DonwloadSaveImage.getImageList(urlList, new DonwloadSaveImage.OnImageFileListCallback() {
            @Override
            public void onimageFileList(ArrayList<File> imageFileList) {
                hideLoading();
                ShareHelper.getInstnce().shareMultiImageToWXTimeLine(mContext, imageFileList);
            }
        });
    }

    private void shareToQQ() {
    }

    private void shareToQQZone() {
    }


}

DonwloadSaveImage:下载和保存图片

/**
 * Cerated by xiaoyehai
 * Create date : 2019/12/4 17:57
 * description : 下载图片并且保存到本地
 */
public class DonwloadSaveImage {

    //线程池
    private static ExecutorService executor;
    private static Handler mHandler;

    private static String imageDirPath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "tjz";

    static {
        executor = Executors.newFixedThreadPool(5);
        mHandler = new Handler();
    }

    public static void getImageList(List<String> urlList, OnImageFileListCallback callback) {
        executor.execute(new Runnable() {
            @Override
            public void run() {
                deleteFile();
                ArrayList<File> localUrls = new ArrayList<>();
                for (String url : urlList) {
                    localUrls.add(downloadImage(url));
                }
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        callback.onimageFileList(localUrls);
                    }
                });
            }
        });
    }

      /* Glide.with(getActivity()) // could be an issue!
                        .load(shareimgUrl)
                        .asBitmap()   //强制转换Bitmap
                        .into(new SimpleTarget() {
                            @Override
                            public void onResourceReady(Bitmap resource, GlideAnimation glideAnimation) {
                                // //这里我们拿到回掉回来的bitmap,可以加载到我们想使用到的地方
                                hideLoading();
                                ShareUtils.shareImage(mContext, resource, wxSceneSession);
                            }

                            @Override
                            public void onLoadFailed(Exception e, Drawable errorDrawable) {
                                super.onLoadFailed(e, errorDrawable);
                                hideLoading();
                                ToastUtil.showShortToast("加载图片失败");
                            }
                        });*/


    /**
     * 下载图片
     *
     * @param url
     * @return
     */
    private static File downloadImage(String url) {
        File file = null;
        try {
            URL imageurl = new URL(url);
            HttpURLConnection conn = (HttpURLConnection) imageurl.openConnection();
            conn.setDoInput(true);
            conn.connect();
            InputStream is = conn.getInputStream();
            Bitmap bitmap = BitmapFactory.decodeStream(is);
            is.close();
            file = saveBitmap(bitmap);

        } catch (IOException e) {
            e.printStackTrace();
        }
        return file;
    }

    /**
     * 保存图片到本地
     *
     * @param bitmap
     * @return
     */
    private static File saveBitmap(Bitmap bitmap) {
        File appDir = new File(imageDirPath);
        if (!appDir.exists()) {
            appDir.mkdir();
        }
        String fileName = System.currentTimeMillis() + ".jpg";
        File file = new File(appDir, fileName);
        try {
            FileOutputStream fos = new FileOutputStream(file);
            //通过io流的方式来压缩保存图片
            bitmap.compress(Bitmap.CompressFormat.JPEG, 60, fos);
            fos.flush();
            fos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new File(imageDirPath, fileName);
    }

    private static void deleteFile() {
        File dir = new File(imageDirPath);
        if (dir.exists()) {
            File[] files = dir.listFiles();
            if (files != null) {
                for (File file : files) {
                    file.delete();
                }
            }
        }
    }

    public interface OnImageFileListCallback {
        void onimageFileList(ArrayList<File> imageFileList);
    }
}

注意问题:

实际分享的时候因为是调用系统本地的分享功能,所以分享的图片也就必须要存到本地,不然就会提示获取资源失败,只支持分享到朋友圈等等的问题。

因为考虑到如果存的图片太多就太占内存了,所以最多设置分享9张。

这个是直接调用微信的分享,所以调起分享的时候一定要判断手机里面是否已经安装了微信,如果没有安装还要掉微信分享就是直接崩溃掉。

android N系统以后分享的链接用file://…的时候会出现一个异常android.os.FileUriExposedException。网上虽然很多朋友都给出了用 v4包中的FileProvider来解决,但是不知道为什么,反正我的项目导入后就报错了,最后在网上找了另一个方法在项目的BaseApplication的onCreate中用VmPolicy的方法解决。

/解决android N(>=24)系统以上分享 路径为file://时的 android.os.FileUriExposedException异常
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
    StrictMode.setVmPolicy(builder.build());
}

你可能感兴趣的:(android)