一、前言
UnityGoogle PlayGoogleAPK150MAPK300M+UnitySplit Application Binary
二、Demo工程
Demo
Resources
目录和StreamingAssets
目录分别放一张图片。场景如下,
Canvas
节点挂Main.cs
脚本,image
节点显示图片。场景中的
image
节点不要引用图片资源,而是在Main.cs
脚本中动态赋值。Main.cs
脚本代码如下:
using UnityEngine;
using UnityEngine.UI;
public class Main : MonoBehavIoUr {
public Image img;
void Start() {
img.sprite = Resources.Load<Sprite>("bg");
}
}
运行效果如下,可以看到动态加载了图片。
此时我们打包
apk
,如果我们不开启Split Application Binary
,显然,Resources
和StreamingAssets
目录都会打进包内。
三、开启Split Application Binary,打包
Player SettingsPublishing SettingsSplit Application Binary
执行
Build
打包,如下,保存为test.apk
。最终生成的文件如下,可以看到有一个
apk
和一个obb
文件。四、什么文件进入了obb中
obbOpaque Binary Blobapk7zassetsobbapk
往里进,看到了
pic2.png
,这个就是Unity
中StreamingAssets
目录中的pic2.png
,也就是说,StreamingAssets
目录中的文件,会被丢到obb
文件中。那
Resources
目录的资源,也是在obb
中 吗?我们往里进,可以看到在assets\bin\Data
目录中有个data.unity3d
文件,我猜,我们Resources
目录中的那张bg.png
就在这里面。我用
AssetStudioGUI.exe
无法反出这个data.unity3d
文件,那么,我们就用反证法来证明Resources
目录文件会在obb
文件中吧。
五、只安装apk,不放obb
apkResourcesbg.pngapk
现在,另一个问题来了,这个
obb
文件,如何使用,放在安卓中的哪个目录呢?
六、放obb文件
obbobbmain..<包名>.obbapkcom.linxinfa.obbtestBundle Version Code2
所以最终
obb
重命名如下:main.2.com.linxinfa.obbtest.obb
把它拷贝到
Android/obb/包名
目录下,如下:七、运行apk闪退
apkadb
D/Activity( 6326): on create,cpu abi: armeabi-v7a,brand: Android
D/updatePackage( 905): version com.linxinfa.obbtest 2
I/Launcher( 905): Deferring update until onResume
V/libnb ( 6326): enter native_bridge2_isSupported /data/app/com.linxinfa.obbtest-1/lib/arm/libmain.so
D/libnb ( 6326): enter native_bridge2_loadLibrary /data/app/com.linxinfa.obbtest-1/lib/arm/libmain.so
D/com.netease.nemu_vapi_android.thread.HttpServer( 842): http server response data: {"errcode":0,"message":"OK"}
D/houdini ( 6326): [6326] Added shared library /system/lib/arm/libaudio_rawdata.so for ClassLoader by Native Bridge.
D/houdini ( 6326): [6326] Added shared library /data/app/com.linxinfa.obbtest-1/lib/arm/libmain.so for ClassLoader by Native Bridge.
V/libnb ( 6326): enter native_bridge2_getTrampoline JNI_OnLoad
D/com.netease.nemu_vapi_android.thread.HttpServer( 842): http server response data: {"errcode":0,"message":"OK"}
I/Mono ( 6326): JNI_OnLoad called
D/com.netease.nemu_android_watchdog_lib.core.Watchdog( 842): upload server response: {"errcode": 100,"errmsg": "ok"}
D/com.netease.nemu_android_watchdog_lib.core.Watchdog( 842): upload result: true
D/ ( 6326): QemuPipestream get vt: 1
D/ ( 6326): QemuPipestream use_vt: 1
D/ ( 6326): HostConnection::get() New Host Connection established 0xbf269540,tid 6326 host arch 0
I/ActivityManager( 523): displayed com.linxinfa.obbtest/com.unity3d.player.UnityPlayerActivity: +285ms
W/InputMethodManagerService( 523): Starting input on non-focused client com.android.internal.view.IInputMethodClient$Stub$Proxy@17cc531 (uid=10015 pid=3699)
I/Unity ( 6326): MemoryManager: Using 'Dynamic Heap' Allocator.
I/Unity ( 6326): check apk path fail,reported:/storage/emulated/0/Android/obb/com.linxinfa.obbtest/main.2.com.linxinfa.obbtest.obb,actual:/data/app/com.linxinfa.obbtest-1/base.apk
I/Unity ( 6326):
I/Unity ( 6326): Illegal usage of unity detected,shutdown unity.
I/Unity ( 6326):
I/Process ( 6326): Sending signal. PID: 6326 SIG: 9
W/Inputdispatcher( 523): channel 'aede570 com.linxinfa.obbtest/com.unity3d.player.UnityPlayerActivity (server)' ~ Consumer closed input channel or an error occurred. events=0x9
E/Inputdispatcher( 523): channel 'aede570 com.linxinfa.obbtest/com.unity3d.player.UnityPlayerActivity (server)' ~ Channel is unrecoverably broken and will be disposed!
I/WindowState( 523): WIN DEATH: Window{aede570 u0 com.linxinfa.obbtest/com.unity3d.player.UnityPlayerActivity}
W/Inputdispatcher( 523): Attempted to unregister already unregistered input channel 'aede570 com.linxinfa.obbtest/com.unity3d.player.UnityPlayerActivity (server)'
W/WindowManager( 523): Force-removing child win Window{8bc567a u0 SurfaceView} from container Window{aede570 u0 com.linxinfa.obbtest/com.unity3d.player.UnityPlayerActivity}
I/ActivityManager( 523): Process com.linxinfa.obbtest (pid 6326) has died
D/ActivityManager( 523): cleanUpApplicationRecord -- 6326
W/ActivityManager( 523): Force removing ActivityRecord{50e4779 u0 com.linxinfa.obbtest/com.unity3d.player.UnityPlayerActivity t547}: app died,no saved state
W/WindowManager( 523): Failed looking up window
W/WindowManager( 523): java.lang.IllegalArgumentException: Requested window android.os.BinderProxy@7d300e9 does not exist
W/WindowManager( 523): at com.android.server.wm.WindowManagerService.windowForClientLocked(WindowManagerService.java:8881)
W/WindowManager( 523): at com.android.server.wm.WindowManagerService.windowForClientLocked(WindowManagerService.java:8872)
W/WindowManager( 523): at com.android.server.wm.WindowState$DeathRecipient.binderDied(WindowState.java:1216)
W/WindowManager( 523): at android.os.BinderProxy.sendDeathNotice(Binder.java:558)
I/WindowState( 523): WIN DEATH: null
I/com.android.server.tabs.TabManagerService( 523): notifyClosing:741: notify tab closed in android as it's closed task com.linxinfa.obbtest,taskId: 547,elapseTime: 372
D/Interception( 523): result: allow,reason: calleePkg is system app,rule: runType===broadcast|||callerPkg===android|||calleePkg===com.mumu.acc|||calleeClass===com.mumu.acc.AccMsgReceiver|||action===uu.intent.action.STOP_ACCELERATE
在同事的提醒下,看到有一句关键的日志:
Illegal usage of unity detected,shutdown unity.
搜索了一下,原来如此:
我们在国内下载
Unity
一般是在 https://unity.cn/ 下载,这里下的,都是中国版的。那么,在哪里下载国际版的
Unity
呢?
八、下载国际版Unity
Unity
九、国际版发布apk+obb
apk+obb
按照同样的规则放好
obb
包,apk
由此,我们得出结论,
Resources
目录的资源也是在obb
文件中。
十、您上传的APK没有经过Zipalign处理
apkobbGoogle Console您上传的APK没有经过Zipalign处理,请对APK 运行 Zipalign 工具,然后重新上传
Android 1.6SDKbuild-tools\26.0.2zipalign
zipalign -v 4 源文件 对齐之后的文件
例:
zipalign -v 4 test.apk test_aligned.apk
十一、Google Play Console后台在哪里上传apk、obb
Google ConsoleAPK
APK
上传成功后,点击这个...
按钮然后选择
上传拓展文件(.obb)
然后上传
obb
就可以啦。十二、结束语
UnityUnity