android 4.2 系统编译小结

来源:互联网 发布:php excel 导出到桌面 编辑:程序博客网 时间:2024/06/05 23:58
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值


机器总内存是4G的,将-JXms16M -JXmx2048M修改为-JXms1024M -JXmx2048M试下


原创粉丝点击