微信分享那些事

  1. https://open.weixin.qq.com/上注册微信开放平台账号
  2. 创建应用
    a. 创建应用的第二步填写平台信息. 这一步比较关键, 应用签名和应用报名一定不要填错, 否则就分享不了了, 如图:
    填写平台信息

    b. 关于怎么获取签名, 微信开放平台上有教程, 这里直接引用过来了:

Signature的生成方法
这里以windows平台的cygwin环境和命令行环境为例,且默认开发者已经安装了jdk,能够正常使用keytool

cygwin环境下
在cygwin环境下运行如下命令,输出结果即为signature
keytool -exportcert -alias [alias] -keypass [alias password] -keystore [keystore file path] -storepass [keystore password] | md5sum

例如:当前路径下包含用于对app签名的test.keystore文件,且keystore密码为123456,别名为openapi,别名密码为654321,则运行如下命令:
keytool -exportcert -alias openapi -keypass 654321 -keystore ./test.keystore -storepass 123456 | md5sum
输出结果为:8f88de9693d22430ad7ce55047ec7946

命令行环境下
由于命令行下系统没有提供默认的md5sum,建议开发者自行选择合适的md5生成工具http://sourceforge.net/directory/os:windows/freshness:recently-updated/?q=md5,生成方法跟cygwin环境下类似,可以先将keytool的输出重定向到文件,然后再用md5生成工具对该文件进行md5处理,获得signature,结果跟cygwin环境下相同。
keytool -exportcert -alias openapi -keypass 654321 -keystore ./test.keystore -storepass 123456 > out.txt

  1. 将SDK(libammsdk.jar)拷贝到libs目录下
  2. 添加权限
    在AndroidManifest.xml文件中添加SDK所需要的权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
  1. 初始化API
    在Activity的onCreate( )方法中 或者 在 自定义的Application中初始化API
private IWXAPI api;
public void init(Context appContext) {
      api = WXAPIFactory.createWXAPI(appContext, APP_ID, true);
      api.registerApp(APP_ID);
}

IWXAPI是微信分享的接口, 所有操作都通过它来执行, APP_ID是在微信开放平台上创建应用后生成的应用ID, IWXAPI的定义如下:

public interface IWXAPI {
    boolean registerApp(String var1);
    void unregisterApp();
    boolean handleIntent(Intent var1, IWXAPIEventHandler var2);
    boolean isWXAppInstalled();
    boolean isWXAppSupportAPI();
    int getWXAppSupportAPI();
    boolean openWXApp();
    boolean sendReq(BaseReq var1);
    boolean sendResp(BaseResp var1);
    void detach();
}

其doc文档如下:


IWXAPI方法说明
  1. 分享
    分享主要通过 IWXAPI 的两个方法:
boolean sendReq(BaseReq var1);
boolean sendResp(BaseResp var1);

关于各种分享, 如图片/文字/网页...., 微信开放平台中的文档也说的十分清晰, 这里直接引用如下:

分享与收藏功能开发文档(Android应用)

微信分享及收藏是指第三方App通过接入该功能,让用户可以从App分享文字、图片、音乐、视频、网页至微信好友会话、朋友圈或添加到微信收藏。
微信分享及收藏功能已向全体开发者开放,开发者在微信开放平台帐号下申请App并通过审核后,即可获得微信分享及收藏权限。
微信分享及收藏目前支持文字、图片、音乐、视频、网页共五种类型。开发者在App中在集成微信SDK后,可调用接口实现,以下依次是文字分享、图片分享、音乐分享、视频分享、网站分享的示例。
分享或收藏的目标场景,通过修改scene场景值实现。
发送到聊天界面——WXSceneSession
发送到朋友圈——WXSceneTimeline
添加到微信收藏——WXSceneFavorite

一、文字类型分享示例

二、图片类型分享示例

三、音乐类型分享示例


注意:分享至微信的音乐,直接点击好友会话或朋友圈下的分享内容会跳转至第三方 APP,点击会话列表顶部的音乐分享内容将跳转至微信原生音乐播放器播放。

四、视频类型分享示例

五、网页类型分享示例

  1. 发送请求 或 响应微信

[2] 发送请求或响应到微信
现在,你的程序要发送请求或发送响应到微信终端,可以通过IWXAPI的 sendReq 和 sendResp 两个方法来实现。
boolean sendReq(BaseReq req);

