关于Angry Birds不能在我的板子上执行的探索

    Angry Birds安装后,运行后提示:Unfortunately, Angry Birds has stopped. 虽然没做过android开发,但我还是先尝试做一下android下的调试,为以后打打基础。

    1、查log信息:

    Android下查看log使用logcat工具(参考http://fins.iteye.com/blog/141021)。

    logcat输出:

E/AndroidRuntime( 2443): FATAL EXCEPTION: main
E/AndroidRuntime( 2443): java.lang.UnsatisfiedLinkError: Couldn't load angrybirds: findLibrary returned null
E/AndroidRuntime( 2443):        at java.lang.Runtime.loadLibrary(Runtime.java:365)
E/AndroidRuntime( 2443):        at java.lang.System.loadLibrary(System.java:535)
E/AndroidRuntime( 2443):        at com.rovio.ka3d.App.onCreate(App.java:29)
E/AndroidRuntime( 2443):        at android.app.Activity.performCreate(Activity.java:4465)
E/AndroidRuntime( 2443):        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
E/AndroidRuntime( 2443):        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1919)
E/AndroidRuntime( 2443):        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1980)
E/AndroidRuntime( 2443):        at android.app.ActivityThread.access$600(ActivityThread.java:122)
E/AndroidRuntime( 2443):        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1146)
E/AndroidRuntime( 2443):        at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime( 2443):        at android.os.Looper.loop(Looper.java:137)
E/AndroidRuntime( 2443):        at android.app.ActivityThread.main(ActivityThread.java:4340)
E/AndroidRuntime( 2443):        at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime( 2443):        at java.lang.reflect.Method.invoke(Method.java:511)
E/AndroidRuntime( 2443):        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
E/AndroidRuntime( 2443):        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
E/AndroidRuntime( 2443):        at dalvik.system.NativeStart.main(Native Method)

可以看出系统在加载一个库文件时出现错误:Couldn't load angrybirds,这里我想应该是俩个意思:1、这个库不存在;2、库的格式不对。最初我是按第一个意思理解,而且没看出库的名字是什么,现在看来应该是libangrybirds.so。既然不知道程序加载哪个库文件,那就想办法跟踪系统调用。

    2、跟踪系统调用

    linux下跟踪系统调用可以使用strace,android下也有相应的工具,我的sdk已经自带了strace,省去的编译的麻烦。但strace要在命令行下执行,因此需要找到手动启动应用的方法。

    3、手动启动程序

    搜索了一下google,android手动启动应用要使用am工具,参考http://tech.it168.com/a2009/0529/579/000000579028.shtml。

    am的简单用法是:am start PackageName/ActivityName。PackageName和ActivityName在AndroidManifest.xml中定义,因此解压apk包,找到angry birds的AndroidManifest.xml,但这个xml居然是个二进制文件,应该是加扰过的,需要反编译。

    4、反编译

    参考http://lytsing.org/wiki/android/decompile.html,我下载了里面的AXMLPrinter2.jar,在pc上执行java -jar AXMLPrinter2.jar AndroidManifest.xml > AndroidManifest2.xml,得到xml的源码如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest
	xmlns:android="http://schemas.android.com/apk/res/android"
	android:versionCode="2110"
	android:versionName="2.1.1"
	android:installLocation="0"
	package="com.rovio.angrybirds"
	>
	<application
		android:label="@7F030001"
		android:icon="@7F020000"
		android:debuggable="false"
		>
		<activity
			android:theme="@android:01030007"
			android:name="com.rovio.ka3d.App"
			android:launchMode="2"
			android:screenOrientation="0"
			android:configChanges="0x000004A0"
			>
			<intent-filter
				>
				<action
					android:name="android.intent.action.MAIN"
					>
				</action>
				<category
					android:name="android.intent.category.LAUNCHER"
					>
				</category>
			</intent-filter>
		</activity>
		<activity
			android:theme="@android:01030007"
			android:name="com.burstly.lib.component.networkcomponent.burstly.VideoPlayerActivity"
			android:configChanges="0x000000B0"
			>
		</activity>
		<activity
			android:theme="@android:01030007"
			android:name="com.burstly.lib.component.networkcomponent.burstly.BurstlyFullscreenActivity"
			android:configChanges="0x000000B0"
			>
		</activity>
		<activity
			android:name="com.google.ads.AdActivity"
			android:configChanges="0x00000FB0"
			>
		</activity>
		<provider
			android:name="com.greystripe.android.sdk.AdContentProvider"
			android:exported="false"
			android:multiprocess="true"
			android:authorities="com.rovio.ka3d.AdContentProvider"
			>
		</provider>
		<activity
			android:name="com.greystripe.android.sdk.AdView"
			android:configChanges="0x000000B0"
			>
			<intent-filter
				>
				<category
					android:name="android.intent.category.LAUNCHER"
					>
				</category>
			</intent-filter>
		</activity>
		<activity
			android:name="com.millennialmedia.android.MMAdViewOverlayActivity"
			>
		</activity>
		<activity
			android:theme="@android:01030007"
			android:name="com.millennialmedia.android.VideoPlayer"
			android:configChanges="0x000000B0"
			>
		</activity>
		<supports-screens
			android:anyDensity="true"
			android:smallScreens="true"
			android:normalScreens="true"
			android:largeScreens="true"
			>
		</supports-screens>
		<activity
			android:theme="@android:01030007"
			android:name="com.burstly.lib.component.networkcomponent.jumptap.JumptapActivity"
			android:configChanges="0x000000B0"
			>
		</activity>
	</application>
	<uses-permission
		android:name="android.permission.INTERNET"
		>
	</uses-permission>
	<uses-permission
		android:name="android.permission.ACCESS_WIFI_STATE"
		>
	</uses-permission>
	<uses-permission
		android:name="android.permission.ACCESS_COARSE_LOCATION"
		>
	</uses-permission>
	<uses-permission
		android:name="android.permission.ACCESS_NETWORK_STATE"
		>
	</uses-permission>
	<uses-permission
		android:name="android.permission.READ_PHONE_STATE"
		>
	</uses-permission>
	<uses-permission
		android:name="android.permission.WRITE_EXTERNAL_STORAGE"
		>
	</uses-permission>
	<uses-sdk
		android:minSdkVersion="4"
		android:targetSdkVersion="13"
		>
	</uses-sdk>
