java中的左移<<操作符

 分类:Java, Java语言 阅读 (1,479)  java中的左移<<操作符已关闭评论
8月 162019
 

对于正数来说,左移1位相当于这个数值翻倍,或者对于类型为int的负数来说,左移一位也是翻倍

但是对于类型小于int的类型,比如short和byte,本来以为左移并不会带符号,但经过测试不是这样的,看代码:

左移后为int型数值,本来以左移8位后,前16位会用0填充,但是没有,左移是带符号移位的,看运行结果如下:

好,我们再看看其他情况的。

1、byte为正数的情况,moveb = 2的运行结果

 

 

 Posted by on 2019-08-16

java中的右移>>和无符号右移>>>

 分类:Java, Java语言 阅读 (5,207)  java中的右移>>和无符号右移>>>已关闭评论
8月 062019
 

右移>>是指带符号右移,如果最高位的符号位为1,则右移时左侧补上的空位用1填充,否则用0填充

而无符号右移>>>,不管左侧最高位是1还是0,左侧补上的空位统统用0填充,如下面的例子:

看输出结果:

我们从第13位开始左移,即第二字节的101那里,左移后的结果如下,右侧应该有一些0用省略号代替了

101 11110100 01010100…..

我们再右移29位,即只剩下101,那么如果用>>前面将被补上很多的1,如果使用>>>,则会补很多0

 Posted by on 2019-08-06

gradle中动态修改生成的apk的文件名

 分类:Android, Java 阅读 (1,271)  gradle中动态修改生成的apk的文件名已关闭评论
8月 062019
 

在app/build.gradle中的android节点中增加如下代码:

myapp_固定的名称

buildType.name 为release或者debug

${variant.versionName}为versionName

${variant.versionCode}为versionCode

生成的apk的文件名为myapp_debug.apk

 Posted by on 2019-08-06

Java数据类型转换的一些问题总结

 分类:Java, Java语言, Uncategorized 阅读 (1,072)  Java数据类型转换的一些问题总结已关闭评论
8月 062019
 
一、强制类型转换导致数据的变化

举例:short类型的值范围为-32768 ~ 32767,看下面这些对short值的操作

最后的输出结果为:

二、关于一些运算后生成的默认值

对于长度小于或者等于int的数据类型,如short, byte在进行如下运算后,其他运算结果为int型

<<,>>,>>>,&,|,^,+,-,*,/

如下代码,就会提示你将运算强制转换成short类型

三、有符号数转无符号数

可以通过&运算将有符号号转为无符号数,

对于byte类型& 0xFF,

对于short类型& 0xFFFF,

对于int类型& 0xFFFFFFFF

注意&运算完的结果是一个int型的值

下面看一个示例代码:

运行结果:

强制类型转换并没有改变符号。

四、负数的左移位操作

负数的左移位操作会使数据保持为负数

http://bcoder.com/java/right-shift-operator-in-java

 Posted by on 2019-08-06

关于Gson使用的一些深入研究

 分类:Android, Java 阅读 (998)  关于Gson使用的一些深入研究已关闭评论
7月 042019
 
一、Gson的复用

一直有一个担心,对于不同的数据类是否可以用同一个gson实例,今天研究了一下,不仅是可以,而且最好是这样使用。看代码Gson.java中的getAdapter方法,一开始就是在typeTokenCache这个缓存中找type相关的TypeAdapter。

因此复用一个gson的实例会省去匹配TypeAdapter(当然还有new Gson())的时间。

如下代码实例:

在我机器上测试不复用的话用时220-260毫秒之间(非常不稳定),复用120毫秒。

二、TypeToken是个什么东东?

TypeToken其实是为了给标识一个泛型类中的T,对于普通的类我们通过getClass().getName就可以得到类的标识,但是对于泛型类,只能得到泛型外层的类名,并不能得到泛型外层类+泛型类这样的全名。

如下代码:

输出结果是:java.util.ArrayList,而不是java.util.ArrayList<java.lang.Integer>

使用TypeToken来获取就是另外一种情况了,看下面的例子:

输出结果:

三、TypeAdapter的使用

 

四、一些类的作用

1. ConstructorConstructor – 返回一个函数可以给要操作的类新建一个实例对象。

2. InstanceCreator – 用于给没有无参数构造函数的类,创建一个实例的一个接口。解释:gson在反序列时需要创建类的一个实例,如果该类没有无参数构造函数(如:三方库中的类),则会出现异常,所以开发者需要新建一个类实现这个接口,并用该类可用的构造函数新建一个实例。并使用下面方式Gson gson = new GsonBuilder().registerTypeAdapter(Id.class, new IdInstanceCreator()).create();注册到gson中。

3. FutureTypeAdapter – 用于缓存TypeAdapter。为什么不用TypeAdapter的实例缓存?因为TypeAdapter是个虚类 :-D 

 

ByteBuffer详解

 分类:Android, Java, Java语言 阅读 (5,521)  ByteBuffer详解已关闭评论
7月 022019
 