sendReq是第三方app主动发送消息给微信,发送完成之后会切回到第三方app界面。
boolean sendResp(BaseResp resp);

sendResp是微信向第三方app请求数据,第三方app回应数据之后会切回到微信界面。
sendReq的实现示例,如下图所示:



需要注意的是,SendMessageToWX.Req的scene成员,如果scene填WXSceneSession,那么消息会发送至微信的会话内。如果scene填WXSceneTimeline(微信4.2以上支持,如果需要检查微信版本支持API的情况, 可调用IWXAPI的getWXAppSupportAPI方法,0x21020001及以上支持发送朋友圈),那么消息会发送至朋友圈。scene默认值为WXSceneSession。
sendResp的实现与SendReq类似,如下图所示:



具体要发送的内容由第三方app开发者定义,具体可参考微信开发工具包中的SDK Sample Demo源码。
[3] 接收微信的请求及返回值
如果你的程序需要接收微信发送的请求,或者接收发送到微信请求的响应结果,需要下面3步操作:

a. 在你的包名相应目录下新建一个wxapi目录,并在该wxapi目录下新增一个WXEntryActivity类,该类继承自Activity(例如应用程序的包名为net.sourceforge.simcpux,则新添加的类如下图所示)



并在manifest文件里面加上exported属性,设置为true,例如:

b. 实现IWXAPIEventHandler接口,微信发送的请求将回调到onReq方法,发送到微信请求的响应结果将回调到onResp方法
c. 在WXEntryActivity中将接收到的intent及实现了IWXAPIEventHandler接口的对象传递给IWXAPI接口的handleIntent方法,示例如下图:

当微信发送请求到你的应用,将通过IWXAPIEventHandler接口的onReq方法进行回调,类似的,应用请求微信的响应结果将通过onResp回调。
  1. 混淆
    为了保证sdk的正常使用, 在混淆规则文件中添加如下语句:
-keep class com.tencent.mm.sdk.** {
     *;
}
  1. 我们可以将分享的api进行封装一下, 下面是我封装的一个分享工具类:
package com.stone.wx.share.wx;

import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.Log;

import com.tencent.mm.sdk.modelbase.BaseReq;
import com.tencent.mm.sdk.modelmsg.SendMessageToWX;
import com.tencent.mm.sdk.modelmsg.WXFileObject;
import com.tencent.mm.sdk.modelmsg.WXImageObject;
import com.tencent.mm.sdk.modelmsg.WXMediaMessage;
import com.tencent.mm.sdk.modelmsg.WXMusicObject;
import com.tencent.mm.sdk.modelmsg.WXTextObject;
import com.tencent.mm.sdk.modelmsg.WXVideoObject;
import com.tencent.mm.sdk.modelmsg.WXWebpageObject;
import com.tencent.mm.sdk.openapi.IWXAPI;
import com.tencent.mm.sdk.openapi.IWXAPIEventHandler;
import com.tencent.mm.sdk.openapi.WXAPIFactory;

import rx.Observable;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;

/**
 * @author stone
 * @date 16/8/30
 */
public final class WXShareManager {

    private final String APP_ID = "wx8zq97f092818osua";
    private IWXAPI api;
    private ShareResultListener listener;

    private final String TRANSACTION_TEXT = "text";
    private final String TRANSACTION_IMAGE = "image";
    private final String TRANSACTION_WEBPAGE = "webpage";
    private final String TRANSACTION_MUSIC = "music";
    private final String TRANSACTION_VIDEO = "video";
    private final String TRANSACTION_FILE = "file";

    private final int THUMBNAIL_SIZE = 150;

    //分享类型
    public enum ShareType {
        FRIENDS, FRIENDSCIRCLE, FAVOURITE
    }

    private WXShareManager() {
        //no instance
    }

    public static class InstanceHolder {
        private static WXShareManager INSTANCE = new WXShareManager();
    }

    public static WXShareManager get() {
        return InstanceHolder.INSTANCE;
    }

    /**
     * 初始化微信API 推荐在自定义的Application的onCreate方法中调用
     * @param appContext
     */
    public void init(Context appContext) {
        api = WXAPIFactory.createWXAPI(appContext, APP_ID, true);
        api.registerApp(APP_ID);
    }

