android c++ java相关知识

1 C++ java函数、类模板


  在android framework hal中经常可以看到类似下面的代码

template<typename SERVICE> /* 等同于template <class SERVICE> */
class BinderService
{
public:
    static status_t publish(bool allowIsolated = false) {
        sp<IServiceManager> sm(defaultServiceManager());
        return sm->addService(
                String16(SERVICE::getServiceName()),
                new SERVICE(), allowIsolated);
    }

    static void publishAndJoinThreadPool(bool allowIsolated = false) {
        publish(allowIsolated);
        joinThreadPool();
    }

    static void instantiate() { publish(); }
    ...
};

  这种就是类模板。template是定义模板函数的关键字。template后面的尖括号不能省略;class(或typename)是声明数据类型参数标识符的关键字,用以说明它后面的标识符是数据类型标识符。
  
  SERVICE可以认为是一个变量名,可以是其他名字,符合要求就行。SERVICE变量的类型是不确定的,由调用者确定。
  
  如cameraService实例化时执行了CameraService::instantiate();,BinderService是CameraService的父类,且CameraService并没有重写instantiate方法,实例化时就调用了BinderService的instantiate方法。这里SERVICE就是CameraService
  new WeakReference<Camera>(this)也是一个类模板使用的例子,使用类模板来实例化一个类。类的定义类似下面代码。这里是android framework java代码

template <typename T> /* 实际上并没有这句,直接写到class行,class WeakReference<T> */
class WeakReference{
    WeakReference(T){ //构造函数
        ... 
    }
}
实际代码参考:android源码
./libcore/luni/src/main/java/java/lang/ref/WeakReference.java
./libcore/libart/src/main/java/java/lang/ref/Reference.java

  另一个使用例子

   WeakReference<AutoActivity> mactivity; //引用

    public MyHandler(AutoActivity activity){
        mactivity = new WeakReference<AutoActivity>(activity); //实例
    }

  函数模板如下

template <typename T1, typename T2>
T1 function(T1 a, T2 b){
    std::cout<<a<<std:endl
    return a;
}
int main(void)
{
    function("test", 5); //T1:字符串,T2:整型,也可以这么写:function<char *, int>("test", 5)
}

  调用函数时最好用function

2 java接口定义


public interface IBinder //接口定义,使用关键字public interface
{
    . . . . . .
    public String getInterfaceDescriptor() throws RemoteException;
    public boolean pingBinder();
    public boolean isBinderAlive();
    public IInterface queryLocalInterface(String descriptor);
    public void dump(FileDescriptor fd, String[] args) throws RemoteException;
    public void dumpAsync(FileDescriptor fd, String[] args) throws RemoteException;
    public boolean transact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException;

    public interface DeathRecipient 
    {
        public void binderDied();
    }
    public void linkToDeath(DeathRecipient recipient, int flags)throws RemoteException;
    public boolean unlinkToDeath(DeathRecipient recipient, int flags);
}
/* 继承testClass类,实现IBinder接口 */
class test extends testClass implements IBinder 
{
    ...
}

  类可以继承另一个类,普通类只能实现,并且可以实现多个接口;而一个抽象类可以实现一个接口;接口可以继承另一个接口。继承使用关键字:extends,实现接口使用关键字:implements
  java只能继承一个类,可以实现多个接口;而C++中并没有接口的概念,C++可以继承多个类。

3 C++中指针、引用的区别


参考

1.指针和引用的定义和性质区别:

(1)指针:指针是一个变量,只不过这个变量存储的是一个地址,指向内存的一个存储单元;而引用跟原来

的变量实质上是同一个东西,只不过是原变量的一个别名而已。如:

int a=1;int *p=&a;

int a=1;int &b=a;

上面定义了一个整形变量和一个指针变量p,该指针变量指向a的存储单元,即p的值是a存储单元的地址。

而下面2句定义了一个整形变量a和这个整形a的引用b,事实上a和b是同一个东西,在内存占有同一个存储单

元。

(2)引用不可以为空,当被创建的时候,必须初始化,而指针可以是空值,可以在任何时候被初始化,在初始化的时候需要分配存储空间。

(3)可以有const指针,但是没有const引用;

(4)指针可以有多级,但是引用只能是一级(int **p;合法 而 int &&a是不合法的)

(5)指针的值可以为空,但是引用的值不能为NULL,并且引用在定义的时候必须初始化;

(6)指针的值在初始化后可以改变,即指向其它的存储单元,而引用在进行初始化后就不会再改变了。

(7)”sizeof引用”得到的是所指向的变量(对象)的大小,而”sizeof指针”得到的是指针本身的大小;

(8)指针和引用的自增(++)运算意义不一样;

(9)如果返回动态内存分配的对象或者内存,必须使用指针,引用可能引起内存泄漏;