一、ByteBuffer的父类

  ByteBuffer的父类是Buffer类,意思为缓冲区类,ByteBuffer为字节缓冲区,当然他也可以处理int, long, char等基本数据类型。

  相比于Buffer类的其他继承类CharBuffer、DoubleBuffer、FloatBuffer、IntBuffer、LongBuffer 和 ShortBuffer,ByteBuffer类应用更广泛。

 
二、ByteBuffer的几个变量
position 表示当前bytebuffer的数据指针的位置。因为ByteBuffer还可以做为一个数据解析器,比如getShort()可以读出来一个short类型的数据,因此position也是很重要的。
limit 读取时可用作数据索引的上限(此时相当于数据的length – 1),但是写入时又不能有这个limit,否则会造成数据无法写入(写入时可设置limit = capacity)
mark 用于标记读取数据的起始位置,比如我们已经处理完成10个字节的数据,以后不用再管这10个字节,那么我们可以用mark()标记一下,然后配套的时候reset使position回到这个位置(比如后边的处理遇到了异常,或者遇到了不完整的数据)。
capacity 容量,很简单啦,就是最大允许的字节数量。
 
三、几个要点

  1、limit的设置,因为put和get系列函数只会影响position,不会影响limit,limit是数据的结尾位置,是相当的重要。

 
四、ByteBuffer类的方法
put(byte b) 向ByteBuffer中写入一个字节,并且如果成功position+1
put(byte[] src) 将参数中的byte数据写入bytebuffer中,并且如果成功position+src的长度
put(byte[] src, int offset, int length) 将src数组中,在offset处开始,长度为length的数据写入到ByteBuffer中,并且如果成功,position+length
compact() 其实就是删除已读过的数据,将position到limit之间的数据移动到0和limit-position处,并将mark重置为-1,position放到数据结尾,总结一下,就是可以继续写数据了,但是不能读数据。
limit() 获取当前的数据尾的位置(当然,前提是你设置过limit或者调用过flip)
limit(int newLimit) 设置数据的结尾位置。
rewind() 执行后position = 0, mark = -1,数据内容不变。应用场景:新put数据后,使用rewind将指针位置恢复到起始位置。
reset() 将position恢复到mark处的位置。
clear() 重置ByteBuffer的 position = 0; limit = capacity; mark = -1,实际数据内容无变化,其实这个函数会比较少用,不如rewind的实用性强,因为rewind不会改变limit。
remaining() 还未读取的数据limit – position,前提是你正确设置了limit的位置(所有数据的结尾位置)或者调用过flip()函数。
hasRemaining() 是否还有未读取的数据,前提是你正确设置了limit的位置(所有数据的结尾位置)或者调用过flip()函数。
mark() 将当前的position设备为mark(),mark要和reset配合使用。
discardMark() 将mark的位置重置为-1,貌似很少会单独使用这个函数,而是用rewind或者clear来重置mark值
flip() 其实这个函数的意思是,数据准备好了,可以读了,估计是reset、rewind、clear这些名字用的差不多了,起了一个这个难理解的名字,翻转,听着就让人晕。这个函数相当于下面两个函数的组合buf.limit(buf.position());
buf.rewind();。
get系列函数  
 Posted by on 2019-07-02

Android Studio中引入编译好的so文件

 分类:Android, Java 阅读 (1,985)  Android Studio中引入编译好的so文件已关闭评论
6月 252019
 

so文件单纯的放在源码libs目录下是不能编译到apk中的,需要下面的步骤才可以使用so文件。

一、首先将so文件放到app/src/main/libs目录下,so文件在libs目录下或者libs子目录下均可

二、修改build.gradle(app)文件,在defaultConfig节中加入下面代码

三、然后调用so文件就可以了

 Posted by on 2019-06-25

Android编译系统(mk)路径变量整理

 分类:Android, Java 阅读 (4,401)  Android编译系统(mk)路径变量整理已关闭评论
6月 062019
 

本文基于Android8.1系统源码,常量的定义在文件./build/make/core/envsetup.mk中

TOPDIR – 源码根目录

OUT_DIR – out目录,默认情况下是源码目录下的out目录,如果指定OUT_DIR_COMMON_BASE这个环境变量,则为这个变量指定的目录

TARGET_BUILD_TYPE – 是release还是debug的编译,在环境变量TARGET_BUILD_TYPE中指定

SOONG_OUT_DIR – soong目录,默认情况下是out/soong

DEBUG_OUT_DIR – TARGET_BUILD_TYPE为debug时会用到此目录,默认是out/debug

TARGET_OUT_ROOT – target目录,默认是out/target,debug时为out/debug/target

TARGET_PRODUCT_OUT_ROOT – 默认是out/target/product目录

TARGET_COMMON_OUT_ROOT – 默认是out/target/common目录,用于生成编译时的中间文件

PRODUCT_OUT – 默认是out/target/product/{设备型号},真正的编译生成文件的目录

TARGET_OUT – $(PRODUCT_OUT)/system目录

TARGET_OUT_GEN – $(PRODUCT_OUT)/gen

TARGET_OUT_EXECUTABLES – $(TARGET_OUT)/bin