    /**
     * @param shareText
     * @param title
     * @param description
     * @param type
     * @param listener
     * @return
     */
    public boolean shareText(@NonNull String shareText, @NonNull String title, @NonNull String description,
                             @NonNull ShareType type, @Nullable ShareResultListener listener) {
        this.listener = listener;
        WXTextObject obj = new WXTextObject(shareText);
        WXMediaMessage msg = buildMediaMesage(obj, title, description);
        BaseReq req = buildSendReq(msg, buildTransaction(TRANSACTION_TEXT), getWxShareType(type));
        return api.sendReq(req);
    }

    public boolean shareImage(@NonNull Bitmap bitmap, @NonNull String title, @NonNull String description,
                              @NonNull ShareType type, @Nullable ShareResultListener listener) {
        this.listener = listener;

        WXMediaMessage.IMediaObject obj = new WXImageObject(bitmap);
        WXMediaMessage msg = buildMediaMesage(obj, title, description);
        msg.setThumbImage(bitmap);
        BaseReq req = buildSendReq(msg, buildTransaction(TRANSACTION_IMAGE), getWxShareType(type));
        return api.sendReq(req);
    }

    public boolean shareImage(@NonNull final String pathOrUrl, @NonNull Bitmap thumbnail, @NonNull String title, @NonNull String description,
                              @NonNull ShareType type, ShareResultListener listener) {
        this.listener = listener;

        //分享url图片
        if(pathOrUrl.contains("://")) {
//            obj.imageUrl = pathOrUrl; //不能编译???
            Observable.<byte[]>create(subscriber -> {
                subscriber.onNext(Util.getHtmlByteArray(pathOrUrl));
            }).subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(data -> {
                        shareImage(data, title, description, type, listener);
                    });
            return true;
        }

        //分享文件系统中的图片
        WXImageObject obj = new WXImageObject();
        obj.imagePath = pathOrUrl;
        WXMediaMessage msg = buildMediaMesage(obj, title, description);
        if(thumbnail != null) {
            msg.setThumbImage(thumbnail);
        } else {
            Bitmap thumbNail = getThumbnail(pathOrUrl, THUMBNAIL_SIZE);
            msg.setThumbImage(thumbNail);
            thumbNail.recycle();
        }
        BaseReq req = buildSendReq(msg, buildTransaction(TRANSACTION_IMAGE), getWxShareType(type));
        return api.sendReq(req);
    }

    public boolean shareImage(@NonNull byte[] imageData, @NonNull String title, @NonNull String description,
                              @NonNull ShareType type, @Nullable ShareResultListener listener) {
        this.listener = listener;

        WXMediaMessage.IMediaObject obj = new WXImageObject(imageData);
        WXMediaMessage msg = buildMediaMesage(obj, title, description);

        Bitmap thumbnail = getThumbnail(imageData, THUMBNAIL_SIZE);
        msg.setThumbImage(thumbnail);
        thumbnail.recycle();

        BaseReq req = buildSendReq(msg, buildTransaction(TRANSACTION_IMAGE), getWxShareType(type));
        return api.sendReq(req);
    }

    public boolean shareMusic(@NonNull String url, @NonNull String title, @NonNull String description,
                              @NonNull ShareType type, @Nullable ShareResultListener listener) {
        this.listener = listener;

        WXMusicObject obj = new WXMusicObject();
        obj.musicUrl = url;
        WXMediaMessage msg = buildMediaMesage(obj, title, description);
        BaseReq req = buildSendReq(msg, buildTransaction(TRANSACTION_MUSIC), getWxShareType(type));
        return api.sendReq(req);
    }

    public boolean shareVideo(@NonNull String url, @NonNull String title, @NonNull String description,
                              @NonNull ShareType type, @Nullable ShareResultListener listener) {
        this.listener = listener;

        WXVideoObject obj = new WXVideoObject();
        obj.videoUrl = url;
        WXMediaMessage msg = buildMediaMesage(obj, title, description);
        BaseReq req = buildSendReq(msg, buildTransaction(TRANSACTION_VIDEO), getWxShareType(type));
        return api.sendReq(req);
    }

    public boolean shareWebPage(@NonNull String weburl, @NonNull String title, @NonNull String description,
                                @NonNull ShareType type, @Nullable ShareResultListener listener) {
        this.listener = listener;

        WXWebpageObject obj = new WXWebpageObject(weburl);
        WXMediaMessage msg = buildMediaMesage(obj, title, description);
        BaseReq req = buildSendReq(msg, buildTransaction(TRANSACTION_WEBPAGE), getWxShareType(type));
        return api.sendReq(req);
    }

