bcoder

Android编译系统命令总结

 分类:Android, Java 阅读 (331)  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
3月 262019
 

一、必要的系统环境

  硬盘200G,内存4G+,交换分区(swap)4G+(可装完系统后添加,见后面错误处理部分)

二、下载源码,国内可以在清华镜像站下载 

  地址:https://mirrors.tuna.tsinghua.edu.cn/help/AOSP/

  网上有很多教程,这里就不再累述了

三、然后安装编译时需要的三方库

sudo apt-get install git-core gnupg flex bison gperf build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z-dev ccache libgl1-mesa-dev libxml2-utils xsltproc unzip

安装open-jdk-8

sudo add-apt-repository ppa:openjdk-r/ppa

sudo apt-get update

sudo apt-get install openjdk-8-jdk

四、开始编译

  然后进入到Android源码目录,假设源码在用户根目录的aosp目录中:

cd ~/aosp

  然后初始化编译环境,使用下面的命令:

source build/envsetup.sh

  然后选择要编译的目标版本,先输入lunch命令

lunch

  然后在显示的列表中选择你的目标版本,输入相应的数字,按回车即可

  然后使用make开始编译,可以使用-j参数增加编译的线程以提高速度,线程数量为cpu核心数的2倍比较合适,比如你的cpu是4核的使用

make -j8

  就可以了

五、遇到的错误

1、错误1:

03:00:11 ckati failed with: signal: killed
build/core/main.mk:21: recipe for target ‘run_soong_ui’ failed
make: *** [run_soong_ui] Error 1

解决方案1:
增加swap空间
增加办法:
cd /
增加4个G的交换空间
sudo dd if=/dev/zero of=/swp bs=10M count=400
sudo mkswap /swp
sudo swapon /swp

用free -m查看交换空间的情况
这个方法增加的是临时交换空间,如需一直保留,需要其他操作
参考链接:
https://blog.csdn.net/yellow_hill/article/details/38894317

解决方案2:
export LC_ALL=C

 

2、错误2:
JackServer提示out of memory

解决方案1:
增加虚拟机内存至最少4G

解决方案2:
修改jack server内存
步骤:
打开./prebuilts/sdk/tools/jack-admin
找到下面这一行
JACK_SERVER_VM_ARGUMENTS=”${JACK_SERVER_VM_ARGUMENTS:=-Dfile.encoding=UTF-8}”
修改为
JACK_SERVER_VM_ARGUMENTS=”${JACK_SERVER_VM_ARGUMENTS:=-Dfile.encoding=UTF-8 -XX:+TieredCompilation -Xmx4096M}”
保存jack-admin文件
在命令行执行
./prebuilts/sdk/tools/jack-admin kill-server
./prebuilts/sdk/tools/jack-admin start-server
重启jack server
然后重新编译

3、错误3:

Error while parsing ‘/media/liuderu/新加卷/android-8.0.0_r1/out/target/common/obj/APPS/QuickSearchBox_intermediates/with-local/classes.dex.flags’:1

原因:路径中包含中文字符

4、错误4

FAILED: out/target/common/obj/PACKAGING/checktestapi-current-timestamp

先执行一次make update-api然后再执行make

 Posted by on 2019-03-26

Android中aidl开发步骤

 分类:Android, Java 阅读 (395)  Android中aidl开发步骤已关闭评论
2月 242019
 
一、常见问题回顾

1、为什么要使用aidl?

答:aidl可以进行跨进程通讯。

2、aidl文件是怎么变成java代码的?

答:aidl是Android interface definition language的缩写,是一种中间语言,用于描述跨进程通信时的业务逻辑。aidl文件是通过android sdk中的名为aidl的程序生成java文件的,一般在{android-sdk}/build-tools/{android版本}/这个目录下。

3、aidl中都可以使用哪些数据类型?

答:可以使用基本的java数据类型(除了short以外),比如int, boolean, String,也可以使用List类型,如果要使用自己的类则该类需要实现Parcelable接口。

4、服务端中aidl接口的改变会不会导致未更新aidl的客户端崩溃或者出现数据混乱?

答:假如服务端中aidl更新了,客户端未更新,客户端不会报错。假如更新的接口是在接口的尾部添加的,不会出现数据混乱,如果接口在中间添加则会引发后面的函数返回结果混乱。即aidl的函数列表顺序不能乱。

二、aidl服务端开发步骤(使用Android Studio)

1、新建一个android工程

2、新建一个Service,本例为MyAidlService.java

3、新建一个aidl文件,比如IMyAidlInterface

4、为此aidl增加一个函数,比如如下,然后使用Android Studio重新编译一下项目:

5、在MyAidlService.java中,定义一个内部类,继承自IMyAidlInterface.Stub,比如AidlInterfaceStub

6、在MyAidlService.java中定义一个AidlInterfaceStub对象并初始化,如AidlInterfaceStub mAidlInterfaceStub = new AidlInterfaceStub();

7、在MyAidlService.java的onBind函数中返回上一步定义的对象,这样服务端的开发就完成了。

三、aidl客户端开发步骤

1、新建一个android工程

2、将服务端的aidl文件拷贝到客户端工程中,要保持aidl文件所在相对路径与服务端的路径结构一致,即让这个aidl的包名和服务端的包名一致

3、在客户端的Activity中定义一个IMyAidlInterface的对象,如:mIClientAidlInterface

