Android笔记八.Intent对象的使用及.apk反编译

 Intent对象的使用及.apk反编译
    前三节主要学习了Intent对象的作用、属性以及不同Activity之间值的传递,这节将着重学习Intent对象的用法。在我的语音识别项目中,通过使用Inteng对象来启动应用内组件、系统应用程序以及第三方应用程序(如QQ、微信等)。
一、Intent对象开发方法
    首先,我们还是先学习下Intent对象启动组件(应用)有哪几种方法:
1.利用Intent对象的Component属性
    使用这种方法的前提知道组件的或第三方应用程序的包名、类名,来启动应用程序内组件、第三方应用程序。Intent的Component属性需要要接受一个ComponentName对象,一个基本ComponentName需要指定包名和类名,这可以唯一地确定一个组件类。基本格式:
        ComponentName comp=new ComponentName(包名,类名);
        intent.setComponent(comp);
    ComponentName对象包括以下几种构造器:
      a.ComponentName(String pkg,String cls):创建pkg所在包下的cls类所对应的组件(字符串形式)
      b.ComponentName(Context pkg,String cls):创建pkg所在包下的cls类所对应的组件
      c.ComponentName(Context pkg,Class<?>cls):创建pkg所在包下的cls类所对应的组件(上下文)
应用举例:
(1)intent启动自身组件
Intent intent=new Intent();
ComponentName comp=new ComponentName(PocketSphinxDemo.this,help.class );//使用第三种构造器
intent.setComponent(comp);
startActivity(intent);
注意:这里PocketSphinxDemo.this指定的是我们应用程序的包,help.class为包内将要启动的组件类。
(2)intent启动第三方应用程序
Intent intent=new Intent();
intent.setClassName("com.tencent.mobileqq",
                                "com.tencent.mobileqq.activity.SplashActivity");
startActivity(intent);
注意:关于第三方应用程序的包名(com.tencent.mobileqq)、类名()com.tencent.mobileqq.activity.SplashActivity,我们可以通过反编译其.apk获取AndroidManifest.xml文件的"package"属性,以及action声明为MAIN常量的"android:name"属性,具体如何反编译获取我将会在下面文章中详细述说。
(3)intent启动系统程序
    这部分我觉得使用<intent-filter>方法可能会比较好,这里就不说了。
2.利用setClass启动组件
   使用这种方法的前提知道组件的或第三方应用程序的包名、类名,来启动应用程序内组件、第三方应用程序。setClass*为Intent类的成员方法,功能与Intent对象的Component属性一样,都是通过intent指定需要启动的组件。其也有三种形式:
a.setClass(Context packageContext,Class<?>cls):设置该Intent将要启动的组件的对应类
b.setClassName(Context packageContext,String className): 设置该Intent将要启动的组件的对应类名
c.setClassName(String packageName,String className):设置该Intent将要启动的组将的对应类名
    其中,Android应用的Context代表了访问该应用环境信息的接口,而Android应用的包名则作为应用的唯一标识,即Context对象与该应用的包名有一一对应的关系。setClass方法就是指定包名和组件的实现类
应用举例:
(1)intent启动自身组件
Intent intent=new Intent();
intent.setClassName(PocketSphinxDemo.this,help.class );//使用第三种构造器
startActivity(intent);
注意:这里PocketSphinxDemo.this指定的是我们应用程序的包,help.class为包内已经实现了的将要启动的组件类
(2)intent启动第三方应用
Intent intent=new Intent();
intent.setClassName("com.tencent.mobileqq","com.tencent.mobileqq.activity.SplashActivity");
startActivity(intent);
注意:关于第三方应用程序的包名(com.tencent.mobileqq)、类名()com.tencent.mobileqq.activity.SplashActivity,我们可以通过反编译其.apk获取AndroidManifest.xml文件的"package"属性,以及action声明为MAIN常量的"android:name"属性,具体如何反编译获取我将会在下面文章中详细述说。
3.利用intent-filter配置(Intent对象的5个属性)
    Intent的Action、Category属性都是一个普通的字符串,其基本思想是:在发出"意图"的组件中,调用Intent成员方法设置好其计划启动组件的一些特征,然后在接收"意图"组件的AndroidManifest.xml文件中的<intent-filter>配置是否符合"意图"要求,从而确定是否能被启动。其中:
    Action属性代表该Intent所需要完成的一个抽象"动作";
    Category属性用于为Action增加额外的附加类别信息
    Data属性用于向Action属性提供操作的数据,且其接受一个Uri对象
    Type属性用于指定该Data所指定Uri对应的MIME类型,这种MIME类型可以是任何自定义的MIME类型,只要符合abc/xyz格式的字符串即可
    Extras属性用于多个Action之间进行数据交换,即值传递,通常用于不同Activity之间的数据传递交换
    Flags属性用于该Intent添加一些额外的控制旗标,Intent可调用addFlags()方法来为Intent添加控制旗标。
(1)利用intent-filter配置启动系统程序
    由于Android手机中的系统程序,其<intent-filter>属性的设置可以说是通用的,所以使用这种方法比前面的方法要方便可靠。示例代码如下:
