1. 程式人生 > >Android開發知識(十一):讓你的應用接入微信分享,完美繞過微信分享的大坑

Android開發知識(十一):讓你的應用接入微信分享,完美繞過微信分享的大坑

目錄

一、申請應用

1、首先到 [ 微信開放平臺官網] 申請註冊帳號,這些流程就忽略了到官網一看自然就知道怎麼走,感覺在這裡沒有必要說很多。
2、申請一個移動應用,填寫完成你的應用資訊。其他的沒啥,最主要的是要填對你的簽名和包名,否則SDK調不起來。包名大家都懂,主要是這個簽名的過程需要提醒一下:
1)簽名全部是小寫,沒有大寫。
2)簽名填的是MD5,不是SHA1更不是SHA256,有的同學不小心就搞錯了
這裡獲取應用簽名的方法有二。

第一個方法:先假設我們的應用已經有簽名檔案了(這裡就不講解生成簽名檔案的過程了,Android Studio提供的生成簽名檔案的方法已經很簡單了,這裡不贅述)。在命令列輸入以下命令:

keytool -list -v -keystore 目標籤名檔案路徑

然後輸入一下簽名檔案的密碼後就出來很多簽名檔案的資訊:
簽名
注意是複製出裡面的指紋證書下的MD5那一串。
然後自己手動把大寫字母改成小寫字母,並且把冒號都去掉。這樣子就得到了簽名。

第二個方法:簡單粗暴,微信開放平臺提供給我們一個簽名獲取的工具,點選這裡跳轉
這裡寫圖片描述
然後把apk安裝到手機後,正確輸入你的應用包名後就獲取到了一串簽名:
這裡寫圖片描述

把這串簽名填寫到你申請的應用配置裡面。

搞定,等待微信稽核。
稽核完成後得到AppID 和 AppSecret 。注意這兩個,等下要用到。

二、配置微信分享的SDK

可以直接到官網下載jar包或者配置依賴:

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

或者

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

(其中,前者包含統計功能)

然後我們新增如下許可權:


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

<uses-permission
android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <uses-permission android:name="android.permission.READ_PHONE_STATE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

三、微信分享示例

1、首先我們需要像微信註冊我們申請的應用,在前面我們申請的應用稽核完後的APP_ID 和APP_SECRET 就填寫在這裡:

private static final String APP_ID = "123456"; 
private static final String APP_SECRET = "123456";
private IWXAPI api;  
//向微信註冊app
public void register(Context context) {   
    if(api==null){
        api = WXAPIFactory.createWXAPI(context, APP_ID, true);  
        api.registerApp(APP_ID);        
    }
}

這部分程式碼沒有限制性需要在哪裡執行,你可以放在Application的onCreate,也可以在Activity,筆者推薦放在你要做分享的Activity裡。

接下來就是編寫分享的程式碼了。微信分享有文字、圖片、連結、音樂、視訊這幾種方式,分享的途徑有分享到好友、分享到朋友圈。
由於不同分享方式的原理相同,這裡我們就拿分享網頁連結的例子來說
以下是分享網頁連結的程式碼:

WXWebpageObject webpage = new WXWebpageObject();
        webpage.webpageUrl = "網頁連結";
        final WXMediaMessage msg = new WXMediaMessage(webpage);
        msg.title = "網頁標題";
        msg.description = "網頁內容";

        Bitmap thumb = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.xxx);
        if(thumb != null) {
            Bitmap mBp = Bitmap.createScaledBitmap(thumb, 120, 120, true);
            thumb.recycle();
            msg.thumbData = bmpToByteArray(thumb,true);
        }
       SendMessageToWX.Req req = new SendMessageToWX.Req();    //建立一個請求物件
    req.message = msg; 
    //req.scene = SendMessageToWX.Req.WXSceneTimeline;    //設定傳送到朋友圈
    req.scene = SendMessageToWX.Req.WXSceneSession;   //設定傳送給朋友
    req.transaction = "設定一個tag";  //用於在回撥中區分是哪個分享請求
    boolean successed = api.sendReq(req);   //如果呼叫成功微信,會返回true

好了,正常的話到這一步我們已經能夠調起微信對好友分享網頁連結了。
而往往事與願違,現實和理想差距太大。有很多同學到這一部卻碰到很多問題,比如:

1、調不起來,微信一點反應都沒有;
2、能分享給好友、但是顯示不了網頁連結的圖片;
3、能分享給好友,自己能看到網頁連結的圖片,但是朋友看不到。

問題的答案如下:
第一個問題:調不起來,微信一點反應都沒有
首先你得保證填寫的包名和簽名是一定正確的,簽名你如果不確定是否正確的話就最好用官方的簽名獲取apk來校驗一下。
其次,你得確保有沒有註冊了?我們在程式碼的第一步寫的:
WXAPIFactory.createWXAPI(context, APP_ID, true);
如果都確保是沒問題的,那麼就要從圖示入手了,這是微信文件的一個大坑

我們在分享連結的時候填寫圖片,這個bitmap不能超過32kb
事實證明如果傳給微信的bitmap太大的話,則微信會無任何反應,Log也看不出什麼出錯。
所以有了這一步:

Bitmap mBp = Bitmap.createScaledBitmap(thumb, 120, 120, true);

或者把你的圖切小一點。也許就能調起來了。
第二個問題:能分享給好友、但是顯示不了網頁連結的圖片
這個問題其實也是跟bitmap的大小有關,跟問題一差不多。所以建議兩個方法,要麼把圖片切小一點。要麼程式碼控制圖片的大小,使之在正常的範圍內。

