Android 笔记

---恢复内容开始---

一.MTK Android version在文件下build/core/version_defaults.xml下定义。

二.Android 重新编译frameworks/base/core/res资源文件 生成的apk在哪?

在开发过程中,尤其是Framework相关开发时,有时候需要重新编译资源文件.编译顺序和注意事项如下:

1,资源文件位置:frameworks/base/core/res

2,编译后生成的文件:framework-res.apk 另外com.android.internal.R会更新这个R.java所在目录为/out/target/common/R/com/android/internal.

3,编译资源后,必须重新编译framework.jar.

4,如果在frameworks/base/core/res执行mm是并不重新编译,请使用toutch ### 命令

   ###代表目录下的一个文件.

5,资源文件要小写.

6,如果没有必要,不要编译资源文件,可以用其他方式使用资源,比如将资源使用adb push 传到某个目

   录,程序中直接指定具体目录.我在编译资源过程中遇到一些奇怪的问题,比如有时候许多图标会显

   示错误,原因猜测跟重新编译资源有关,可以试着重新编译services.jar并替换看看.

 

举一个例子:假如我想在WindowManagerService.java中使用一个图片资源pic.png.顺序如下.

1,将文件pic.png拷贝到位置:frameworks/base/core/res/res/drawable下.

2,在frameworks/base/core/res/res/drawable目录下执行touch pic.png.

3,进入目录frameworks/base/core/res/ 执行mm命令, 编译 framework-res.apk

4,执行完后com.android.internal.R 会新生成一个R.drawable.pic的引用.在程序中使用即可.

5,在目录frameworks/base/ 下执行mm 编译 framework.jar.

6,在WindowManagerService.java中使用com.android.internal.R.drawable.pic,使用完后保存文件.

7,进入目录frameworks/base/services/java/ 执行mm 编译  services.jar

8,替换机器上(虚拟机或者真机)的jar apk文件.

  adb push framework-res.apk /system/framework/

  adb push services.jar /system/framework/

  adb push framework.jar /system/framework/

  执行命令时注意framework-res.apk 的真实路径.

9,reboot 机器,查看修改结果.大功告成

三.设置下自动调节亮度默认开关:frameworks\base\core\res\res\values\config.xml:config_allowAutoBrightnessWhileDozing

四.与功能机的按键注册和响应函数:SetKeyHandler(CALLBACK, KEY_CODE, KEY_EVENT)相仿,android智能机的AbsListView类的item点击响应函数为performItemClick(View view, int position, long id),打此函数的断点,效率就会变高。

 

五.相机参数设置生效流程:

AbsListViewer.java下的performItemClick()方法

-->...-->SettingSublistLayout.java


public void onItemClick(AdapterView<?> parent, View view, int index, long id) {
Log.d(TAG, "onItemClick(" + index + ", " + id + ") oldIndex=" + mAdapter.getSelectedIndex());
boolean realChanged = index != mAdapter.getSelectedIndex();
if (realChanged) {
mPreference.setValueIndex(index);
}
if (mListener != null) {
mListener.onSettingChanged(realChanged);
}
}


-->InLineSettingSublist.java

public void onSettingChanged(boolean changed) {
Log.d(TAG, "onSettingChanged(" + changed + ") mListener=" + mListener);
if (mListener != null && changed) {
mListener.onSettingChanged(this, mPreference);
}
collapseChild();
}

-->...-->SettingManager.java
public void onSettingChanged(SettingListLayout settingList, ListPreference preference) {
Log.i(TAG, "onSettingChanged(" + settingList + ")");
if (mListener != null) {
mListener.onSharedPreferenceChanged(preference);
mPreference = preference;
}
refresh();
}

-->CameraActivity.java

