android 4.2 系統編譯小結
1、InputManager.java 類問題
由於 InputManager 類路徑及函數都發生了變化,所以用法有所不同
long now = SystemClock.uptimeMillis();
KeyEvent down = new KeyEvent(now, now, KeyEvent.ACTION_DOWN, eventCode,0);
KeyEvent up = new KeyEvent(now, now, KeyEvent.ACTION_UP, eventCode, 0);
4.0 版本:
import android.os.SystemClock;
import android.view.IWindowManager;
import android.view.KeyEvent;
try {
(IWindowManager.Stub.asInterface(ServiceManager
.getService("window"))).injectInputEventNoWait(down);
(IWindowManager.Stub.asInterface(ServiceManager
.getService("window"))).injectInputEventNoWait(up);
} catch (RemoteException e) {
e.printStackTrace();
}
4.2 版本:
import android.os.SystemClock;
import android.view.KeyEvent;
import android.hardware.input.InputManager;
InputManager.getInstance().injectInputEvent(down,
InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
InputManager.getInstance().injectInputEvent(up,
InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
2、NDK jni頭文件路徑變化問題
jni.h 頭文件存放路徑發生變化:
根目錄: libnativehelper\include\nativehelper 下面 【jni.h 及 JNIHelp.h】
注意路徑,否則可能會導致incluse文件失敗
3、ProGuard 問題
ProGuard是一個壓縮、優化和混淆Java字節碼文件的免費的工具,它可以刪除無用的類、字段、方法和屬性。
可以刪除沒用的注釋,最大限度地優化字節碼文件。它還可以使用簡短的無意義的名稱來重命名已經存在的類、
字段、方法和屬性。
ProGuard的使用是為了:
1.創建緊湊的代碼文檔是為了更快的網絡傳輸,快速裝載和更小的內存占用.
2.創建的程序和程序庫很難使用反向工程.
3.所以它能刪除來自源文件中的沒有調用的代碼
4.充分利用java6的快速加載的優點來提前檢測和返回java6中存在的類文件.
在Android項目中用到JNI,當用了proguard後,發現native方法找不到很多變量,原來是被produard優化掉了。
所以,在JNI應用中該慎用progurad
解決方法:
a、應用的 android.mk 中加入
LOCAL_PROGUARD_ENABLED := disabled
b、按照指定的規則不優化 加一個配置文件,proguard.flags
1、在Android.mk中加入一行:
LOCAL_PROGUARD_FLAGS := -include $(LOCAL_PATH)/proguard.flags
2、創建proguard.flag文件,裡面寫入不需要proguard優化的類和方法。例如:
-keep class tv.ipanel.join.app.dtv.merge.IPanel30PortalActivity {
*
}
建議所有的jni類都要加上,不然會被 proguard 優化掉。從而導致找不到native接口。
更多的使用規則請看:
http://proguard.sourceforge.net/index.html#
也可以參照 build/core/proguard.flags 看一下具體的用法例子
4、memcpy 問題
原型: void *memcpy (void *dest, const void *src, size_t copy_amount)
copy_amount 不能大於 src 實際長度
舉例說明:
char buff[512],p[1024];
snprintf(buff,512,"%s","oi2u3ort29035trlskjglsfwo39052sfkljhso3u205tlsnv03lsnvso2305nlsvs");
memcpy(p,buff,1024);
error: call to '__memcpy_src_size_error' declared with attribute error: memcpy called with size bigger than source
修改 memcpy(p,buff,512);
5、ALOGX 打印函數問題
打印函數變更名稱,但其實現與原來還是一樣
最簡單方式:
system\core\include\cutils 路徑下新定義一個 log_legacy.h
實現如下:
#ifndef __LOG_LEGACY_H__
#define __LOG_LEGACY_H__
#define LOGV ALOGV
#define LOGD ALOGD
#define LOGI ALOGI
#define LOGW ALOGW
#define LOGE ALOGE
#define LOGV_IF ALOGV_IF
#define LOGD_IF ALOGD_IF
#define LOGI_IF ALOGI_IF
#define LOGW_IF ALOGW_IF
#define LOGE_IF ALOGE_IF
#define IF_LOGV IF_ALOGV
#define IF_LOGD IF_ALOGD
#define IF_LOGI IF_ALOGI
#define IF_LOGW IF_ALOGW
#define IF_LOGE IF_ALOGE
#endif /* __LOG_LEGACY_H__*/
然後在 log.h 中最後引用一下即可
#include "log_legacy.h"
如下所有的地方都不用變更
6、編譯android遇到java虛擬機堆內存不夠的問題 java.lang.OutOfMemoryError
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:2786)
at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:94)
at java.util.zip.DeflaterOutputStream.deflate(DeflaterOutputStream.java:155)
at java.util.zip.DeflaterOutputStream.write(DeflaterOutputStream.java:112)
at java.util.zip.ZipOutputStream.write(ZipOutputStream.java:272)
at com.android.signapk.SignApk.copyFiles(SignApk.java:496)
at com.android.signapk.SignApk.main(SignApk.java:557)
make: *** [out/target/product/Hi3716CV200ES/Nand/update.zip] 錯誤 1
應用 build\tools\signapk 源碼
/**
* Copy all the files in a manifest from input to output. We set
* the modification times in the output to a fixed time, so as to
* reduce variation in the output file and make incremental OTAs
* more efficient.
*/
private static void copyFiles(Manifest manifest,
JarFile in, JarOutputStream out, long timestamp) throws IOException {
byte[] buffer = new byte[4096];
int num;
Map<String, Attributes> entries = manifest.getEntries();
ArrayList<String> names = new ArrayList<String>(entries.keySet());
Collections.sort(names);
for (String name : names) {
JarEntry inEntry = in.getJarEntry(name);
JarEntry outEntry = null;
if (inEntry.getMethod() == JarEntry.STORED) {
// Preserve the STORED method of the input entry.
outEntry = new JarEntry(inEntry);
} else {
// Create a new entry so that the compressed len is recomputed.
outEntry = new JarEntry(name);
}
outEntry.setTime(timestamp);
out.putNextEntry(outEntry);
InputStream data = in.getInputStream(inEntry);
while ((num = data.read(buffer)) > 0) {
out.write(buffer, 0, num); //---------- 這個地方報的問題
}
out.flush();
}
}
在JVM中如果98%的時間是用於GC且可用的 Heap size 不足2%的時候將拋出此異常信息!!!
這個問題的根源是jvm虛擬機的默認Heap大小是64M,可以通過設置其最大和最小值來實現.設置的方法主要是幾個.
JVM堆的設置是指java程序運行過程中JVM可以調配使用的內存空間的設置.JVM在啟動的時候會自動設置Heap size的值,
其初始空間(即-Xms)是物理內存的1/64,最大空間(-Xmx)是物理內存的1/4。
可以利用JVM提供的-Xmn -Xms -Xmx等選項可進行設置。
例如:java -jar -Xmn16m -Xms64m -Xmx128m MyApp.jar
如果Heap Size設置偏小,除了這些異常信息外,還會發現程序的響應速度變慢了。
GC占用了更多的時間,而應用分配到的執行時間較少。
Heap Size 最大不要超過可用物理內存的80%,一般的要將-Xms和-Xmx選項設置為相同,而-Xmn為1/4的-Xmx值。
Heap size的 -Xms -Xmn 設置不要超出物理內存的大小。否則會提示
“Error occurred during initialization of VM Could not reserve enough space for object heap”。
修改definitions.mk文件 此文件位於build/core/目錄下
修改變量 :transform-classes.jar-to-dex中的-JXms16M -JXmx2048M值