    public boolean shareFile(@NonNull String filepath, @NonNull String title, @NonNull String description,
                             @NonNull ShareType type, @Nullable ShareResultListener listener) {
        this.listener = listener;

        WXFileObject obj = new WXFileObject(filepath);
        WXMediaMessage msg = buildMediaMesage(obj, title, description);
        BaseReq req = buildSendReq(msg, buildTransaction(TRANSACTION_FILE), getWxShareType(type));
        return api.sendReq(req);
    }

    public void handleIntent(Intent intent, IWXAPIEventHandler handler) {
        api.handleIntent(intent, handler);
    }

    public boolean performShareResult(boolean result) {
        if(listener != null) {
            Log.e("_share_", "performShareResult: " + result);
            listener.onShareResult(result);
            listener = null;
            return true;
        }

        return false;
    }

    private int getWxShareType(ShareType type) {
        if(type == ShareType.FRIENDS) {
            return SendMessageToWX.Req.WXSceneSession;
        } else if(type == ShareType.FRIENDSCIRCLE) {
            return SendMessageToWX.Req.WXSceneTimeline;
        } else if(type == ShareType.FAVOURITE) {
            return SendMessageToWX.Req.WXSceneFavorite;
        }

        throw new IllegalArgumentException("非法参数: 不识别的ShareType -> " + type.name());
    }

    private Bitmap getThumbnail(@NonNull String path, int thumbnailSize) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(path, options);
        Log.e("_share_", "outWidth=" + options.outWidth + ", outHeight=" + options.outHeight);
        int sourceSize = Math.min(options.outWidth, options.outHeight);
        options.inJustDecodeBounds = false;
        options.inSampleSize = sourceSize / thumbnailSize;
        return BitmapFactory.decodeFile(path, options);
    }

    private Bitmap getThumbnail(@NonNull byte[] imageData, int thumbnailSize) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeByteArray(imageData, 0, imageData.length, options);
        options.inJustDecodeBounds = false;
        Log.e("_share_", "outWidth=" + options.outWidth + ", outHeight=" + options.outHeight);
        int sourceSize = Math.min(options.outWidth, options.outHeight);
        options.inSampleSize = sourceSize / thumbnailSize;
        return BitmapFactory.decodeByteArray(imageData, 0, imageData.length, options);
    }

    private BaseReq buildSendReq(WXMediaMessage msg, String transaction, int scene) {
        SendMessageToWX.Req req = new SendMessageToWX.Req();
        req.message = msg;
        req.transaction = transaction;
        req.scene = scene;
        return req;
    }

    private WXMediaMessage buildMediaMesage(WXMediaMessage.IMediaObject obj, String title, String description) {
        WXMediaMessage msg = new WXMediaMessage();
        msg.mediaObject = obj;
        msg.title = title;
        msg.description = description;
        return msg;
    }

    /**
     * @param type text/image/webpage/music/video
     * @return
     */
    private String buildTransaction(String type) {
        return TextUtils.isEmpty(type) ? String.valueOf(System.currentTimeMillis()) : (type + System.currentTimeMillis());
    }

    /**
     * 分享结果回调
     */
    public interface ShareResultListener {
        void onShareResult(boolean result);
    }
}

===============
0x01. 一个完整的demo
在自定义的Application中初始化WXShareManager

public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        WXShareManager.get().init(this);
    }
}

Activity代码

package com.stone.wx.share;

import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import com.stone.wx.share.wx.Util;
import com.stone.wx.share.wx.WXShareManager;

import java.io.File;

