當 Navigation 設定成 Translucent mode 時
snackbar 會跟 navigation bar 重疊
不知道為啥 Google 設計 design library 時沒考慮到這件事
要顯示 snackbar 時,改動 layout parameter
當 Navigation 設定成 Translucent mode 時
snackbar 會跟 navigation bar 重疊
不知道為啥 Google 設計 design library 時沒考慮到這件事
要顯示 snackbar 時,改動 layout parameter
昨天為了讓 Xcode 升到最新版
終於讓 2011" MBA 去升 Yosemite
系統變慢是正常的
Android Studio 結束後有 java zombie process
而且整個記憶體吃很兇
不過最讓我無法忍受的是 Android Studio 的字型變得超醜
搞了半天原來是 Java 7/8 的問題 依據官方的網頁
他裡面有寫要 export STUDIO_JDK
不過我試的結果是直接裝完 java 6 他就會自動去吃了
Apple Java 6 link
用了 Java 6 後
Android Studio 的速度跟吃 RAM 都變正常一點了
今天看到有人在討論的工具 library
如他的名字, 他是拿來試毒氣的金絲雀
主要是把 MAT (Memory Analyzer) 做進去 application level
dependencies {
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3'
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3'
}
PS. 我的 build.gradle 一直少加了
repositories {
mavenCentral()
}
結果 dependencies 一直出問題
加了後,他會自己去抓 library 了
public class ExampleApplication extends Application {
@Override public void onCreate() {
super.onCreate();
LeakCanary.install(this);
}
}
他埋了一個 Activity Watch 在 Application level
所以當你的 Activity finish() 了, 一但 Activity 沒有被正確回收
他就在背景做 heap dump
利用 Eclipse 的 MAT(Memory Analyzer) 去分析是誰 block 住
activity 這個 reference 是誰造成 memory leak
然後他會在 notification dump 出 memory leak 的結果
拉下來點開就有一個分析的畫面跟你說哪邊 memory leak
可以隨時利用他
refWatcher = LeakCanary.install(this);
寫個 getter 把 refWatcher export 出來
RefWatcher refWatcher = ExampleApplication.getRefWatcher(getActivity());
然後監控你要的變數
refWatcher.watch(schrodingerCat);
薛丁格的貓 被 clear 掉,卻沒有正常被 gc 掉的話
就會觸發 notification
另外因為 heap dump 需要幾秒鐘
所以會等一下才跑出來
Put this into ~/.gradle/gradle.properties
RELEASE_STORE_FILE={path to your keystore}
RELEASE_STORE_PASSWORD=*****
RELEASE_KEY_ALIAS=*****
RELEASE_KEY_PASSWORD=*****
注意!RELEASE_STORE_FILE 的路徑要是絕對路徑 Android Studio 很笨的會把 ~/.... 串起來, 然後找不到
signingConfigs {
release {
storeFile file(RELEASE_STORE_FILE)
storePassword RELEASE_STORE_PASSWORD
keyAlias RELEASE_KEY_ALIAS
keyPassword RELEASE_KEY_PASSWORD
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
ref: StackOverflow
解決了一個困擾我三個月的事...
gradle 可以把 src code 分成不同的目錄
然後可以用 build variants 分別去要不要 include 這個東西
android.sourceSets.main {}
android.sourceSets.XXX {}
因為我們現在開發只會用到 XXX
main 也被污染了, 一定要用到 XXX 裡的 code
每次 import project 時,我的 Mac 總是會選到 XXX 的 build variants
所以我的 Android Studio 可以 build 出來
用指令 gradle build 也是正常...
可是其它人的 Windows 總是會選到 main 的那個 build variants
所以他們總是 build 不過
(不過我重灌後的 Windows 上竟然可以!?)
只能改 gradle 把 XXX 裡的目錄加到 main 裡
可是這樣 Project view 時沒辦法把 src set 切開看,很醜
... 反正結論就是 UI 上把 build variant 選成 XXXDebug 就好了
害我為了要看不同 src set local 的 gradle 檔要跟別人不一樣
(只有我用 Mac)
今天為啥會解決這件事呢...
因為我的 Android Studio project 突然爛了
重 import source set 竟然跑回 main 了
而且怎弄都是這樣
才又把 windows 上的 iml 檔拿來 diff
靈機一動想到這回事
原來只是我運氣好(!?) ... -___-
這鳥東西竟然困擾我三個月
幹!
太蠢了,寫起來記錄
新的 build 系統加了 applicationId 這東西
簡單的說, 他要解決不同版本 (free/pro) 如何產出 apk 的問題
例如說兩個版本
在舊的 build tool 上, 要把 AndroidManifest.xml 分別用不用的 packageName 分開
… 想到就很痛苦
新的 build 系統讓 source code 幾乎都不改的情形下
只修改 .gradle 檔
app/build.gradle:
productFlavors {
pro {
applicationId = "com.example.my.pkg.pro"
}
free {
applicationId = "com.example.my.pkg.free"
}
}
buildTypes {
debug {
applicationIdSuffix ".debug"
}
}
....
注意的點在於,雖然不用改 manifest 裡的 pkg name
可是實際上 package name 已經改了
$ aapt d badging app-release.apk
package: name='com.example.my.pkg.free' versionCode='1' versionName='1.0' platformBuildVersionName=''
sdkVersion:'15'
targetSdkVersion:'20'
如果是直接指定 component 的情形下,要小心
adb shell am start -n com.example.my.pkg/.MainActivity 已經無法使用
要改成
adb shell am start -n com.example.my.pkg.free/com.example.my.pkg.MainActivity
build.gradle
加入
allprojects {
gradle.projectsEvaluated {
tasks.withType(JavaCompile) {
options.compilerArgs << "-Xbootclasspath/p:$projectDir/libs/hidden.jar:$projectDir/libs/hidden2.jar"
}
}
}
BSP 在 resource 會使用 product="XXXX" 去分別不同的 target
例如 phone / tablet
在 Eclipse 時代還相安無事
可是 gradle 根本沒有考慮這個情形
(看了一下 source code, 大概吧?)
regex saved my life again !
find res/ -name strings.xml | xargs -n 1 sed -i "" -E '/product="tablet"/d'
Tested in KRT16M / KOT49H
Follow the steps here
http://source.android.com/source/building.html
get source code Version
get nexus driver
fix what's missing in nexus driver
link
yes, pull the binary from stock ROM first
If you didn't do that, your SIM cannot be used
(optional) get /system/media/bootanimation.zip Because AOSP android doesn't have nexus animation
(ADD: 2013/11/29 16:55) add Network Location Provider for GMS
link
Fixed Wireless GPS issues. Changed "config_locationProviderPackageNames" from "com.google.android.location" to "com.google.android.gms" in frameworks/base/core/res/res/values/config.xml
start to build
$ source build/envsetup.sh
$ lunch
=> Press AOSP hammerhead userdebug
$ make clobber
$ make -j 4
flash custom recovery (CWM or TWRP)
flash everything other than recovery
fastboot reboot bootloader
Press VOL-UP than power button to enter recovery mode
Choose Advanced -> sideload mode, if you are using TWRP
$ adb sideload gapps
gapps link http://forum.xda-developers.com/showthread.php?t=2397942
$ adb sideload stock_boot_animation or
adb push bootanimation.zip into /system/media/bootanimation.zip
do a factory reset
(ADD: 2013/12/19 16:07)
fix green line issue in camcorder KOT49H (KRT16M has this issue?)
Replace /system/lib/libmmcamera_interface.so by stock one
link
Have fun!
在找 OnSharedPreferenceChangeListener 範例抄時找到這個
SharedPreferences keeps listeners in a WeakHashMap. This means that you cannot use an anonymous inner class as a listener, as it will become the target of garbage collection as soon as you leave the current scope.
SharedPreferences.onSharedPreferenceChangeListener not being called consistently
靠... 這很容易踩到啊 =_=
plurka 廣告設計得太爛,不要怪我對你不義啊
記錄一下
adb shell mount -o rw,remount /system
adb push hosts.for.mobile.txt /etc/hosts
adb reboot
refs: xda
public class L {
private static boolean BUILDCONFIG_DEBUG = false;
static {
try {
Class<?> c = Class.forName("com.helloworld.BuildConfig");
Field field = c.getField("DEBUG");
BUILDCONFIG_DEBUG = field.getBoolean(null);
} catch (NoSuchFieldException e) {
} catch (ClassNotFoundException e) {
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
}
}
}
if (isInEditMode()) { // put some item here }這樣在 layout editor 就可以看到,而不是空空的一片
android.app.ActivitManager
android.content.Intent
android.media.AudioManager
android.media.AudioSystem
android.text.TextUtils
$ jar cvf ~/hidden.jar android
$ cat classlist.txt
android.app.ActivitManager
android.content.Intent
android.media.AudioManager
android.media.AudioSystem android.text.TextUtils
$ unzip classes-full-debug.jar -d xxx; cd xxx; cat ../classlist.txt | sed 's/./\//g' | sed 's/$/.class/' | perl -ne '@ = glob $; print "$ " for @;' | xargs jar cvf ../hidden.jar