private SettingManager.SettingListener mSettingListener = new SettingManager.SettingListener() {
@Override
public void onSharedPreferenceChanged(ListPreference preference) {
Log.d(TAG, "[onSharedPreferenceChanged]");
if (preference != null) {
String settingKey = preference.getKey();
String value = preference.getValue();
mISettingCtrl.onSettingChanged(settingKey, value);
}
mCameraDeviceCtrl.applyParameters(false);
}

  {1.-->通过此方法mISettingCtrl.onSettingChanged(settingKey, value)设置需要提交的mParameters的全局变量
-->{
  {2.-->通过此方法mCameraDeviceCtrl.applyParameters(false)将mParameters提交到数据库中

1.-->SettingCtrl.java
onSettingChanged中有这样一句代码:
Parameters parameters = mICameraDevice.getParameters();
onSettingChanged(parameters, currentCameraId, settingKey, value);
-->CameraDeviceImpl.java
public Parameters getParameters() {
return mMyCameraDevice.getParametersExt();
}

-->CameraDeviceExt.java
public ParametersExt getParametersExt() {
return mParametersExt;
}

2.-->CameraDeviceCtrl.java
applyParameters()方法中有这样一句代码:
prepareParameter(needRestart, isPreviewRatioChanged, isPreviewSizeChanged);-->if (mCurCameraDevice.isSceneModeChanged()) {
mCurCameraDevice.applyParametersToServer();
}
-->CameraDeviceExt.java
public void applyParametersToServer() {
lockRun(new Runnable() {
@Override
public void run() {
mCameraDevice.setParameters(mParameters);
}
});
Log.i(TAG, "[applyParametersToServer]");
}
-->CameraManager.java
到这里就是发送消息写数据库了
public void setParameters(Parameters params) {
if (params == null) {
Log.v(TAG, "null parameters in setParameters()");
return;
}
mCameraHandler.obtainMessage(SET_PARAMETERS, params.flatten()).sendToTarget();
}
 纠正下错误:相机设置写文件的流程不是上面写的那样,正确流程如下,上面流程具体作用有待研究。

SettingSublistLayout.java
public void onItemClick(AdapterView<?> parent, View view, int index, long id) {
Log.d(TAG, "onItemClick(" + index + ", " + id + ") oldIndex=" + mAdapter.getSelectedIndex());
boolean realChanged = index != mAdapter.getSelectedIndex();
if (realChanged) {
mPreference.setValueIndex(index);
}
if (mListener != null) {
mListener.onSettingChanged(realChanged);
}
}
-->
ListPreference.java
public synchronized void setValueIndex(int index) {
if (index < 0 || index >= mEntryValues.length) {
print();
Log.w(TAG, "setValueIndex(" + index + ")", new Throwable());
return;
}
setValue(mEntryValues[index].toString());
}

-->
public void setValue(String value) {
if (findIndexOfValue(value) < 0) {
throw new IllegalArgumentException();
}
mValue = value;
persistStringValue(value);
}
-->
private void persistStringValue(String value) {
SharedPreferences.Editor editor = getSharedPreferences(mKey).edit();
editor.putString(mKey, value);
editor.apply();
}



六:关于android源码编译报错:

Error: The output jar is empty. Did you specify the proper '-keep' options?

问题分析:其实质是就代码混淆引起的,什么是代码混淆?本段落最后将给出几篇文章连接供参考

具体解析:android源码编译的时候,会进行对某个apk的源码进行混淆,当然可以取消混淆,(为何混淆,如何混淆,如何取消,为什么/如何指定某些类不混淆)参考下面提供的链接,都会给出解释。当你的apk所有的代码被混淆(包括类和jar包),代码没有任何一个入口可被外部调用,也就是说,因为你混淆了,所以你的代码变的不可被编译器识别了,我是这么理解的,所以编译会报错。所以总结就是至少一你要保证你的APK有一个类或者jar包可被编译器识别,可以看作编译器的一个识别入口吧。那么怎么做呢,就需要用到一个参数-keep。

具体解决办法:在akp下添加这样一个文件proguard.flags,文件里的内容写入这样一句:

# Keep all class in this package
-keep class com.hely.showversion.VersionReceiver

意思就是keep后面的类不参加编译器的代码混淆,当然你也可以keep更多的类或者jar,详见链接文档。

然后还需要在Android.mk下加入这样一行代码:

LOCAL_PROGUARD_FLAG_FILES := proguard.flags
这样就OK了。
最后给出相关链接:
http://blog.csdn.net/primer_programer/article/details/37602339

http://blog.csdn.net/lovexjyong/article/details/24652085

http://blog.sina.com.cn/s/blog_5f1ebb8f0101lkqz.html

 

 

 七:从一个broadcast直接启动一个activity需要注意的地方:

需要设置INTENT FLAG属性:activityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);具体详见android官方文档。


八:addLinks的用法简介:

 创建自定义的链接字符串:


  为了定义自己的链接字符串,你需要创建一个RegEx样式来匹配文本,进而显示成超链接。和本地类型一样,通过调用Linkify.addLinks来指定目标View,但这次,传入的是新的RegEx样式。你还可以传入一个前缀,当链接点击时,它会添加到目标URI上。


 


int flags = Pattern.CASE_INSENSITIVE;
Pattern p = Pattern.compile(“\\bquake[0-9]*\\b”, flags);
Linkify.addLinks(myTextView, p, “content://com.paad.earthquake/earthquakes/”);

 注意:正则表达式匹配的字串,即文本中添加下滑线的字串,会自动添加到 “content://com.paad.earthquake/earthquakes/”这个链接后面,即链接会变成:
“content://com.paad.earthquake/earthquakes/quake[0-9]*”


九:Linkify 详解:

Linkify是一个辅助类, 在TextView(包含派生类)中通过RegEx模式匹配创建超链接;

 

Linkify的预设值可以检测到Web URL, Email, 电话号码等, 转换为链接;


使用静态的Linkify.addLinks()方法, 需要传入视图(TextView)掩码(bitmask);


掩码包括: WEB_URLS(网址链接), EMAIL_ADDRESSES(email地址), PHONE_NUMBERS(电话号码) 和 ALL(全部);


也可以在布局(layout)内使用android:autoLink属性;


 


可以定制链接字符串, 需要传递视图(textView), 模式匹配(RegEX模式, 正则模式), 基本的URI(base URI);


可以使用MatchFilter(匹配过滤器), 和TransformFilter(转换过滤器);


MatchFilter: 重写acceptMatch()方法, 返回bool类型, 过滤不匹配的链接;


TransformFilter: 重写transformUrl()方法, 返回String类型, 修改URI的内容;



十:match.group()的用法:

原来,group是针对()来说的,group(0)就是指的整个串,group(1) 指的是第一个括号里的东西,group(2)指的第二个括号里的东西。
最近学习正则表达式,发现Java中的一些术语与其他地方描述的有所差异。比如Java正则表达式中的“组”概念与《正则表达式必知必会》一书中 讲述的“子表达式”其实是一样的,只是表述不同而已。由此也引发了使用JavaAPI时对group(int group)、start(int group)、end(int group)不是太理解。在阅读了关于正则表达式问题:有谁用过Matcher类的group()方法没有 之后彻底明白,并写了一个小程序测试。

程序如下
Java代码  收藏代码
  1. package cn.mingyuan.regexp.singlecharacter;  
  2.   
  3. import java.util.regex.Matcher;  
  4. import java.util.regex.Pattern;  
  5.   
  6. public class GroupIndexAndStartEndIndexTest {  
  7.   
  8. /** 
  9. * @param args 
  10. */  
  11. public static void main(String[] args) {  
  12.    // TODO Auto-generated method stub  
  13.    String str = "Hello,World! in Java.";  
  14.    Pattern pattern = Pattern.compile("W(or)(ld!)");  
  15.    Matcher matcher = pattern.matcher(str);  
  16.    while(matcher.find()){  
  17.     System.out.println("Group 0:"+matcher.group(0));//得到第0组——整个匹配  
  18.     System.out.println("Group 1:"+matcher.group(1));//得到第一组匹配——与(or)匹配的  
  19.     System.out.println("Group 2:"+matcher.group(2));//得到第二组匹配——与(ld!)匹配的,组也就是子表达式  
  20.     System.out.println("Start 0:"+matcher.start(0)+" End 0:"+matcher.end(0));//总匹配的索引  
  21.     System.out.println("Start 1:"+matcher.start(1)+" End 1:"+matcher.end(1));//第一组匹配的索引  
  22.     System.out.println("Start 2:"+matcher.start(2)+" End 2:"+matcher.end(2));//第二组匹配的索引  
  23.     System.out.println(str.substring(matcher.start(0),matcher.end(1)));//从总匹配开始索引到第1组匹配的结束索引之间子串——Wor  
  24.    }  
  25. }  
  26.   
  27. }  



程序的运行结果为:
Java代码  收藏代码
  1. Group 0:World!  
  2. Group 1:or  
  3. Group 2:ld!  
  4. Start 0:6 End 0:12  
  5. Start 1:7 End 1:9  
  6. Start 2:9 End 2:12  
  7. Wor  
总结:其实group(),start(),end()所带的参数i就是正则表达式中的子表达式索引(第几个子表达式),由于刚开始对Java正
则表达式中的组的概念不清晰,导致理解困难。当将“组”的概念与“子表达式”对应起来之后,理解matcher的group,start,end就完全没
有障碍了。




十一 Android 源码编译报错问题: undefined reference to `jniGetFDFromFileDescriptor'

顾名思义,jniGetFDFromFileDescriptor这个方法没找到,由于自己的APK的JNI代码,需要用到这个JNI方法,编自己的APK时候的报错这个错误,
但是全编(make -j24 2>&1 | tee build.log)的时候不报错,所以把大量时间花在全编和单编模块的区别,一直以为全编的时候才编出某个零时库,
但单编的时候清除掉了这个库,所以需要全编,但是后来想,这样的编译设计不是一个坑吗,所以作为google那些大神们不可能这么昏庸啊。
于是打算一探究竟,后来发现/system/lib64下来确实没生成我自己写的JNI的库,说明全编的时候编译器遗漏或者忽略我这个APK的错误,
果然编译器也是不能100%信任的。于是再单编,果然还是报错,说明我这个apk没有完全编译成功(也许全编的时候,编译器只关心你的你JAVA代码是否有错,
忽略了JNI代码链接的错误,所以全编的时候会生成apk,但是不会生成你自己写JNI库,但是单编的时候由于jni编译报错,apk也将不会编译完成,这就是单编和全编的区别
,可能是因为我还什么盲点还不知道吧,总感觉全编也可以检测到这样的错误,但是至今没发现需要怎么设置,有时间再研究研究)。
那么来看看问题的根源是什么?
找不到这个方法,第一,排除是不是包含了头文件,注意C,C++中头文件很重要,检查后发现已经包含了#include "JNIHelp.h"这个头文件,是不是路径不对,加上绝对路径后还是报错,
详细错误描述:/home/rainey/projects/M3502/libnativehelper/include/nativehelper/JNIHelp.h:160: undefined reference to `jniGetFDFromFileDescriptor'
从错误中也可以看出不是路径问题,因为已经找到了这个头文件,且错误发生在这个头文件的160行,看到这行的代码如下:
 159:inline int jniGetFDFromFileDescriptor(JNIEnv* env, jobject fileDescriptor) {
160: return jniGetFDFromFileDescriptor(&env->functions, fileDescriptor);
161:}
说的是160行的这个方法,找不到,这个方法位于JNIHelp.cpp里面,说明没编到或没被链接到,既然全编了且其他地方调用没报错,说明已经编到,那么就是剩下链接问题了。
对比其他调用的地方,头文件包含也没区别(本人比较多疑,其实这种想法以后少想,声明一个方法的头文件已经被包含,跟其他头文件应该没啥关系,所以想多了)。那么就怀疑是链接库的问题了,
果然发现,JNIHelp.cpp被编译到一个叫做libnativehelper.so(详见JNIHelp.cpp所在模块的mk文件),其他调用这个方法的地方都包含了这个库,于是99.9%确定是这个问题了,然后在自己的MK文件下
加入代码:LOCAL_SHARED_LIBRARIES += libnativehelper
大功告成!!!!

十二.关于Android中 XXXPlugIn.java 和mplugin/javalib.jar中MPlugin.class的理解:
mplugin/javalib.jar位于/vendor/lentek/libs下,阐述2者关系前,先上代码:
private IDataProtectionExt mDataProectExt;

....
mDataProectExt = (IDataProtectionExt) UtilsExt.getDataProectExtPlugin(getActivity());

public static IDataProtectionExt getDataProectExtPlugin(Context context) {
IDataProtectionExt ext;
ext = (IDataProtectionExt) MPlugin.createInstance(
IDataProtectionExt.class.getName(), context);
if (ext == null) {
ext = new DefaultDataProtectionExt(context);
}
return ext;
}

mDataProectExt.addDataPrf(deviceAdminCategory);

public class DataProtectionPlugIn extends DefaultDataProtectionExt {
....
  public void addDataPrf(PreferenceGroup prefGroup) {
  Log.d(TAG, "addDataPrf for dataprotection plugin");
  if (prefGroup instanceof PreferenceGroup) {
  prefGroup.addPreference(mPreference);
  }
  }
....


public class DefaultDataProtectionExt extends ContextWrapper implements IDataProtectionExt {
...
    public void addDataPrf(PreferenceGroup prefGroup) {
  Log.d(TAG, "will not add data protection preference by default");
  }

...

最终发现mDataProectExt.addDataPrf(deviceAdminCategory)走的是DataProtectionPlugIn的方法,那么说明getDataProectExtPlugin方法里创建的ext对象引用的是DataProtectionPlugIn的实例
也就是说MPlugin.createInstance(IDataProtectionExt.class.getName(),context)虽然传入的是IDataProtectionExt接口名,但是返回的对象却是DataProtectionPlugIn的对象.那么是不是可以看作
MPlugin.class是XXXPlugIn.java的管理器,如果某个XXXPlugIn.java实现了类似IDataProtectionExt命名规则的接口,那么想得到这个类的对象可以通过MPlugin.createInstance(IDataProtectionExt.class.getName(),context)
这样的方式去实现.这相当于mtk给我们这样的框架,可以让我们自己设计IDataProtectionExt这样的接口,同时自己设计类似DataProtectionPlugIn 命名规则的类,通过MPlugin.createInstance(String 接口名,Context context)
统一管理产生类的实例.而MPlugin.class是被MTK封装在javalib.jar里面,对外不可见,你不必关心实例是怎么产生,你只要关心你自己设计的接口和实现这个接口的类是怎么设计的.
总而言之,MPlugin.class是产生XXXPlugIn.java这些类实例的管理器,我们只要安照MTK提供的命名规则,就可以按照这个框架,编写我们想要的代码,实现相应的功能.

注意:这些类都是在MTK包名下,并非android源生代码 
类似的举例:
// Power saving mode feature plug in
private IBatteryExt mBatteryExt;



public PowerUsageExts(Context context, PreferenceGroup appListGroup) {
mContext = context;
mAppListGroup = appListGroup;
// Battery plugin initialization
mBatteryExt = UtilsExt.getBatteryExtPlugin(context);

}
/**
* M: Create battery plugin object
* @param context Context
* @return IBatteryExt
*/
public static IBatteryExt getBatteryExtPlugin(Context context) {
IBatteryExt ext;
ext = (IBatteryExt) MPlugin.createInstance(
IBatteryExt.class.getName(), context);
if (ext == null) {
ext = new DefaultBatteryExt();
}
return ext;
}
----------------------------------------分割线-------------------------------------------------
Android adb pull 拉去一类文件,可以使用xargsadb shell ls接受通配符的命令的结果。这使你可以复制多个文件。令人生气的是,该adb shell ls命令的输出包含换行控制字符tr -d '\r'
ex:
adb shell 'ls sdcard/gps*.trace' | tr -d '\r' | xargs -n1 adb pull

----------------------------------------------------------------------------------------------
Q: Cannot run program "aapt": error=2
resolution: 默认使用的SDK下面build_tools/下面的aapt, 因为win32库的问题,需要用linux下的aapt, 使用sudo apt-get install aapt.并且更新win32相关的库:sudo apt-get install gcc-multilib lib32z1 lib32stdc++6
 
 ---------------------------------------------------------------------------------------------------------------------------------------------------
Q:Entry fileTemplates//code/Google Test Fixture SetUp Method.cc.ft not found in C:/Program Files/Android/Android Studio/lib/idea.jar

A:
这样做就可以了
修改studio.exe.vmoptions和studio64.exe.vmoptions
-Djdk.util.zip.ensureTrailingSlash=false
 ---------------------------------------------------------------------------------------------------------------------------------------------------

十三、Android Q 编译报错:
"lz4c" is not allowed to be used. See https://android.googlesource.com/platform/build/+/master/Changes.md#PATH_Tools for more information.

A:如官网描述:最好的办法是按照官方的办法将
TEMPORARY_DISABLE_PATH_RESTRICTIONS=true置为true, 或者在build/soong/ui/build/paths/config.go文件下添加外部工具名称。

    其次的办法是:将kernel/msm4.4/AndroidKernel.mk下的

    TARGET_PREBUILT_INT_KERNEL := $(KERNEL_OUT)/arch/$(KERNEL_ARCH)/boot/Image.lz4

 改成 TARGET_PREBUILT_INT_KERNEL := $(KERNEL_OUT)/arch/$(KERNEL_ARCH)/boot/Image.gz。

    并且将

    CONFIG_IMG_LZ4_DTB=n
    CONFIG_IMG_GZ_DTB=y

    这2个宏配置上。

 
 

posted on 2015-12-03 14:25  找工作中  阅读(1046)  评论(0编辑  收藏  举报