好長時間沒寫blog了,以前換了一家公司。表示工做更有戰鬥力了,惋惜就是沒時間寫文章了。在這段時間實際上是遇到不少問題的,只是都是記錄下來,並無花時間去研究解決。可是這周遇到這個問題沒辦法讓我繼續前進了。必須記錄一下。以被後人使用。很少說了,進入主題。html
一、對於GA的瞭解(自行google)java
二、對CampaignTrackingReceiver類的瞭解,他是當從GP上下載而且安裝完成一個app的時候,發送一個廣播,會在Intent中攜帶一些數據,通常是Refer值,這裏能夠區分從哪裏下載的,具體簡單的例子:A應用是我須要發佈到GP上的應用,可是咱們可能會在各個渠道上推廣A,因此咱們可能須要加上渠道號進行統計,因此這時候須要在A應用添加CampaignTrackingReceiver廣播接收器,而後處理接收到的廣播中的Intent的內容,解析出具體的渠道號,進行上報便可。因此說GP發送這個廣播仍是很奇特的,他發送了這個廣播,而後等咱們安裝A而且運行了以後就能夠接收到這個廣播,等於這個廣播發出去了,他會等待有一個接收器接受他。android
三、本文中須要用到的工具下載地址:http://download.csdn.net/detail/jiangwei0910410003/8679153,下載完以後,首先要看一下txt文檔中的說明。app
工程中接入了GA統計(Google提供的一種app統計功能的SDK),可是咱們本身可能須要統計app從GP上下載的統計(這裏通常是註冊一個CampaignTrackingReceiver的廣播),可是有問題就是GA的SDK中已經包含了CampaignTrackingReceiver類了,當時在弄的時候進入到了一個誤區:就是認爲若是app中想接收到這個廣播的話。廣播接收器的包名必須是:com.google.analytics.tracking.android,類名:CampaignTrackingReceiver,相似於下面的註冊代碼:ide
<receiver android:name="com.google.analytics.tracking.android.CampaignTrackingReceiver" android:exported="true"> <intent-filter> <action android:name="com.android.vending.INSTALL_REFERRER" /> </intent-filter> </receiver>可是以後發現不須要這樣的,只要包名同樣便可,其實從Android中發送廣播的機制就能夠知道。類名沒有關係的,可是當時這個東西沒辦法測試的(須要發佈一個測試app到GP上,時間上也是不容許的,只能聽前輩的)。最後也是本身發佈了一個測試app測試了才知道,不須要類名同樣的,這個也算是一種收穫,那麼既然類名不同的話,這裏就沒有問題了。就不會和GA中的類重複了。可是我在沒有解釋這個誤區前用了另外的一種方法解決了這個問題。既然GA中有這個廣播接收類,咱們不能定義的話,能夠在它的SDK中的這個廣播類中插入一段代碼:發送一個廣播,把Intent中的數據帶出來便可。思路有了,下面來看一下具體操做:
下面講述的內容是基於上面的誤區沒有被解釋的狀況下說的,並且側重點也不是解釋誤區。而是如何修改Jar中內容工具
首先說一下這個過程當中的三個角色:jar,dex,smali測試
四個工具:dx.bat,dex2jar.bat,baksmali.jar,smali.jarui
關係圖以下:this
咱們這裏須要修改jar中的代碼,google
首先說明一下,關於修改jar中的代碼其實有不少方法的:
一、直接用壓縮包工具打開jar中的class文件進行修改(除非你對指令集很熟悉,反正我是不肯意嘗試)
二、使用jd-gui工具直接打開jar,進行修改(這個雖然能看懂代碼,可是有一個問題就是若是代碼被混淆了,那個難度還不如第一種方法了,因此也沒有嘗試)
好吧,那麼第三種方法就是修改smali文件,這個文件的好處在於:指令簡單,並且若是混淆了,也是沒有關係的。關於smail的指令說明,能夠自行google一下。很簡單這裏就不作解釋了。
那麼問題來了,如何將jar變成smali呢?這裏沒有發現他們兩之間的直接轉化工具,因此就曲線救國的方式作了。
首先將jar==>dex==>smali
而後修改smail中的內容
修改完以後會變成jar
smail==>dex==>jar
至關於dex是中轉站了。
技術實現說明完以後,下面來看一下Demo:
ReceiverLib工程
一、BtnReceiver.java
package com.example.receiverdemo; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.util.Log; public class BtnReceiver extends BroadcastReceiver{ private String action = "demo.action.myreceiver"; @Override public void onReceive(Context context, Intent intent) { Log.i("demo", "action:"+intent.getAction()); } }接收到廣播而後打印log一下
二、MyReceiver.java
package com.example.receiverdemo; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.util.Log; public class MyReceiver extends BroadcastReceiver{ private String action = "demo.action.myreceiver"; @Override public void onReceive(Context context, Intent intent) { Log.i("demo", "action:"+intent.getAction()); } }
package com.example.receiverdemo; import android.content.Context; import android.content.Intent; public class Utils { public static void sendBroadcast(Context context,String action){ Intent intent = new Intent(); intent.setAction(action); context.sendBroadcast(intent); } }說明:BtnReceiver是點擊Button以後發送的一個模擬廣播,至關於上面須要改的CampaignTrackingReceiver類,MyReceiver是咱們須要本身添加的廣播接收器。
項目下載:http://download.csdn.net/detail/jiangwei0910410003/8679113
ReceiverDemo工程(須要導入ReceiverLib導出的jar)
package com.example.receiverdemo; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; import android.view.View; import android.view.View.OnClickListener; public class MainActivity extends ActionBarActivity { private String action = "demo.action.btnreceiver"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.btn).setOnClickListener(new OnClickListener(){ @Override public void onClick(View v) { Utils.sendBroadcast(MainActivity.this, action); }}); } }模擬發送一個廣播
項目下載:http://download.csdn.net/detail/jiangwei0910410003/8679123
效果:
點擊Button以後,發送了廣播,BtnReceiver也接收到了。
那麼下面就開始在BtnReceiver.java中插入代碼,發送一個MyReceiver
首先使用dx命令,將咱們上面ReceiverLib導出的jar變成dex文件:
dx命令的使用方式:dx --dex --output C:\receiver.dex receiver.jar
而後在將receiver.dex轉化成smali:
baksmali.jar的使用方式:java -jar baksmali-2.0.5.jar -o c:\classout/ c:\receiver.dex
咱們能夠查看smali文件,咱們重點看BtnReceiver.smali文件,由於咱們要在這裏插入代碼:
.class public Lcom/example/receiverdemo/BtnReceiver; .super Landroid/content/BroadcastReceiver; .source "BtnReceiver.java" # direct methods .method public constructor <init>()V .registers 1 .prologue .line 8 invoke-direct {p0}, Landroid/content/BroadcastReceiver;-><init>()V return-void .end method # virtual methods .method public onReceive(Landroid/content/Context;Landroid/content/Intent;)V .registers 7 .param p1, "context" # Landroid/content/Context; .param p2, "intent" # Landroid/content/Intent; .prologue .line 12 invoke-virtual {p2}, Landroid/content/Intent;->getAction()Ljava/lang/String; move-result-object v0 .line 13 .local v0, "action":Ljava/lang/String; const-string v1, "demo" new-instance v2, Ljava/lang/StringBuilder; const-string v3, "action:" invoke-direct {v2, v3}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V invoke-virtual {v2, v0}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; move-result-object v2 invoke-virtual {v2}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String; move-result-object v2 invoke-static {v1, v2}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I const-string v4, "demo.action.myreceiver" invoke-static {p1, v4}, Lcom/example/receiverdemo/Utils;->sendBroadcast(Landroid/content/Context;Ljava/lang/String;)V const-string v5, "sendbroadcast" invoke-static {v1, v5}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I .line 14 return-void .end method
Utils.sendBroadcast方法:
這個過程當中沒有難度的,就不作解釋了
下面咱們就須要還原成jar了:
使用smali.jar工具將samli變成dex
用法:java -jar smali-2.0.5.jar c:\classout/ -o c:\receiver.dex
而後使用dex2jar命令將dex變成jar
用法:dex2jar receiver.dex
這時候咱們就產生了修改以後的jar,咱們將這個jar替換ReceiverDemo中的jar,而後運行結果:
成功顯示了。咱們的MyReceiver接收到了BtnReceiver中發送出來的廣播了。
問題:
在這個過程當中可能使用一些命令的時候會出現問題:
這個是class版本號不對,須要修改一下Eclipse中的Java編譯器版本在編譯導出jar就能夠了。
其餘的問題我這裏沒有遇到了。若是在開發的過程當中遇到問題,記得回覆留言,我儘可能解答一下~~
一、關於上面說到的問題,就是GA包中的類重複的問題,再次在說明一下,那個是個誤區,咱們自定一個Receiver也是能夠的,不須要類名必須是:CampaignTrackingReceiver,因此有同窗若是用到這個類的話,必定要記得,不要在入這個誤區了。
二、關於修改jar中的內容,其實用途仍是不少的,可是不是正規的解決方法,這個有點偏向於破解的方向了,這個是不符合開發原則的,這裏說明一下就是爲了多一條解決問題的辦法,並且對逆向領域的一種知識補充,這個內容對逆向領域用處仍是很大的。
三、關於這種方式使用與全部Java編寫的程序,這裏可能偏向於Android移動端了,可是若是JavaWeb中遇到這樣的問題,也是可使用這種方式解決的,不只僅侷限於Android方向。