public class MainActivity extends AppCompatActivity
        implements View.OnClickListener {

    private final int KEY_REQUEST_CODE_READ_DISK = 0x001;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_xx);
        initViews();


        int accessPermission = ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE);
        if(accessPermission != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.READ_EXTERNAL_STORAGE}, KEY_REQUEST_CODE_READ_DISK);
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if(grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            t("您已经授权访问磁盘啦");
            return;
        }

        t("您没有权限访问磁盘");
    }

    private void t(String msg) {
        Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
    }
    private void initViews() {
        findViewById(R.id.send_image_bitmap).setOnClickListener(this);
        findViewById(R.id.send_image_url).setOnClickListener(this);
        findViewById(R.id.send_image_path).setOnClickListener(this);
        findViewById(R.id.send_image_byte_array).setOnClickListener(this);
        findViewById(R.id.send_text).setOnClickListener(this);
        findViewById(R.id.send_video).setOnClickListener(this);
        findViewById(R.id.send_music).setOnClickListener(this);
        findViewById(R.id.send_video).setOnClickListener(this);
        findViewById(R.id.send_webpage).setOnClickListener(this);
        findViewById(R.id.send_file).setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        WXShareManager mgr = WXShareManager.get();
        WXShareManager.ShareResultListener listener = new WXShareManager.ShareResultListener() {
            @Override
            public void onShareResult(boolean result) {
                Log.e("_share_", "onShareResult: " + result);
            }
        };
        boolean result = false;
        switch (view.getId()) {
//            case R.id.send_req:
//                result = mgr.sendReq("Send Request: Hello world !");
//                Toast.makeText(this, "share result = " + result, Toast.LENGTH_SHORT).show();
//                break;
//            case R.id.send_resp:
//                result = mgr.sendReq("Send Response: Hello world !");
//                Toast.makeText(this, "share result = " + result, Toast.LENGTH_SHORT).show();
//                break;

            case R.id.send_text:
                result = mgr.shareText("send text", "", "分享一段文字", WXShareManager.ShareType.FRIENDS, listener);
                Toast.makeText(this, "share result = " + result, Toast.LENGTH_SHORT).show();
                break;
            case R.id.send_image_bitmap:
                Drawable d = ActivityCompat.getDrawable(this, R.mipmap.ic_launcher);
                result = mgr.shareImage(((BitmapDrawable)d).getBitmap(), "", "分享一张图片", WXShareManager.ShareType.FRIENDS, listener);
                Toast.makeText(this, "share result = " + result, Toast.LENGTH_SHORT).show();
                break;
            case R.id.send_image_path:
                // 6.0+, 需要请求权限, 否则无法访问sdcard, 导致crash
                File file = new File(Environment.getExternalStoragePublicDirectory("aa"), "aa.jpg");
                Log.e("_share_", file.getAbsolutePath() + ", exist=" + file.exists());
                result = mgr.shareImage(file.getAbsolutePath(), null , "", "分享一张图片", WXShareManager.ShareType.FRIENDS, listener);
                Toast.makeText(this, "share result = " + result, Toast.LENGTH_SHORT).show();
                break;
            case R.id.send_image_url:
                result = mgr.shareImage("http://hbimg.b0.upaiyun.com/1b2e580fd26f7980ace830102f380f6edbef7a2b19d24-ZulhPB_fw658",
                        ((BitmapDrawable)ActivityCompat.getDrawable(this, R.mipmap.ic_launcher)).getBitmap(), "", "分享一张图片", WXShareManager.ShareType.FRIENDS, listener);
                Toast.makeText(this, "share result = " + result, Toast.LENGTH_SHORT).show();
                break;
            case R.id.send_image_byte_array:
                Bitmap bm = BitmapDrawable.class.cast(ActivityCompat.getDrawable(this, R.mipmap.ic_launcher)).getBitmap();
                byte[] imageData = Util.bmpToByteArray(bm, true);
                result = mgr.shareImage(imageData, "", "分享一张图片", WXShareManager.ShareType.FRIENDS, listener);
                Toast.makeText(this, "share result = " + result, Toast.LENGTH_SHORT).show();
                break;
            case R.id.send_music:
                //http://music.baidu.com/song/s/02071e66eed085438dcab?pst=sug
                result = mgr.shareMusic("http://music.baidu.com/album/269450521?pst=shoufa",
                        "寂寞先生", "一首流行歌曲",
                        WXShareManager.ShareType.FRIENDS, listener);
                Toast.makeText(this, "share result = " + result, Toast.LENGTH_SHORT).show();
                break;
            case R.id.send_video:
                result = mgr.shareVideo("http://v.youku.com/v_show/id_XODkyNjAyMzg4.html",
                        "动漫", "一个动漫视频", WXShareManager.ShareType.FRIENDS, listener);
                Toast.makeText(this, "share result = " + result, Toast.LENGTH_SHORT).show();
                break;
            case R.id.send_webpage:
                result = mgr.shareWebPage("http://www.jianshu.com/", "简书", "这是简书官网", WXShareManager.ShareType.FRIENDS, listener);
                Toast.makeText(this, "share result = " + result, Toast.LENGTH_SHORT).show();
                break;
            case R.id.send_file:
                Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
                intent.setType("image/*.png");
                startActivityForResult(Intent.createChooser(intent, "select file"), 10);
                Toast.makeText(this, "share result = " + result, Toast.LENGTH_SHORT).show();
                break;
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(requestCode == 10 && resultCode == RESULT_OK) {
            Uri uri = data.getData();
            String path = getPath(this, uri);
            WXShareManager.ShareResultListener listener = new WXShareManager.ShareResultListener() {
                @Override
                public void onShareResult(boolean result) {
                    Log.e("_share_", "onShareResult: " + result);
                }
            };
            WXShareManager.get().shareFile(path, "文件", "一个图片文件" ,WXShareManager.ShareType.FRIENDS, listener);
        }
    }

    String getPath(Context context, Uri uri) {

        if ("content".equalsIgnoreCase(uri.getScheme())) {
            String[] projection = { "_data" };
            Cursor cursor = null;

            try {
                cursor = context.getContentResolver().query(uri, projection,null, null, null);
                int column_index = cursor.getColumnIndexOrThrow("_data");
                if (cursor.moveToFirst()) {
                    return cursor.getString(column_index);
                }
            } catch (Exception e) {
                // Eat it
            }
        } else if ("file".equalsIgnoreCase(uri.getScheme())) {
            return uri.getPath();
        }

        return null;
    }
}

