3-安卓底層-實(shí)現(xiàn)安卓控制LED

安卓源碼目錄:

abi     bootable  dalvik       device    frameworks  libnativehelper  ndk       pdk        system
art     build     developers   docs      hardware    Makefile         out       prebuilts
bionic  cts       development  external  libcore     modules          packages  sdk
  • build :
  • build 目錄中存放的是編譯系統(tǒng)mk文件,編譯規(guī)則和generic產(chǎn)品基礎(chǔ)配置文件
  • device :
  • device 是和設(shè)備平臺(tái)先關(guān)的代碼 比如傳感器的hal camera 的hal 代碼
  • frameworks :
  • frameworks 核心框架——java及C++語(yǔ)言,是Android應(yīng)用程序的框架
  • system :
  • system Android根文件系統(tǒng)相關(guān)源碼,如:init、adb、toolbox及一些庫(kù)
  • out :
  • out 輸出文件的目錄
  • external
  • external Android使用的一些開(kāi)源的模塊代碼

* 重要 : device frameworks hardware


1.配置

配置編譯android環(huán)境分為以下幾部

source build/envsetup.sh 配置環(huán)境變量加載分支

2.選擇分支

lunch 選擇分支

You're building on Linux

Lunch menu... pick a combo:
     1. aosp_arm-eng
     2. aosp_arm64-eng
     3. aosp_mips-eng
     4. aosp_mips64-eng
     5. aosp_x86-eng
     6. aosp_x86_64-eng
     7. fspad_733-eng
     8. fspad_733-user

Which would you like? [aosp_arm-eng] 7

PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=5.0  android 版本號(hào)
TARGET_PRODUCT=fspad_733 廠家產(chǎn)品
TARGET_BUILD_VARIANT=eng android 發(fā)行類(lèi)別
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=arm 平臺(tái)
TARGET_ARCH_VARIANT=armv7-a-neon 平臺(tái)架構(gòu)
TARGET_CPU_VARIANT=cortex-a7 硬件編號(hào)
TARGET_2ND_ARCH=
TARGET_2ND_ARCH_VARIANT=
TARGET_2ND_CPU_VARIANT=
HOST_ARCH=x86_64 宿主機(jī)
HOST_OS=linux
HOST_OS_EXTRA=Linux-3.16.0-30-generic-x86_64-with-Ubuntu-14.04-trusty 宿主機(jī)內(nèi)核版本
HOST_BUILD_TYPE=release
BUILD_ID=LRX21V
OUT_DIR=out  指定的輸出目錄
3.編譯android源碼

make 編譯android源碼

Android.mk
  • m編譯全部
  • mm只編譯當(dāng)前目錄
  • mmm編譯指定目錄
1 LOCAL_PATH := $(call my-dir) 獲得androidmk路徑
2 include $(CLEAR_VARS) 清空除了 local_path 之外的環(huán)境變量
3 LOCAL_MODULE := test 要生成的目標(biāo)
4 LOCAL_SRC_FILES := test.c 目標(biāo)依賴(lài)的源文件
5 LOCAL_MODULE_TAGS := eng    發(fā)行類(lèi)型
6 include $(BUILD_EXECUTABLE) 生成的目標(biāo)文件的類(lèi)型
發(fā)行類(lèi)型

user: 指該模塊只在user版本下才編譯

eng: 指該模塊只在eng版本下才編譯

tests: 指該模塊只在tests版本下才編譯

optional:指該模塊在所有版本下都編譯

一般的我們這樣定義存放文件的目錄的名字

  • 源代碼 src 頭文件 inc 可執(zhí)行程序 bin 庫(kù) lib

adb 工具的使用

DOS 命令與linux命令 :
windows linux
cd cd 切換路徑
dir ls 查看當(dāng)前路徑
del rm 刪除
cp cp 拷貝
d: 進(jìn)入D盤(pán)

1.解壓 fastboot 到D盤(pán)根目錄下

2.通過(guò) dos終端 進(jìn)入fastboot 目錄下

3.在fastboot 目錄下 執(zhí)行 adb devices 列出已連接的所有設(shè)備串號(hào)

4.adb shell 進(jìn)入android 后臺(tái)終端

5.exit 退出終端

adb push test /data 從window 上傳到 android

adb pull /data/test 從android 下載到 windows

打印log信息的函數(shù)原型與使用
int __android_log_print(int prio, const char *tag,  const char *fmt, ...)

typedef enum android_LogPriority {
 80     ANDROID_LOG_UNKNOWN = 0,
 81     ANDROID_LOG_DEFAULT,    /* only for SetMinPriority() */
 82     ANDROID_LOG_VERBOSE,
 83     ANDROID_LOG_DEBUG,
 84     ANDROID_LOG_INFO,
 85     ANDROID_LOG_WARN,
 86     ANDROID_LOG_ERROR,
 87     ANDROID_LOG_FATAL,
 88     ANDROID_LOG_SILENT,     /* only for SetMinPriority(); must be last */
 89 } android_LogPriority;

