本节书摘来自异步社区《Android 应用案例开发大全(第二版)》一书中的第6章,第6.7节获取第三方程序中可调用的窗口,作者李宁

6.7 获取第三方程序中可调用的窗口
Android开发权威指南(第二版)
第X问1 源代码目录:src/ch06/InvokeSinaWeibo

现在很多程序中使用的功能并未包含在程序本身,都是通过各种插件方式获得的其他程序的资源。例如,经常会使用到的“分享”功能就是调用了系统中所有可以处理某类资源的窗口来实现的,如果这样的窗口多于一个,就会显示一个选择列表。

如果想利用其他程序中的资源,首先要了解程序对外的接口。但很多程序并没有公开相应的接口,在这种情况下,就需要通过该程序的APK文件获取我们需要的信息。本节就以新浪微博Android客户端分析如何获取第三方程序中可调用的窗口和调用方法。读者可从官方网站(http://weibo.com)下载最新的新浪微博客户端安装包(APK文件)。安装完后应先登录微博再测试本例。

由于APK文件就是ZIP压缩格式文件,所以读者可以随便找一个解压软件将APK文件解开。这里假设APK文件的文件名为sina_weibo.apk,解开sina_weibo.apk文件后,再解压根目录会找到一个AndroidManifest.xml文件,不过该文件是被编译过的,无法使用文本编辑器查看其内容。但可以使用一些工具将其反编译。本节介绍一个简单的工具AXMLPrinter2,该工具用Java编写,是一个jar文件,所以可以在任何支持JDK的操作系统平台上使用。该工具的下载地址如下:

http://android4me.googlecode.com/files/AXMLPrinter2.jar读者也可以在随书光盘的tools目录中找到该工具。

现在将AXMLPrinter2.jar文件与AndroidManifest.xml文件放到一个目录,然后在控制台(终端)进入该目录,并执行如下的命令,将AndroidManifest.xml文件解压为AndroidManifest.txt。

java -jar ./AXMLPrinter.jar ./AndroidManifest.xml > ./AndroidManifest.txt
现在用任何一个文本编辑器打开AndroidManifest.txt,除了引用的资源都变成了十六进制的值外,其他的内容都恢复了原样。

本例会使用sina_weibo.apk的3个功能:显示微博主界面、发布微博(显示空的微博发布窗口)和分享微博(将要发布的文本和图像传入微博发布窗口)。在运行本例之前一定要安装sina_weibo.apk,否则程序会因为没找到相应的窗口而抛出异常。

首先来看如何显示微博主界面。既然显示的是主界面,那么一定是单击程序图标显示的窗口,也就是包含android.intent.action.MAIN的窗口,了解了这些后,马上在AndroidManifest.txt文件中搜索android.intent.action.MAIN,我们会找到一个SplashActivity窗口,这是显示程序封面的窗口,该窗口关闭后,就会显示微博主窗口(带微博列表的窗口),由于在SplashActivity类中需要做一些初始化工作,所以不能直接显示主窗口(MainTabActivity)。

现在搜素SplashActivity窗口的过滤器,会找到如下一个过滤器。我们会发现这个过滤器很眼熟。在6.6.3小节介绍的系统浏览器(Browser)也使用了类似的过滤器,只不过scheme不同,而且也没指定host。

<intent-filter>
  <action
    android:name="android.intent.action.VIEW">
  </action>
  <category
    android:name="android.intent.category.DEFAULT">
  </category>
  <category
    android:name="android.intent.category.BROWSABLE">
  </category>
  <data
    android:scheme="sinaweibo"
    android:host="splash">
  </data>
</intent-filter>

如果读者仔细阅读了6.5节的内容,应该很容易知道如何显示这个过滤器所在的窗口,代码如下。

public void onClick_StartSinaWeibo(View view)
{
  Intent intent = new Intent("android.intent.action.VIEW");
  intent.addCategory("android.intent.category.BROWSABLE");
  intent.setData(Uri.parse(**"**sinaweibo://splash**"**));
  startActivity(intent);
}

现在要找到可以发布新微博的窗口,继续搜索AndroidManifest.txt文件的内容(主要搜索标签),会找到一个叫com.sina.weibo.intent.action.NEW_BLOG的Action,对应的窗口类是EditActivity。现在用下面的代码测试一下,发现完全可以显示微博的发布界面。

public void onClick_PostWeibo(View view)
{
  Intent intent = new Intent("com.sina.weibo.intent.action.NEW_BLOG");
  startActivity(intent);
}

最后要实现“分享”功能,这个功能需要使用前面涉及的一个通用的Action,就是Intent.ACTION_SEND(android.intent.action.SEND),分享微博的代码如下:

public void onClick_Share(View view)
{
  Intent intent = new Intent("android.intent.action.SEND");
  // 设置要分享的文本
  intent.putExtra(Intent.EXTRA_TEXT, "今天气温很低,注意保暖哦,亲!");
  // 必须指定Mime Type为text/plain
  intent.setType("text/plain");
  startActivity(intent);
}

如果读者还想确定一下的话,可以在AndroidManifest.txt文件中搜索android.intent.action.SEND,会找到两个指定该Action的过滤器。一个设置了Mime Type为“text/plain”,用于处理文本数据;另一个Mime Type为“image/*”,用于处理文本和图像数据。如果想同时处理文本和图像数据(发布带图像的微博),可以使用下面的代码。

Intent intent = new Intent("android.intent.action.SEND");
intent.putExtra(Intent.EXTRA_TEXT, "今天气温很低,注意保暖哦,亲!");
// 需要指定图像文件的绝对路径
intent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file:///sdcard/test.jpg"));
// 通常设为Mime Type为image/*
intent.setType("image/*");
startActivity(intent);

如果使用上面的代码可能会有多个窗口符合条件,这样就会显示选择列表。如果不想显示选择列表,直接调用新浪微博的分享微博界面,可以使用下面的代码。

public void onClick_ShareWithSinaWeibo(View view)
{
    Intent intent = new Intent("android.intent.action.SEND");
    // 直接指定Package Name和Activity Class Name
    intent.setClassName("com.sina.weibo", "com.sina.weibo.EditActivity");
  intent.putExtra(Intent.EXTRA_TEXT, "今天气温很低,注意保暖哦,亲!");
  intent.setType("text/plain");
  startActivity(intent);
}

注意

使用显式方式调用EditActivity,也需要指定android.intent.action.SEND,这是因为在微博程序内部检测了Action,如果不为Intent对象指定Action,则Action为null,系统就不会继续处理传递的数据了。如果想通过显式方式分享文本和图像,对Intent对象的设置与隐式方式完全一样。
如果读者想调用系统内置的程序,并且没有Android源代码,也可以从Android模拟器上使用adb pull命令下载相应的APK文件,并按着本节的方法进行分析。