启动系统相机
Intent intent=new Intent();
intent.setAction(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA); //启动相机app
startActivity(intent); 
启动浏览器
Uri uri=Uri.parse("http://blog.csdn.net/u012637501"); 
Intent intent=new Intent(); 
intent.setAction(Intent.ACTION_VIEW); 
intent.setData(uri); 
startActivity(intent);
(2)利用intent-filter启动应用自身组件
a.创建一个Intent对象,并自定义字符串设置给intent的属性
Intent intent=new Intent(); //创建一个Intent对象
String data="lee://www.fkjava.org:8888/mypath";    //自定义字符串
Uri uri=Uri.parse(data); //将字符串转换为Uri
intent.setAction(Intent.ACTION_VIEW);
intent.setData(uri); //设置Intent对象Data属性
startActivity(intent);
或者
Intent intent=new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(Uri.parse("lee://www.fkjava.org:8888/mypath"));
startActivity(intent);<span style="background-color: inherit; font-family: 'Times New Roman';">  </span>
b.实现想要启动的一个及以上组件(比如SecondaryActivity)
c.在AndroidManifest.xml中为组件(如Activity)添加一个<Activity>元素并设置<data../>元素中的相关内容
 <data android:mimeType="lee"   
           android:host="www.fkjava.org"   
           android:port="8888"   
           android:path="/mypath"   
          android:pathPrefix=""
          android:pathPattern=""/>  可以全部设置,也可以选择性设置。
经过上述设置,intent就会根据其他组件的<data.../>元素里所能匹配的项依次列出符合intent条件的一系列组件。         

二、Intent对象启动第三方应用
     Intent对象除了能给启动应用自身组件、系统应用,还可以启动第三方应用,比如QQ、微信、文件管理器等。由于第三方应用的<intent-filter.../>属性是各应用开发商自定义的,不能调用Intent预定义的相关属性常量。为了成功启动第三方应用,我们可以利用Intent对象的Component属性或者调用Intent类的setClassName方法,通过指定第三方应用的包名、类名来启动。
    由于第三方应用大部分都是封装好的,为了从AndroidManifest.xml工程文件中获取应用的包名、类名以及获取相关的Java格式源码,我们可以对应用安装包(.apk)进行反编译。
1.搭建反编译环境
(1)Win7 x86
(2)Fedora14或cygwin,即linux编译环境。这里我直接使用cygwin, Cygwin相当于Windows下的Linux环境。具体的安装配置方法配置,详见我这一篇博文http://blog.csdn.net/u012637501/article/details/40480823
2.apk反编译生成程序的XML配置、图片、语言等资源文件

(1)下载上述反编译工具包,打开apk2java目录下的apktool1.4.1文件夹,内含三个文件:aapt.exeapktool.batapktool.jar 

注:里面的apktool_bk.jar是备份的老版本,最好用最新的apktool.jar

(2)切换到apktool1.4.1文件夹,使用apktool.bat工具进行反编译

 

a.切换命令:

b.编译命令:


                                 apktool.bat 命令行解释:apktool.bat   d  -f    [apk文件 ]   [输出文件夹]

c.result文件夹下,反编译的结果:


3.重新打包成apk

    将反编译完的文件重新打包成apk,很简单,输入apktool.bat   b    abc123(你编译出来文件夹)即可,命令如下:


打包apk后的文件在目录C:\HelloAndroid下,生成了两个文件夹:

build

dist

其中,打包生成的HelloAndroid.apk,在上面的dist文件夹下.

4.apk反编译得到Java源代码      

    下载上述反编译工具包,打开apk2java目录下的dex2jar-0.0.9.9文件夹,内含apk反编译成java源码工具,以及源码查看工具。

dex2ja:rapk反编译工具,是将apk中的classes.dex转化成jar文件

jdgui源码查看工具,是一个反编译工具,可以直接查看反编译后的jar包源代码

dex2jar 和 jdgui 最新版本下载,分别见google code:

dex2jar(google code)

jdgui(google code),最新版本请见 官方

(1)首先将apk文件后缀改为zip并解压,得到其中的classes.dex,它就是java文件编译再通过dx工具打包而成的,将classes.dex复制到dex2jar.bat所在目录dex2jar-0.0.9.9文件夹。

(2)在命令行下定位到dex2jar.bat所在目录,运行dex2jar.bat    classes.dex生成classes_dex2jar.jar

(3)进入jdgui文件夹双击jd-gui.exe,打开上面生成的jar包classes_dex2jar.jar,即可看到源代码了,如下图:

HelloAndroid源码在反编译前后的对照如下:

 



      经过以上几步我们就可以成功的对apk安装包进行反编译,获取源码。其实,如果我们只是反编译用来实现Intent启动第三方应用只需操作第二步即可获得安装包的AndroidManifest.xml工程文件。
    如inten启动微信.apk
1.反编译"微信.apk",查看AndroidManifest.xml工程文件获取包名、主Activity类名


2.intent设置
Intent intent=new Intent();
intent.setClassName("com.tencent.mm","com.tencent.mm.app.MMApplication");
startActivity(intent);

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。