//要包含 #include<android/log.h>
 __android_log_print(ANDROID_LOG_INFO, "aaaaaaa" , "******fd = %d",fd);

//mk文件必須要加liblog系統(tǒng)庫(kù)
1 LOCAL_PATH := $(call my-dir)
2 include $(CLEAR_VARS)
3 LOCAL_MODULE:= libnative
4 LOCAL_SRC_FILES:= src/native.c
5 LOCAL_MODULE_TAGS:= eng
6 LOCAL_SHARED_LIBRARIES:= liblog      當(dāng)使用android 系統(tǒng)庫(kù)是使用   LOCAL_SHARED_LIBRARIES 來(lái)指定使用庫(kù)的名稱(chēng)
7 LOCAL_MODULE_PATH:= $(LOCAL_PATH)/lib
8 include $(BUILD_SHARED_LIBRARY)

實(shí)現(xiàn)安卓應(yīng)用控制LED

  1. 寫(xiě)jni 將iboled.c 生成 libiboled.so 上傳到 android 平板的 /system/lib 目錄下
  • 如果出現(xiàn) /system/lib 只讀則執(zhí)行:mount -o rw,remount -t ext4 /dev/block/by-name/system
  1. 寫(xiě)一個(gè)安卓應(yīng)用 , 調(diào)用jni方法。

iboled.c

#include <jni.h>
#include <android/log.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/ioctl.h>

#define LED_OFF _IO('k',0)
#define LED_ON  _IO('k',1)

int fd;

jint Jopen(JNIEnv *env,jobject obj,jstring dev){
    const jbyte *str;
    str = (*env)->GetStringUTFChars(env, dev, NULL);
    if (str == NULL) return -1;

    fd = open(str,O_RDWR);
    if (fd < 0) {
        __android_log_print(ANDROID_LOG_INFO, "openFailed", "openFailed %d \n",fd);
        return -1;
    }else{
        __android_log_print(ANDROID_LOG_INFO, "openSeccus", "openSeccus %d \n",fd);
    }

    return fd;
}
void Jioctl(JNIEnv *env,jobject obj,jint cmd){
    if (cmd == 1) ioctl(fd,LED_ON);
    else ioctl(fd,LED_OFF);
    __android_log_print(ANDROID_LOG_INFO, "ioctl", "cmd = %d \n",cmd);
    return;
}
void Jclose(JNIEnv *env,jobject obj){
    close(fd);
    return;
}

JNINativeMethod methods[]={
    "open","(Ljava/lang/String;)I",(void *)Jopen,
    "close","()V",(void *)Jclose,
    "ioctl","(I)V",(void *)Jioctl,
};

JNIEXPORT jint JNICALL
JNI_OnLoad(JavaVM *vm, void *reserved){
    JNIEnv *env;
    jclass cls;

    (*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_2);
    if(env == NULL) return JNI_ERR;

    cls = (*env)->FindClass(env, "com/ibo/jnidemo/TestJni");
    if(cls == NULL) return JNI_ERR;

    (*env)->RegisterNatives(env, cls,methods, sizeof(methods)/sizeof(JNINativeMethod));

    return JNI_VERSION_1_2;
}

Android.mk

LOCAL_PATH :=$(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE :=libiboled
LOCAL_SRC_FILES :=src/iboled.c
LOCAL_MODULE_TAGS :=eng
LOCAL_SHARED_LIBRARIES :=liblog
LOCAL_MODULE_PATH :=$(LOCAL_PATH)/lib
include $(BUILD_SHARED_LIBRARY)

1.寫(xiě)完 Android.mk 之后 執(zhí)行 mm 生成 libiboled.so

2. libiboled.so 復(fù)制到 fastboot 根目錄

3.執(zhí)行 adb push libiboled.so system/lib 上傳到 android 平板的 /system/lib 目錄下

TestJni.java

package com.ibo.jnidemo;

class TestJni{
    static{
        System.loadLibrary("iboled");
    }

    public native int open(String dev);
    public native void close();
    public native void ioctl(int cmd);
}

MainActivity.java

package com.ibo.jnidemo;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Button btn;
    boolean isLight = false;
    private TestJni ibo;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ibo = new TestJni();
        int open = ibo.open("/dev/led");
        if (open<0){
            System.out.println("####  open error ! "+open);
            return;
        }

        btn = (Button) findViewById(R.id.btn);
        btn.setOnClickListener(this);
    }

    @Override
    protected void onDestroy() {
        ibo.ioctl(0);
        ibo.close();
        super.onDestroy();
    }

    @Override
    public void onClick(View v) {
        if (isLight){
            isLight=false;
            ibo.ioctl(0);
            btn.setText("on");
        }else{
            isLight=true;
            ibo.ioctl(1);
            btn.setText("off");
        }
    }
}

4.運(yùn)行,完成了~

結(jié)束


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容