<package-name>.wxapi.WXEntryActivity.java代码如下:

package com.stone.wx.share.wxapi;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Toast;

import com.stone.wx.share.DevUtils;
import com.stone.wx.share.wx.WXShareManager;
import com.tencent.mm.sdk.modelbase.BaseReq;
import com.tencent.mm.sdk.modelbase.BaseResp;
import com.tencent.mm.sdk.openapi.IWXAPIEventHandler;

/**
 * @author stone
 * @date 16/8/30
 */
public class WXEntryActivity extends Activity implements IWXAPIEventHandler{


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        WXShareManager.get().handleIntent(getIntent(), this);
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        WXShareManager.get().handleIntent(intent, this);
    }

    @Override
    public void onReq(BaseReq baseReq) {
        DevUtils.d("baseReq="+baseReq + ",thread=" + Thread.currentThread().getName());
    }

    @Override
    public void onResp(BaseResp resp) {
        DevUtils.d("baseResp="+resp + ",thread=" + Thread.currentThread().getName());
        if(isFinishing()) return;

        if(WXShareManager.get().performShareResult(resp.errCode == BaseResp.ErrCode.ERR_OK)) {
            finish();
            return;
        }

        switch (resp.errCode) {
            case BaseResp.ErrCode.ERR_OK:
                t("已发送");
                break;
            case BaseResp.ErrCode.ERR_AUTH_DENIED:
                t("发送被拒绝");
                break;
            case BaseResp.ErrCode.ERR_SENT_FAILED:
                t("发送失败");
                break;
            case BaseResp.ErrCode.ERR_USER_CANCEL:
                t("取消发送");
                break;
            default:
                t("发送返回");
        }
        finish();
    }

    private void t(String msg) {
        Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
    }

}

布局文件比较简单, 就是一些Button, 因此省略.

总结
a. 在微信平台创建应用时, 签名和包名必须填写正确
b. 应用必须审核通过后才能分享, 否则分享会失败
c. 必须使用生成签名的keystore打的包才能分享

想要了解更多微信分享相关资料, 请参考微信开放平台相关文档, 微信开放平台

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,569评论 25 707
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,100评论 18 139
  • 最近由于相关需求,需要将微信分享集成到项目中,但在过程中遇到很多问题,现大致整理与此 此次过程中还有些许遗留问题(...
    忍辞阅读 18,218评论 13 46
  • 说来惭愧,从小喜欢手工劳技课(暴露年龄),自己也DIY多年,只要手工都喜欢,所以涉及的手工类也比较杂,可惜拿得出手...
    浮生九木阅读 141评论 0 0
  • 何辞可叹悲清秋,雁阵南去空哀嚎; 秋风一扫落叶尽,唯见糖槭依旧红。
    62227阅读 246评论 0 1