上次给退役的一加1刷了lineage-16.0后,本来一直使用的挺好,当个备用怀旧游戏机还挺流畅的,最近拿来做一些安卓调试时突然发现logcat没反应了,AndroidStudio里一片空白,adb设备状态一切正常,尝试adb logcat以及adb shell后logcat,发现会提示“logcat read failure”这个错误,查了半天,尝试了个各种手段,root su进到/system/bin下看logd完好无埙,又看有人说是selinux的问题,ls -Z检查了logd的权限:u:object_r:logd_exec:s0,发现也没问题。然后又以为是装Magisk装的把系统搞坏了,于是有恢复出厂了一次,结果发现错误依旧!最后突然想到之前的系统镜像貌似是不知道哪个瞎八网站上下载的,本来里面就内置了一堆乱起八糟的app,会不会是不靠谱的rom作者把重要功能给改坏了?于是废了半天劲找了个lineage官方的旧版本系统镜像:https://lineageosroms.com/bacon/#installing-lineageos-from-recovery 然后又重刷了一次机,果然,纯原版的镜像是没有问题的,logcat恢复正常了。
android
AndroidStudio制作Unity 2020.3插件的新坑
在Unity还是4.x 5.x的时代,为了做一些安卓原生功能,如获取电量,wifi信号强度等功能,或者是为了接入某些原生SDK,经常需要制作Unity的Android原生插件,当时基本就是基于Unity的安卓classes.jar制作plugin.jar,然后自定义AndroidManifest.xml,一起放到Unity项目的Assets/Plugins/Android下,然后Build安卓apk即可,简单粗暴。最近又有了做安卓插件的需求,这次换上了2020版的Unity,本以为还是当年熟悉的操作,没成想来了个大人,时代变了,踩了不少新坑:
首先,当年好像还是用Eclipse做Android开发,现在早就是Android Studio的天下了,我用的版本是:Chipmunk 2021.2.1 Patch 2,按着网上找到的教程(对,很久没用了,都快忘了怎么建项目了),创建了Android Library项目,又从Unity的“D:\Program Files\Unity\Hub\Editor\2020.3.30f1c1\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Release\Classes”位置,拿到了熟悉的classes.jar,注意这里有一些变量,比如mono,现在还有了il2cpp的选择,Release对应还有Debug,根据实际情况进行选择吧。然后,随便写了几个简单的静态方法,Unity C#里调用了下,nice,没有问题,于是开始进行下一步,自定义入口activity,然后就开始踩坑了:
Continue reading…Android Studio使用override自动生成方法形参名错误问题
使用Android Studio写Java,Kotlin代码时,经常会用到Ctrl+O来实现接口的方法,今天偶然发现AS自动添加的代码变成了这样:
1 2 3 4 5 6 7 8 9 10 11 | val textWatcher = object: TextWatcher { override fun afterTextChanged(p0: Editable?) { } override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) { } override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) { } } |
虽然不影响功能,但是看起来就很费劲了,形参名不具有自解释性了,记得之前一直是没问题的,简单查了下发现,原来是之前更新了platform sdk后,没有选择同时安装source,在SDK Manager中把当前正在用的target api版本对应的source安装上,再次执行同样操作就可以了:
Continue reading…Android Studio带C++项目提示More than one file was found with OS independent path问题修正
近日,在将一个旧Android Studio项目(带native c/c++)升级了新版本gradle 4.0.1后(Android Studio版本4.0.1),发现重新clean再构建时,提示:
More than one file was found with OS independent path ‘lib/armeabi-v7a/xxx.so’. If you are using jniLibs and CMake IMPORTED targets, see https://developer.android.com/studio/preview/features#automatic_packaging_of_prebuilt_dependencies_used_by_cmake
虽然一开始也是一脸茫然,但既然提示信息里都提供了连接了,那就看一下吧,顺带一提,给出的链接我写这篇博文的时候并不是最终信息位置,最终链接在这里:https://developer.android.com/studio/releases/gradle-plugin#cmake-imported-targets ,仔细阅读了一下,发现实际上是从gradle 4.0开始就对jni的预编译依赖引用方式做出了修改:
Continue reading…解决Android NDK编译FFmpeg 4.2.2的x86 cpu版时的问题
老规矩,编译环境:Win10 1903,WSL ubuntu,ndk r20b,FFmpeg 4.2.2,首先分享下编译脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | #!/bin/bash make clean export NDK= /home/kres/android-ndk-r20b TOOLCHAIN=$NDK /toolchains/llvm/prebuilt/linux-x86_64/ API=21 function build_android { echo "Compiling FFmpeg for $CPU" . /configure \ --prefix=$PREFIX \ -- enable -neon \ -- enable -hwaccels \ -- enable -gpl \ -- enable -postproc \ -- enable -shared \ -- enable -jni \ -- enable -mediacodec \ --disable-decoders \ -- enable -decoder=h264_mediacodec \ -- enable -decoder=vp9 \ -- enable -decoder=h264 \ -- enable -decoder=mpeg4 \ -- enable -decoder=aac \ -- enable -decoder=aac_latm \ -- enable -decoder=mjpeg \ -- enable -decoder=png \ -- enable -decoder=mpeg4_mediacodec \ --disable-encoders \ -- enable -encoder=vp9_vaapi -- enable -encoder=h264_nvenc -- enable -encoder=h264_v4l2m2m -- enable -encoder=hevc_nvenc \ --disable-demuxers \ -- enable -demuxer=rtsp -- enable -demuxer=rtp -- enable -demuxer=flv -- enable -demuxer=h264 \ --disable-muxers \ -- enable -muxer=rtsp -- enable -muxer=rtp -- enable -muxer=flv -- enable -muxer=h264 \ --disable-parsers \ -- enable -parser=mpeg4video -- enable -parser=aac -- enable -parser=h264 -- enable -parser=vp9 \ --disable-protocols \ -- enable -protocol=rtmp -- enable -protocol=rtp -- enable -protocol=tcp -- enable -protocol=udp \ --disable-bsfs \ --disable-indevs -- enable -indev=v4l2 \ --disable-outdevs \ --disable-filters \ --disable-postproc \ --disable-static \ --disable-doc \ --disable-ffmpeg \ --disable-ffplay \ --disable-ffprobe \ -- enable -avdevice \ --disable-doc \ --disable-symver \ --cross-prefix=$CROSS_PREFIX \ --target-os=android \ --arch=$ARCH \ --cpu=$CPU \ --cc=$CC \ --cxx=$CXX \ -- enable -cross-compile \ --sysroot=$SYSROOT \ --extra-cflags= "-Os -fpic $OPTIMIZE_CFLAGS" \ --extra-ldflags= "$ADDI_LDFLAGS" \ $ADDITIONAL_CONFIGURE_FLAG make clean make -j6 make install echo "The Compilation of FFmpeg for $CPU is completed" } #armv8-a ARCH=arm64 CPU=armv8-a CC=$TOOLCHAIN /bin/aarch64-linux-android $API-clang CXX=$TOOLCHAIN /bin/aarch64-linux-android $API-clang++ SYSROOT=$NDK /toolchains/llvm/prebuilt/linux-x86_64/sysroot CROSS_PREFIX=$TOOLCHAIN /bin/aarch64-linux-android- PREFIX=$( pwd ) /android/ $CPU OPTIMIZE_CFLAGS= "-march=$CPU" build_android #armv7-a ARCH=arm CPU=armv7-a CC=$TOOLCHAIN /bin/armv7a-linux-androideabi $API-clang CXX=$TOOLCHAIN /bin/armv7a-linux-androideabi $API-clang++ SYSROOT=$NDK /toolchains/llvm/prebuilt/linux-x86_64/sysroot CROSS_PREFIX=$TOOLCHAIN /bin/arm-linux-androideabi- PREFIX=$( pwd ) /android/ $CPU OPTIMIZE_CFLAGS= "-mfloat-abi=softfp -mfpu=vfp -marm -march=$CPU " build_android #x86 ARCH=x86 CPU=x86 CC=$TOOLCHAIN /bin/i686-linux-android $API-clang CXX=$TOOLCHAIN /bin/i686-linux-android $API-clang++ SYSROOT=$NDK /toolchains/llvm/prebuilt/linux-x86_64/sysroot CROSS_PREFIX=$TOOLCHAIN /bin/i686-linux-android- PREFIX=$( pwd ) /android/ $CPU OPTIMIZE_CFLAGS= "-march=i686 -mtune=intel -mssse3 -mfpmath=sse -m32" build_android #x86_64 ARCH=x86_64 CPU=x86-64 CC=$TOOLCHAIN /bin/x86_64-linux-android $API-clang CXX=$TOOLCHAIN /bin/x86_64-linux-android $API-clang++ SYSROOT=$NDK /toolchains/llvm/prebuilt/linux-x86_64/sysroot CROSS_PREFIX=$TOOLCHAIN /bin/x86_64-linux-android- PREFIX=$( pwd ) /android/ $CPU OPTIMIZE_CFLAGS= "-march=$CPU -msse4.2 -mpopcnt -m64 -mtune=intel" build_android |
修改Android签名证书keystore的密码、别名alias以及别名密码
之前在测试Eclipse ADT的Custom debug keystore自定义调试证书的时候,发过一篇关于调试证书规格的博文:Eclipse ADT的Custom debug keystore所需证书规格,提到过自定义调试证书的密码和alias命名以及alias密码都是有规矩的。其实Android应用开发接入各种SDK时会发现,有很多SDK是需要靠package name和keystore的指纹hash来识别的(百度地图SDK、Facebook SDK等等…),这样如果使用默认自动生成的debug keystore的话就会给开发调试工作带来一些麻烦。这时可以通过修改正式的release keystore,生成一份“遵守规矩”的临时自定义调试证书给开发时用,就方便多了,具体方法如下:
一个小问题,Unity游戏打包Android运行时锁屏游戏退出的修正
记个小问题,今天在看一个Unity的游戏demo时,发现打出的安卓包在运行时,一旦屏幕锁屏(并没有开wakelock屏幕常量),游戏便会自动退出,看了下logcat,也没有什么异常崩溃的记录,只有一个WIN DEATH,开始以为是onPause之类进后台做了什么操作导致的进程结束,最后发现其实是自定义的Android Manifest中configChanges里响应了不必要的项目,导致的退出:
原始:
1 | < activity android:name = "net.k_res.gotyedemo.MainActivity" android:label = "@string/app_name" android:screenOrientation = "landscape" android:configChanges = "fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|uiMode|touchscreen" > |
去掉无用项修改为:
1 | < activity android:name = "net.k_res.gotyedemo.MainActivity" android:label = "@string/app_name" android:screenOrientation = "landscape" android:configChanges = "orientation|navigation|screenSize|keyboard|keyboardHidden" > |
后锁屏正常,游戏不再退出
Android Studio通过CMake编译原生代码运行时符号(函数)丢失的问题
由于新版Android Studio的native调试功能实在是太好用了,所以试了下把旧版Cococs2d-x项目(大概是2.x版本吧)重建Android Studio项目。花了很长时间添加各种source,static library,prebuilt library以后,终于项目可以在Android Studio的cmake编译工具下成功编译链接并生成.so了,迫不及待的一运行,发现直接闪退,检查后发现是”Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeOnResume”这个cocos2d-x的jni函数没有找到!
初步检查了下,发现cmake编译出的cocos2d静态库.a中存在这个函数符号,但是最终生成的.so中确实是没有这个函数(使用ndk toolchain里面的nm),于是想到应该是链接时认为这个符号没有代码调用,被stripe掉了。
后来又仔细看了下Android.mk,发现玄机貌似在于
LOCAL_WHOLE_STATIC_LIBRARIES += cocos2dx_static
对cocos2dx的静态库使用了WHOLE的链接方式,于是开始查找同样功能在cmake中的实现方式,最后查的结果如下:
Continue reading…
quick-cocos2d-x-2.2.6的CCHTTPRequest在Android 5.0+系统上的崩溃问题
虽然是比较旧版本的quick了,但也许会有人需要此版本的项目重新编译运行在新版本Android系统上,或是有遇到类似问题可以供参考,所以此篇文章记录解决这个问题的方法。
报错的现象是在使用“network.createHTTPRequest”进行http访问的时候(也就是lua调用的CCHTTPRequest类),出现native crash,大致异常信息是“use of deleted local reference XXXX”,看下logcat中的调用栈信息可以发现是在CCHTTPRequest::setRequestMethodJava调用时导致的。
关于这个问题我以前曾经写过相关的文章:
[译]Android冰淇淋三明治ICS(4.0+)JNI局部引用的变化 – http://blog.k-res.net/archives/1525.html
Android NDK中多线程JNI的local reference释放问题 – http://blog.k-res.net/archives/1794.html
基本问题就是高版本安卓系统的JNI部分有一些关于Local Reference的改动,导致曾经没问题的JNI逻辑在新版本系统上crash,先放出修改吧,修改
lib\cocos2d-x\external\extra\platform\android\CCHTTPRequestAndroid.cpp这个文件中Android平台下对于CCHTTPRequest的实现,找到getClassID_,修改为如下所示:
Continue reading…
Android获取未经启动器launcher主题theme修改过的应用图标icon
今天说的这个问题是这样的,在Android App中获取自身或其它某个包名应用的图标时,取到的Drawable并不是实际资源的图标图,而是被启动器或者主题“风格化”后的版本,比如我的一加一的CM13s系统默认主题下启动器中的应用图标会被自动P成这样:
其它如MIUI等也会有类似操作,而无论你是用这样:
1 | getPackageManager().getApplicationIcon(getApplicationInfo()); |
还是这样:
1 2 3 4 5 6 7 8 9 | // Unity应用默认的图标res名叫app_icon,AS会叫ic_launcher,看下manifest中指定的资源ID串就知道了 int iconId = getResources().getIdentifier( "app_icon" , "drawable" , getPackageName()); if (iconId> 0 ) { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { dIcon = getResources().getDrawable(iconId, getTheme()); } else { dIcon = getResources().getDrawable(iconId); } } |
取到的都会是修改后的图标图,那么如何取得apk中的原版图标图片呢?答案在此(感谢伟大的google及stackoverflow!):
Continue reading…