TARGET_OUT_OPTIONAL_EXECUTABLES – $(TARGET_OUT)/xbin

TARGET_OUT_RENDERSCRIPT_BITCODE := $(TARGET_OUT_SHARED_LIBRARIES)

TARGET_OUT_JAVA_LIBRARIES :=$(PRODUCT_OUT)/system/framework

TARGET_OUT_APPS :=$(PRODUCT_OUT)/system/app

TARGET_OUT_APPS_PRIVILEGED :=$(PRODUCT_OUT)/system/priv-app

TARGET_OUT_KEYLAYOUT :=$(PRODUCT_OUT)/system/usr/keylayout

TARGET_OUT_KEYCHARS :=$(PRODUCT_OUT)/system/usr/keychars

TARGET_OUT_ETC :=$(PRODUCT_OUT)/system/etc

TARGET_OUT_FAKE := $(PRODUCT_OUT)/fake_packages

TARGET_OUT_TESTCASES := $(PRODUCT_OUT)/testcases

HOST_OUT_ROOT – host目录,默认是out/host

HOST_OUT

SOONG_HOST_OUT

HOST_CROSS_OUT

 Posted by on 2019-06-06

Android编译系统命令总结

 分类:Android, Java 阅读 (857)  Android编译系统命令总结已关闭评论
6月 062019
 

本文基于Android8.1系统源码

– lunch: lunch <product_name>-<build_variant>
– tapas: tapas [<App1> <App2> …] [arm|x86|mips|armv5|arm64|x86_64|mips64] [eng|userdebug|user]
– croot: 回到源码根目录.
– cproject 回到当前项目的根目录
– m: 从根目录开始编译,相当于make整个系统.
– mm: 编译当前目录下的所有模块,但不包括他们的依赖.
– mmm: 编译指定目录下的所有模块,但不包括他们的依赖,.
To limit the modules being built use the syntax: mmm dir/:target1,target2.
– mma: 编译当前目录下的所有模块,包括他们的依赖.
– mmma: 编译指定目录下的所有模块和他们的依赖.
– provision: Flash device with all required partitions. Options will be passed on to fastboot.
– cgrep: 在所有的c或者c++文件中搜索某个关键字.
– ggrep: 在所有的gradle文件中搜索某个关键字.
– jgrep: 在所有的java文件中搜索某个关键字.
– resgrep: 在所有的资源文件中搜索某个关键字.
– mangrep: 在所有的AndroidManifest.xml文件中搜索某个关键字.
– mgrep: 在所有的Makefiles文件中搜索某个关键字.
– sepgrep: 在所有的sepolicy文件中搜索某个关键字.
– sgrep: 在所有的源代码文件中搜索某个关键字.
– rcgrep: 在所有的rc文件中搜索某个关键字
– godir: 跳转到包含某个文件的目录中某个关键字.

具体的函数实现可以查看build/envsetup.sh

 Posted by on 2019-06-06
4月 252019
 
一、启动init进程

init程序是Linux启动的和经一个程序

init程序的源文件在system/core/init/init.cpp里

二、解析init.rc

在init的main函数里,会先做一些系统初始化的工作,然后通过Parser对象来解析init.rc文件

parser对象的源文件在system/core/init/init_parser.cpp里面

在8.1系统源码里面,rc文件分别存在几个不同的目录里面

  • 主rc文件,init.rc在device/设备名/型号名/目录里,init.rc通过import的形式导入其他的rc文件
  • 还有一些其他的rc文件也在这个目录里面
  • init.zygote.rc文件在system/core/rootdir里面

但是在把系统镜像烧录到车机后,rc文件都在根目录/下

三、启动zygote

init进程解析完init.rc,将根据配置文件启动zygote

zygote是所有安卓服务和应用的父进程,承载着创建java虚拟机并且孵化安卓层的SystemServer和安卓应用的功能

zygote源码在frameworks/base/cmds/app_process/app_main.cpp中

四、启动SystemServer

在zygote中其实并没有fork出来一个SystemServer,而是先启动了java层的ZygoteInit类(通过runtime.start(“com.android.internal.os.ZygoteInit”, args, zygote))

当然fork是不能java层直接调用的,ZygoteInit.java中又通过Zygote类,Zygote类又通过jni调用了Linux层的函数fork出来了SystemServer

ZygoteInit.java的源码在:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

Zygote.java的源码在:frameworks/base/core/java/com/android/internal/os/Zygote.java

Zygote jni层的代码在:frameworks/base/core/jni/com_android_internal_os_Zygote.cpp

SystemServer启动后,会启动一大堆系统服务,安卓的基础运行环境就起来了,启动服务的几个函数为:

SystemServer的代码在:frameworks/base/services/java/com/android/SystemServer.java

五、Launcher的启动

在SystemServer的startOtherServices函数中调用了mActivityManagerService.systemReady,

在ActivityManagerService的systemReady函数中通过startHomeActivityLocked来启动Launcher

六、待续问题:

init.rc中的服务是怎么启动的

 Posted by on 2019-04-25