</manifest>

    可以看出其PackageName和ActivityName分别为:com.rovio.angrybirds和com.rovio.ka3d.App。

    5、继续strace追踪

    使用am执行:am start com.rovio.angrybirds/com.rovio.ka3d.App,可以看到触摸屏上出现同样的提示:Unfortunately, Angry Birds has stopped. 于是加上strace执行:strace am start com.rovio.angrybirds/com.rovio.ka3d.App,却提示:

execve("/system/bin/am", ["am", "start com.rovio.angrybirds/com."...], [/* 20 vars */]) = -1 ENOEXEC (Exec format error)
write(2, "strace: exec", 12strace: exec)            = 12
write(2, ": ", 2: )                       = 2
write(2, "Exec format error", 17Exec format error)       = 17
write(2, "\n", 1
)                       = 1
exit_group(1)                           = ?
strace不能启动am。继续查了一下am,发现am其实是个脚本:

# Script to start "am" on the device, which has a very rudimentary
# shell.
#
base=/system
export CLASSPATH=$base/framework/am.jar
exec app_process $base/bin com.android.commands.am.Am "$@"
那么,直接修改exec为exec strace -f(-f为追踪fork的子进程)。于是,strace成功输出系统调用过程。
    6、strace分析

    一般来说,如果是动态库不存在,系统会返回ENOENT错误,但查找了strace的所有输出,没发现哪个so存在ENOENT的错误返回,甚至没找到跟angry birds有关的so调用,我想可能是strace在追踪android应用时,对虚拟机的调用捕获的不完整。但其中有一个打开logging.properties的ENOENT的错误,很值得注意。

    7、logging.properties

    这个文件是jdk的日志配置文件(参考http://qingzuochen.iteye.com/blog/616151)。按照文章中的配置,程序执行后确实在/目录下生成的SSLog0.log,可惜内容是空的,没写入任何log信息。

    8、最终答案:ARM与MIPS

    也许经验丰富的人早就看出问题的所在了,我的板子是个MIPS的方案,而android现在只提供了arm的编译器,软件商也只提供了基于arm的jni本地版本,所以网上下载的大多数游戏在我的MIPS CPU上不能运行是再正常不过的事情了,而我却绕了这么大一个圈子,最后看到apk下的so是放在arm文件夹下,才想起这个事情,这也算是初入android平台的教训吧。好消息在这儿:http://mobile.csdn.net/a/20120417/2804671.html

你可能感兴趣的:(exception,android,jni,NetWork,工具,encoding)