申請應(yīng)用AppKey申請方法:訪問友推網(wǎng)站后臺,登錄后進入應(yīng)用列表,添加需要集成友推組件的App,如下圖,添加成功后可獲取應(yīng)用的AppKey。如何把app分享到微信2申請社交平臺appkey集成前您需要為您的應(yīng)用在各大社交網(wǎng)站的開放平臺申請賬號并通過審核,否則只能調(diào)用系統(tǒng)的分享菜單,無法跟蹤分享的回調(diào)事件及統(tǒng)計平臺如何把app分享到微信3引用youtui庫項目將youtui-lib項目庫和應(yīng)用工程放在同一個目錄下在PackageExplorer中右鍵點擊工程的根目錄,選擇Properties(屬性),然后點擊,在Android選項點擊Add添加youtui-lib如何把app分享到微信4注冊需要分享的平臺1.配置各分享平臺key,該配置文件為youtui_sdk.xml,配置完放入工程的assets文件夾。2.如果需要分享到哪個平臺就將該平臺的Enable屬性設(shè)置為true.3.如果需要將某個平臺排列到前面,只需要改變它在youtui_sdk.xml文件中的位置即可。5各平臺需要注意的事項:新浪微博:新浪微博需要驗證應(yīng)用簽名,請一定要在新浪開放平臺管理中心應(yīng)用信息-基本信息-Android簽名包名信息配置該信息每次包名變化或者使用的.keystore變化都會導(dǎo)致應(yīng)用簽名變化,請重新到新浪微博開放平臺設(shè)置。運行Demo時如果重新編譯,因為使用的.keystore文件變化也會導(dǎo)致應(yīng)用簽名變化,導(dǎo)致Demo新浪微博分享無法正常工作,請運行Demo時使用Demo工程包中提供的debug.keystore替換C:\Users\Administrator.android中的debug.keystore文件微信和朋友圈:微信和朋友圈也需要驗證應(yīng)用簽名,請在微信開放平臺管理中心修改應(yīng)用-開發(fā)信息配置。QQ和QQ空間:QQ和QQ空間使用的是騰訊開放平臺api,請在騰訊開放平臺申請賬號和注冊應(yīng)用,請不要使用QQ互聯(lián)(用于網(wǎng)站賬號登錄)的配置,雖然都是騰訊的,但是兩個平臺并不通用,除了需要在youtui_sdk.xml配置信息,還需要在manifest文件中的android:scheme中的tencent后的一串?dāng)?shù)字換成自己應(yīng)用的appid。最后一行配置說明:選用調(diào)用系統(tǒng)分享菜單功能在AndroidManifest.xml注冊權(quán)限在AndroidManifest.xml注冊需要的Activity微信和朋友圈回調(diào)設(shè)置如果需要分享微信和朋友圈,必需建一個應(yīng)用包名+.wxapi的包,在該包下建WXEntryActivity.java,將該類繼承cn.bidaround.youtui.wxapi.WXEntryActivity即可(里面不用寫代碼)publicclassWXEntryActivityextendscn.bidaround.youtui.wxapi.WXEntryActivity{}如圖:(將com.xingxinglangtuoche替換成你應(yīng)用的package名,微信回調(diào)會使用到)如何把app分享到微信初始化友推開發(fā)者請在自己的程序開始,最好是在MainActivity的onCreate方法調(diào)用YtTemplate.init(this)初始化友推sdk,這樣友推sdk才能進行后續(xù)調(diào)用(否則分享等操作會出現(xiàn)空指針異常),例如:protectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);YtTemplate.init(this);/初始化友推/initView();}應(yīng)用退出時:在您項目的出口Activity的onDestroy方法的第一行插入下面的代碼YtTemplate.release(this);此方法用于釋放內(nèi)存,統(tǒng)計用戶使用情況,一旦調(diào)用了release,就必須重新調(diào)用init才能使用友推的功能,否則會出現(xiàn)空指針異常;創(chuàng)建ShareData實例,調(diào)用該實例的set方法設(shè)置需要分享的數(shù)據(jù):創(chuàng)建ShareData實例,調(diào)用該實例的set方法設(shè)置自己需要分享的數(shù)據(jù),關(guān)于該實例具體內(nèi)容見下文,如果只是分享應(yīng)用則只需要設(shè)置setIsAppShare(true)就可以分享應(yīng)用在友推后臺填寫的信息和下載鏈接。ShareData包含的字段:isAppSharetextimagePathimageUrldescriptiontitletarget_url判斷是否為分享應(yīng)用待分享的文字,短信要小于70個字符,微博要小于140個字符,如果需要分享鏈接,最好將鏈接url放在最后待分享的本地圖片地址,分享圖片的話需要在本地和網(wǎng)絡(luò)圖片中選一,如果都有則優(yōu)先分享本地圖片待分享網(wǎng)絡(luò)圖片url,分享圖片的話需要在本地和網(wǎng)絡(luò)圖片中選一,如果都有則優(yōu)先分享本地圖片待分享內(nèi)容的描述待分享內(nèi)容的標(biāo)題待分享內(nèi)容的跳轉(zhuǎn)鏈接通過創(chuàng)建該類實例,調(diào)用實例的set方法設(shè)置這些參數(shù),例如:ShareDatashareData=newShareData();shareData.isAppShare=false;//設(shè)置為true則分享的信息從友推后臺填寫的應(yīng)用信息中讀取,可動態(tài)更新,后面的值不用設(shè)置。shareData.setDescription("友推積分組件");shareData.setTitle("友推分享");shareData.setText("通過友推積分組件,開發(fā)者幾行代碼就可以為應(yīng)用添加分享送積分功能,并提供詳盡的后臺統(tǒng)計數(shù)據(jù),除了本身具備的分享功能外,開發(fā)者也可將積分功能單獨集成在已有分享組件的app上,");shareData.setTarget_url("");shareData.setImageUrl("");shareData.setImagePath("");各個平臺分享數(shù)據(jù)的限制和注意事項:因為各個平臺的分享限制,請分享時盡量分享圖片+鏈接,依靠鏈接來了解信息1)微信朋友圈微信分享為linkcard形式,超出的文字部分不會顯示2)新浪微博很低版本的新浪微博不支持發(fā)多類型微博,進行圖文分享時只會分享圖片,新浪微博分享消息最長為140字3)QQ、QQ空間QQ分享的消息最長40字,分享的標(biāo)題最長30字,多余的部分將被忽略,description將被忽略QQ空間分享的消息最長200字,分享的標(biāo)題最長600字,多余的部分將被忽略,description將被忽略4)騰訊微博只有image(imagePath或imageUrl)和text被分享,其他字段忽略,騰訊微博分享消息最長為140字5)人人網(wǎng)只有image(imagePath或imageUrl)和text被分享,其他字段忽略6)短信只有text被分享,其他字段忽略7)郵件只有text被分享,其他字段忽略如何把app分享到微信調(diào)用友推分享推薦組件為應(yīng)用添加一個分享推薦按鈕,如:如何把app分享到微信在分享按鈕事件中調(diào)用youtui的組件即可,示例代碼:publicvoidonClick(Viewv){if(v.getId()==R.id.popup_bt){/調(diào)用友推分享推薦組件,YouTuiViewType類的常量為分享樣式參數(shù),目前支持白色列表和黑色網(wǎng)格兩種//創(chuàng)建分享的模板,第一個參數(shù)為activity,第二個參數(shù)為分享窗口樣式,第三個參數(shù)為是否需要積分/YtTemplateblackTemp=newYtTemplate(this,YouTuiViewType.BLACK_POPUP,false);//黑色網(wǎng)格樣式不需要積分活動/YtTemplateblackTemp=newYtTemplate(this,YouTuiViewType.WHITE_LIST,ture);///白色列表樣式需要積分活動ShareDatashareData=newShareData();shareData.isAppShare=false;//設(shè)置為true則分享的信息從友推后臺填寫的應(yīng)用信息中讀取,可動態(tài)更新后面的值不用設(shè)置。shareData.setDescription("友推積分組件");shareData.setTitle("友推分享");shareData.setText("通過友推積分組件,開發(fā)者幾行代碼就可以為應(yīng)用添加分享送積分功能,并提供詳盡的后臺統(tǒng)計數(shù)據(jù),除了本身具備的分享功能外,開發(fā)者也可將積分功能單獨集成在已有分享組件的app上,快來試試吧");shareData.setTarget_url("");shareData.setImageUrl("");shareData.setImagePath("");blackTemp.setShareData(shareData);//設(shè)置默認(rèn)的分享數(shù)據(jù);shareData設(shè)置參看4.6//**如果要為某個平臺設(shè)置不一樣的分享信息。則單獨設(shè)置*///blackTemp.addData(YtPlatform.PLATFORM_QQ,shareData);//調(diào)出分享窗口blackTemp.show();//如果需要自定義分享事件,可以創(chuàng)建監(jiān)聽事件,然后在回調(diào)中處理YtShareListenerlistener1=newYtShareListener(){@OverridepublicvoidonSuccess(ErrorInfoarg0){}@OverridepublicvoidonPreShare(){}@OverridepublicvoidonError(ErrorInfoarg0){}@OverridepublicvoidonCancel(){}};//給新浪微博添加分享監(jiān)聽blackTemp.addListener(YtPlatform.PLATFORM_SINAWEIBO,listener1);//給QQ添加分享監(jiān)聽//blackTemp.addListener(YtPlatform.PLATFORM_QQ,listener2);}
在陸豐等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強發(fā)展的系統(tǒng)性、市場前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供網(wǎng)站設(shè)計制作、網(wǎng)站建設(shè) 網(wǎng)站設(shè)計制作按需制作網(wǎng)站,公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),品牌網(wǎng)站設(shè)計,網(wǎng)絡(luò)營銷推廣,外貿(mào)營銷網(wǎng)站建設(shè),陸豐網(wǎng)站建設(shè)費用合理。
你可以這么做,數(shù)據(jù)庫里面有一個字段是來判斷是不是第一次,字段為1的話就是已經(jīng)轉(zhuǎn)發(fā)過了,為0的話就是還沒有轉(zhuǎn)發(fā),如果為1你就不要執(zhí)行jssdk的分享
程序運行原理
給頁面文字添加span標(biāo)簽,設(shè)置id="text-xx"唯一屬性,使用contenteditable="true",開啟該元素的編輯模式,用jQuery屬性.click()判斷點擊,用.text()返回此元素的文本內(nèi)容,并用正則進行判斷內(nèi)容是否合法,然后通過AJAX POST給php處理,php對傳入的參數(shù)進行過濾,然后讀取模版文件,替換模版文件對應(yīng)內(nèi)容,保存為新文件并記錄操作,最后返回數(shù)據(jù)給前端,前端處理數(shù)據(jù)并更新頁面。
主要思路
從UI獲取文本信息是最為簡單的方法,于是應(yīng)該優(yōu)先逆向UI代碼部分。
逆向微信apk
首先解包微信apk,用dex2jar反編譯classes.dex,然后用JD-GUI查看jar源碼。當(dāng)然,能看到的源碼都是經(jīng)過高度混淆的。但是,繼承自安卓重要組件(如Activity、Service等)的類名無法被混淆,于是還是能從中看到點東西。
首先定位到微信APP package。我們知道這個是 com.tencent.mm。
在 com.tencent.mm
中,我們找到一個 ui
包,有點意思。
展開 com.tencent.mm.ui
,發(fā)現(xiàn)多個未被混淆的類,其中發(fā)現(xiàn) MMBaseActivity直接繼承自 Activity
, MMFragmentActivity
繼承自 ActionBarActivity
, MMActivity
繼承自 MMFragmentActivity
,并且 MMActivity
是微信中大多數(shù)Activity的父類:
public class MMFragmentActivity
extends ActionBarActivity
implements SwipeBackLayout.a, b.a {
...
}
public abstract class MMActivity
extends MMFragmentActivity {
...
}
public class MMBaseActivity
extends Activity {
...
}
現(xiàn)在需要找出朋友圈的Activity,為此要用Xposed hook MMActivity。
創(chuàng)建一個Xposed模塊
參考 [TUTORIAL]Xposed module devlopment,創(chuàng)建一個Xposed項目。
簡單Xposed模塊的基本思想是:hook某個APP中的某個方法,從而達(dá)到讀寫數(shù)據(jù)的目的。
小編嘗試hook com.tencent.mm.ui.MMActivity.setContentView這個方法,并打印出這個Activity下的全部TextView內(nèi)容。那么首先需要遍歷這個Activity下的所有TextView,遍歷ViewGroup的方法參考了SO的以下代碼:
private void getAllTextViews(final View v) {if (v instanceof ViewGroup) {
ViewGroup vg = (ViewGroup) v;
for (int i = 0; i vg.getChildCount(); i++) {View child = vg.getChildAt(i);
getAllTextViews(child);
}
} else if (v instanceof TextView ) {
dealWithTextView((TextView)v); //dealWithTextView(TextView tv)方法:打印TextView中的顯示文本}
}
Hook MMActivity.setContentView
的關(guān)鍵代碼如下:
findAndHookMethod("com.tencent.mm.ui.MMActivity", lpparam.classLoader, "setContentView", View.class, new XC_MethodHook() {...
});
在findAndHookMethod方法中,第一個參數(shù)為完整類名,第三個參數(shù)為需要hook的方法名,其后若干個參數(shù)分別對應(yīng)該方法的各形參類型。在這里, Activity.setContentView(View view)方法只有一個類型為 View
的形參,因此傳入一個 View.class
。
現(xiàn)在,期望的結(jié)果是運行時可以從Log中讀取到每個Activity中的所有的TextView的顯示內(nèi)容。
但是,因為View中的數(shù)據(jù)并不一定在 setContentView()時就加載完畢,因此小編的實驗結(jié)果是,log中啥都沒有。
意外的收獲
當(dāng)切換到朋友圈頁面時,Xposed模塊報了一個異常,異常源從 com.tencent.mm.plugin.sns.ui.SnsTimeLineUI這個類捕捉到。從類名上看,這個很有可能是朋友圈首頁的UI類。展開這個類,發(fā)現(xiàn)更多有趣的東西:
這個類下有個子類 a
(被混淆過的類名),該子類下有個名為 gyO的 ListView
類的實例。我們知道, ListView
是顯示列表類的UI組件,有可能就是用來展示朋友圈的列表。
順藤摸瓜
那么,我們先要獲得一個 SnsTimeLineUI.a.gyO的實例。但是在這之前,要先獲得一個 com.tencent.mm.plugin.sns.ui.SnsTimeLineUI.a的實例。繼續(xù)搜索,發(fā)現(xiàn) com.tencent.mm.plugin.sns.ui.SnsTimeLineUI有一個名為 gLZ
的 SnsTimeLineUI.a
實例,那么我們先取得這個實例。
經(jīng)過測試, com.tencent.mm.plugin.sns.ui.SnsTimeLineUI.a(boolean, boolean, String, boolean)這個方法在每次初始化微信界面的時候都會被調(diào)用。因此我們將hook這個方法,并從中取得 gLZ。
findAndHookMethod("com.tencent.mm.plugin.sns.ui.SnsTimeLineUI", lpparam.classLoader, "a", boolean.class, boolean.class, String.class, boolean.class, new XC_MethodHook() {@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {XposedBridge.log("Hooked. ");
Object currentObject = param.thisObject;
for (Field field : currentObject.getClass().getDeclaredFields()) { //遍歷類成員field.setAccessible(true);
Object value = field.get(currentObject);
if (field.getName().equals("gLZ")) {
XposedBridge.log("Child A found.");
childA = value;
//這里獲得了gLZ
...
}
}
}
});
現(xiàn)在取得了 SnsTimeLineUI.a
的一個實例 gLZ
,需要取得這個類下的 ListView
類型的 gyO
屬性。
private void dealWithA() throws Throwable{if (childA == null) {
return;
}
for (Field field : childA.getClass().getDeclaredFields()) { //遍歷屬性field.setAccessible(true);
Object value = field.get(childA);
if (field.getName().equals("gyO")) { //取得了gyOViewGroup vg = (ListView)value;
for (int i = 0; i vg.getChildCount(); i++) { //遍歷這個ListView的每一個子View...
View child = vg.getChildAt(i);
getAllTextViews(child); //這里調(diào)用上文的getAllTextViews()方法,每一個子View里的所有TextView的文本...
}
}
}
}
現(xiàn)在已經(jīng)可以將朋友圈頁面中的全部文字信息打印出來了。我們需要根據(jù)TextView的子類名判斷這些文字是朋友圈內(nèi)容、好友昵稱、點贊或評論等。
private void dealWithTextView(TextView v) {String className = v.getClass().getName();String text = ((TextView)v).getText().toString().trim().replaceAll("\n", " ");if (!v.isShown())
return;
if (text.equals(""))
return;
if (className.equals("com.tencent.mm.plugin.sns.ui.AsyncTextView")) {//好友昵稱
...
}
else if (className.equals("com.tencent.mm.plugin.sns.ui.SnsTextView")) {//朋友圈文字內(nèi)容
...
}
else if (className.equals("com.tencent.mm.plugin.sns.ui.MaskTextView")) {if (!text.contains(":")) {
//點贊
...
} else {
//評論
...
}
}
}
自此,我們已經(jīng)從微信APP里取得了朋友圈數(shù)據(jù)。當(dāng)然,這部分抓取代碼需要定時執(zhí)行。因為從 ListView中抓到的數(shù)據(jù)只有當(dāng)前顯示在屏幕上的可見部分,為此需要每隔很短一段時間再次執(zhí)行,讓用戶在下滑加載的過程中抓取更多數(shù)據(jù)。
剩下的就是數(shù)據(jù)分類處理和格式化輸出到文件,受本文篇幅所限不再贅述,詳細(xì)實現(xiàn)可參考作者GitHub上的源碼。
操作步驟如下:
1、首先將要分享的網(wǎng)址發(fā)到手機上,可以通過QQ或者email等各種方法。
如果是在手機瀏覽器上看到的網(wǎng)頁,可以把網(wǎng)址復(fù)制下來,
2、進入朋友圈,長按右上角的相機圖標(biāo),記住,是長按,
3、把要分享的網(wǎng)址粘貼進去,如下圖,然后點發(fā)送,
4、再返回朋友圈,發(fā)現(xiàn)多了一個網(wǎng)址,。
5、點擊該 網(wǎng)址,進入網(wǎng)頁,如下圖,再點右上角的分享圖標(biāo)
6、然后出現(xiàn)了分享到朋友圈的選項,選擇分享到朋友圈,。
7、然后選擇發(fā)送,如下圖,當(dāng)然還可以寫上想法。
8、再返回朋友圈,會發(fā)現(xiàn)要分享的內(nèi)容已經(jīng)出現(xiàn)了,然后把前面發(fā)網(wǎng)址刪除掉就行了。
下面是代碼(相關(guān)參數(shù)請自行修改):
function WeiXinShareBtn() {
if (typeof WeixinJSBridge == "undefined") {
alert("xxxxxxxxxxxxxxxxxxx,通過微信分享文章 ");
} else {
WeixinJSBridge.invoke('shareTimeline', {
"title": "xxx",
"link": "",
"desc": "xxxxxxxx",
"img_url": "assets/images/apple-touch-icon.png"
});
}
}