第三個問題:能分享給好友,自己能看到網頁連結的圖片,但是朋友看不到
前面兩個問題其實還好,至少稍微百度一下就能解決。而第三個問題著實坑爹。好友看不到你的網頁圖片,會讓你誤以為是問題二導致的,結果一頓修改都解決不了問題。
而其實,這個是跟微信的一個敏感詞檢測系統,如果你的網頁分享內容裡面包含了“紅包”、“領取”等等之類的詞語,極有可能造成問題三的產生,而微信目前沒有公佈哪些敏感詞不通過,所以出現這個問題的話你一定要注意修改你的標題和內容了,只能把表達方式換一個,再試一下。

四、微信分享的結果回撥

說了這麼多,想必你已經能調起微信進行分享了吧。我們還沒說到微信的回撥,其實微信的回撥說起來也是比較坑的,如果沒接觸過的話,這個回撥也能耗了你不少時間。
微信的回撥有四大坑,這裡通過踩坑的方式來完成示例:

1、新建WXEntryActivity(坑一:新建的WXEntryActivity類包名路徑不對)
長話短說,這裡千言萬語融成一句話:一定要在建立一個 包名.wxapi.WXEntryActivity
比如你的包名是:com.example.demo。那麼你就得配置一個com.example.demo.wxapi.WXEntryActivity
千萬要注意,不要隨便亂放這個Activity,也不能改名,就叫WXEntryActivity。包名跟你申請應用的時候填寫的包名一致。

2、向AndroidManifest.xml註冊WXEntryActivity(坑二:沒有配置android:exported=”true”)

  <activity android:name=".wxapi.WXEntryActivity"
            android:exported="true"
            android:launchMode="singleTop"
            ></activity>

注意看清楚沒?多配置了一個 android:exported=”true”,這個屬性代表著執行被外界程式所啟動這個Activity,微信對於我們的app來說就是外部程式了,要回調我們的Activity,沒有這個萬萬不行。千萬要注意

3、實現IWXAPIEventHandler介面,註冊API(坑三:沒有在onCreate裡註冊API)
這個介面有兩個方法:

@Override
    public void onReq(BaseReq baseReq) {

    }

    @Override
    public void onResp(BaseResp baseResp) {

    }

分別是我們做出的請求和請求的結果回撥。我們的業務邏輯便是從onResp方法裡寫的
然後一定要 千萬要 萬萬要註冊api、八成沒有接收到回撥的同學們就是沒有這一步:

  @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //註冊API 沒有這個不會執行onResp
        api = WXAPIFactory.createWXAPI(this, WXModel.APP_ID);
        api.handleIntent(getIntent(), this);
        LogUtils.i(TAG, " handleIntent:" + api.handleIntent(getIntent(), this));
    }

4、在onResp方法裡編寫分享後的回撥處理邏輯(坑四:回撥處理邏輯搞錯)
其實到這一步回撥就可以完成了。剩下的是我們的回調回來頁面後的業務邏輯,從onResp來處理。
在這裡特別注意提醒同學們,由於微信的登入和分享都是一樣放在這個WXEntryActivity裡面,所以在onResp方法裡面我們必須做出區分,通過baseReq.getType()可以得到回撥的型別,在ConstantsAPI接口裡面定義了微信回撥的很多型別,需要我們自己來區分
這裡寫圖片描述

然後通過狀態碼:resp.errCode 來得知分享的結果(成功、失敗、取消等等),正常成功的話是resp.errCode==BaseResp.ErrCode.ERR_OK,取消分享是BaseResp.ErrCode.ERR_USER_CANCEL。

好了,到這一步的時候我們就繞過這麼多個坑,基本做對的話就能成功分享連結出去並且回撥分享結果。

最後,由於微信的回撥機制,我們沒辦法做出其他處理,一定只能通過在固定的包名路徑下新建這個類來完成回撥,如果你實在不想微信顯示這個頁面的話,那麼也可以通過廣播、或者EventBus來吧結果回調出去,然後結束頁面。這樣子註冊了廣播接收或者EventBus的Actibity就能接收到回撥的結果:

 @Override
    public void onResp(BaseResp baseResp) {
        if (baseResp.getType() == ConstantsAPI.COMMAND_SENDMESSAGE_TO_WX) {
            Intent intent = new Intent("SHARE_WX_ACTION");
            intent.putExtra("errCode", baseResp.errCode);
            sendBroadcast(intent);
            finish();
        }
    }

五、微信分享的踩坑總結

到這裡,微信分享的過程就結束了,你學會了嗎?
由於坑比較多,在最後我們再總結下微信分享都有哪些需要注意的地方:

1、配置簽名的坑
解決:一定要MD5、小寫、不要帶冒號,最好用官方給的簽名獲取工具。
2、沒有註冊API
解決:API是執行重複註冊的,並且也不是耗時任務,所以不妨放在Activity的onCreate下面,記得寫這個。
3、分享的圖示
解決:分享的圖示大小不能超過32K,要是jpg格式。
3、分享圖示自己能看到,好友看不到
解決:修改分享的標題和內容,不要觸及微信的敏感詞檢測系統,多試幾下。
4、沒有回撥
解決:一定要注意WXEntryActivity的包名路徑是否正確,已經配置export=true
5、確定了問題4後還是調不起來
你確定有在WXEntryActivity的onCreate裡面註冊API並且呼叫 api.handleIntent(getIntent(), this);? 估計你沒有吧?
6、回撥到其他頁面
解決:沒辦法直接回調到其他頁面,但可以通過廣播、EventBus等通知的實現來通知其他頁面重新整理,同時結束WXEntryActivity的頁面。