4 android pid uid作用与区别


  PID:为Process Identifier, PID就是各进程的身份标识,程序一运行系统就会自动分配给进程一个独一无二的PID。进程中止后PID被系统回收,可能会被继续分配给新运行的程序,但是在android系统中一般不会把已经kill掉的进程ID重新分配给新的进程,新产生进程的进程号,一般比产生之前所有的进程号都要大。

  UID:一般理解为User Identifier,UID在linux中就是用户的ID,表明时哪个用户运行了这个程序,主要用于权限的管理。而在android 中又有所不同,因为android为单用户系统,这时UID 便被赋予了新的使命,数据共享,为了实现数据共享,android为每个应用几乎都分配了不同的UID,不像传统的linux,每个用户相同就为之分配相同的UID。(当然这也就表明了一个问题,android只能时单用户系统,在设计之初就被他们的工程师给阉割了多用户),使之成了数据共享的工具。

  因此在android中PID,和UID都是用来识别应用程序的身份的,但UID是为了不同的程序来使用共享的数据。

5 android.mk


  Android.mk是android编译系统中重要组成部分,可以看成是Makefile,再者都是完成编译功能,Anroid.mk除了可以编译linux应用外还可以编译android应用、库以及完成拷贝、编译控制等工作。

5.1 android.mk编译选项:LOCAL_MODULE_TAGS

  LOCAL_MODULE_TAGS :=user eng optional

  • user: 指该模块只在user版本下才编译
  • eng: 指该模块只在eng版本下才编译
  • optional:指该模块在所有版本下都编译

eng、user是编译android时常用的版本,调试阶段一般用eng版本。在android.mk中,如果LOCAL_MODULE_TAGS 为optional,那么在device目录下的mk的文件中的PRODUCT_PACKAGES要加上模块名,该模块才会在编译android时被编译。
  在device目录下特定product目录中会包含多个*.mk文件,有关于PRODUCT_PACKAGES变量的赋值,如下

PRODUCT_PACKAGES += \
        libril  \
        librilutils     \
        rild \
        ...

  rild源码目录在hardware/ril/rild,可以看到其Android.mk有下面两行代码,上面PRODUCT_PACKAGES变量如果不包含rild,那么rild将不会被编译,也就是不会生成rild。

LOCAL_MODULE:= rild
LOCAL_MODULE_TAGS := optional
5.2 简单Android.mk示例及说明

  编译apk、c、c++应用 

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)  # 清变量,但是不会清CAL_PATH
LOCAL_SRC_FILES := $(call all-subdir-java-files) # 当前目录、子目录下所有java文件,也可以跟目录、文件
LOCAL_SHARED_LIBRARIES := libcutils libv4l2-nexell # 依赖的C、C++动态库,只要写.so .a前的部分,两个以上用空格隔开
LOCAL_STATIC_LIBRARIES := libcamerasensor # C、C++静态库,C、C++动/静态库,编译C、C++应用才用到,apk不用
#LOCAL_STATIC_JAVA_LIBRARIES := static-library # 依赖静态.jar文件,编译apk时才用到
#LOCAL_CERTIFICATE := platform # 需要platform key签名的APK 
#LOCAL_CERTIFICATE := vendor/example/certs/app # 需要vendor key签名的APK 
LOCAL_PACKAGE_NAME := test # 编译生成test.apk或者test,test就是apk的名字
include $(BUILD_PACKAGE) # 编译app用BUILD_PACKAGE

  编译静态库  

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := test.c
LOCAL_MODULE    := libtest
include $(BUILD_STATIC_LIBRARY) # 编译C、C++静态库,生成libtest.a

  编译动态库

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := test.c
LOCAL_MODULE    := test
include $(BUILD_SHARED_LIBRARY) # 编译C、C++动态库,生成libtest.so

  编译java静态库、动态库

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_JAVA_LIBRARIES := android.test.lib # 依赖的java动态库
LOCAL_MODULE := test
include $(BUILD_STATIC_JAVA_LIBRARY) # 静态库,如果需要动态库,改成BUILD_JAVA_LIBRARY
5.3 include

  在Android.mk及android编译系统的*.mk文件,常见到include关键字,include其他的mk文件、函数、宏相,这里的include可以看成是调用。
  下面说的是-include的作用,在Android.mk文件中添加 -include test2/Android.mk,那么test2下的Android.mk会被android的编译系统忽略,test2目录下文件不会被编译。

6 android中如何找到指定apk的包名、源码位置


  使用logcat命令,在点击打开应用时会打印下面调试信息

I/ActivityManager( 2666): START u0 {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=android_serialport_api.sample/.MainMenu bnds=[512,134][656,237]} from pid 2864

  这里的cmp=android_serialport_api.sample是关键,可以在packages/apps/、device、vendor使用grep “android_serialport_api.sample”查找相关文件。
  有时候使用grep可能查找不到,使用aapt、grep从已生成的apk中找到相关的信息。脚本如下

#!/bin/bash
ROOT_DIR=`pwd`

source build/envsetup.sh
lunch sabresd_6dq-eng # 配置环境后才能使用aapt命令

cd result
for i in `find ./ -name *.apk`; # 找到result目录下所有apk
do
    echo -e "$i";
    aapt dump badging $i | grep "android_serialport_api"; # 从apk的信息中查找android_serialport_api
done

  最终找到包名为MainMenu.apk,再查找MainMenu可找到源码目录:packages/apps/MainMenu

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值