4、在Activity的定义一个ServiceConnection对象,并用new进行实例化,这个ServiceConnection对象会生成以下两个回调函数的结构onServiceConnected和onServiceDisconnected

5、在上一个函数的onServiceConnected的回调中给mIClientAidlInterface赋值,如下

6、通过上一步得到的mIClientAidlInterface就可以调用远端的函数了

7、哦哦、忘了还没有绑定服务,为方便简单说明,我们直接在onCreate里绑定远端服务吧,如下:

8、客户端到此也完成了,看后面的全部代码试着写一下吧

四、代码

客户端:

服务端:

五、完整代码下载地址

https://download.csdn.net/download/wintergoes/11200474

六、其他问题

1、为什么byte[]数组不能作为参数传递?

传递byte数组时需要添加上in、out、inout修饰符,如下:

 

 Posted by on 2019-02-24
2月 222019
 

  本文基于Android4.4版本源码进行分析。

  一直以为ActivityThread是一个继承自Thread类的子线程,今天初看这个类发现里面的业务逻辑这么多,看了看网上的其他文章,原来这个Thread指的是Android应用的主线程啊。

问:安卓应用的入口函数是哪个?

答:Application.onCreate。错错错

正确的答案是ActivityThraed的main函数。

Android应用入口,ActivityThread.main  

下面咱们就看看ActivityThread.main函数:

首先,第一步启动SamplingProfilerIntegration,这个封装类集成了Dalvik的性能分析工具,用于监测记录应用的性能参数?待进一步查看代码
  相关源码:./frameworks/base/core/java/com/android/internal/os/SamplingProfilerIntegration.java
./frameworks/base/services/java/com/android/server/SamplingProfilerService.java
./libcore/dalvik/src/main/java/dalvik/system/profiler/SamplingProfiler.java
紧接着CloseGuard.setEnabled(false); 
  CloseGuard类实现了一种机制用于检查是否有内存泄露,默认是关闭,可以通过setEnabled(true)开启。
  源码路径:libcore/dalvik/src/main/java/dalvik/system/CloseGuard.java
Environment.initForCurrentUser();初始化Environment类,主要是一些目录的设置,比如我们通常用的获取外部存储路径函数Environment.getExternalStorageDirectory()的返回值就是在这里进行初始化的。
   源码路径:libcore/luni/src/main/java/libcore/io/EventLogger.java
EventLogger.setReporter(new EventLoggingReporter());
  没看懂怎么用的
  相关源码:libcore/luni/src/main/java/libcore/io/EventLogger.java
Security.addProvider(new AndroidKeyStoreProvider());
  为应用添加安全检测管理器,使用AndroidKeyStoreProvider,keystore就是指打release包时的数字证书吧
 

相关源码:frameworks/base/keystore/java/android/security/AndroidKeyStoreProvider.java
frameworks/base/keystore/java/android/security/AndroidKeyStore.java

Process.setArgV0(“<pre-initialized>”);
  因为应用还未启动完成,先给进程设置一个名字为<pre-initialized>
  相关源码:frameworks/base/core/java/android/os/Process.java
Looper.prepareMainLooper();
  将当前线程初始化为一个Looper,用Looper来管理线程内的各种请求。并将该Looper做为程序的主Looper。
  相关源码:frameworks/base/core/java/android/os/Looper.java
ActivityThread thread = new ActivityThread();
thread.attach(false);
   
   
AsyncTask.init();
  初始化AsyncTask,这是一个静态函数,由此可见AsyncTask的串行执行。
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, “ActivityThread”));
}
   
Looper.loop();
  开始循环主线程里的MessageQueue
 Posted by on 2019-02-22

QT中信号槽的断开

 分类:Others, Qt 阅读 (1,736)  No Responses »
2月 142019
 

对对象每次执行一次connect的操作,都会增加一个信号槽连接

如果我们想断开某个对象的所有信号槽,调用对象的disconnect()方法

如果想断开某一个信号槽,在connect时将返回的对象保存一下,然后调用QObject的disconnect()就可以了,如下面的代码:

dialog.cpp文件

dialog.h头文件

界面图片:

 Posted by on 2019-02-14

Qt中引用win32库的方法

 分类:Others, Qt 阅读 (2,002)  No Responses »
1月 282019
 

开发环境:QT+Vs2015

想使用SetCursorPos来控制鼠标的位置

#include <Winuser.h>

但是编译时,总时提示无法解析的外部符号

网上搜了一上,需要引用User32.lib库,最后发现需要在项目的.pro文件中加入user32的库的引用,如下:

如果编译还是不成功,把项目目录下生成的debug目录(build-xxxx-Desktop_Qt_5_10_1_MSVC2015_32bit-Debug)删除掉,再重新编译一下

 Posted by on 2019-01-28
1月 272019
 

  QLabel并不支持鼠标按下、松开等事件,我们需要新建一个QLabel的子类来支持。

  编写qadvancedlabel.h

  然后增加QAdvancedLabel的cpp文件,qadvancedlabel.cpp

  然后在程序中的实现:

  mainwindow.h文件

  mainwindow.cpp文件

  记得一定要设置setMouseTracking,否则只有按下时才会响应move事件。

 

 

 Posted by on 2019-01-27
12月 072018
 

发送端:

接收端:

其中:

67.7是指测试文件的大小是67.7mb

1688是传输文件的端口号

afdtest是传输的文件名,afdtest1688是接收的文件名(可随意设置)

 Posted by on 2018-12-07