分类 android framework 下的文章

Android应用程序如何导入到android源码树

软硬件环境

  • OTT BOx with android 5.1.1

前言

在做android开发时,有时需要事先将应用程序烧写到板子上去而不必让用户在板子出厂后自行安装。将应用导入到android源码树可以分为两种情况:应用的apk文件和工程源码,下面将一一介绍。

APK文件形式导入

这种方式最简单,app源码与android源码分开管理,互不相干。App发布后,再放进android源码库中编译打包。主要有一下几个步骤

在应用程序所在目录创建文件夹

一般是packages/apps/这个目录或者厂家自己存放apps的位置

mkdir Hello
将Hello.apk拷贝到刚才所创建的文件夹下
copy Hello.apk Hello
在apk同级创建Android.mk文件
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
    
LOCAL_MODULE := Hello.apk
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE_CLASS := EXECUTABLE
LOCAL_MODULE_PATH := $(TARGET_OUT_APPS)
LOCAL_SRC_FILES := $(LOCAL_MODULE)
到android根目录进行编译
make

应用源码形式导入

在应用程序所在目录创建文件夹

一般是packages/apps/这个目录或者厂家自己存放apps的位置

mkdir Hello
将工程源码拷贝到Hello文件夹下
copy -rf Hello/* Hello/
新建Android.mk文件
LOCAL_PATH:= $(call my-dir) 
include $(CLEAR_VARS)

LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_PACKAGE_NAME := Hello
LOCAL_MODULE_TAGS := eng 
    
include $(BUILD_PACKAGE)
到android根目录进行编译
make
如果java中调用了c库,则工程中会有个jni目录

source_tree_01

这里的Android.mk是用来编译C文件产生lib*.so的,如

LOCAL_PATH := $(call my-dir) 
include $(CLEAR_VARS) 

# java中System.loadLibray()使用 
LOCAL_MODULE := SerialPort
LOCAL_SRC_FILES := SerialPort.c     
LOCAL_LDLIBS := -llog 
include $(BUILD_SHARED_LIBRARY)
此时工程的Android.mk可如下
LOCAL_PATH:= $(call my-dir) 
include $(CLEAR_VARS) 
LOCAL_MODULE_TAGS := eng 
LOCAL_SRC_FILES := $(call all-java-files-under, src) 
LOCAL_PACKAGE_NAME := testApp 
LOCAL_CERTIFICATE := platform 
LOCAL_JNI_SHARED_LIBRARIES := libserial_port 
LOCAL_PROGUARD_ENABLED := disabled 
include $(BUILD_PACKAGE) 
include $(call all-makefiles-under,$(LOCAL_PATH))
重新编译
make

关于作者

Website: http://www.xugaoxiang.com
Github: https://github.com/djstava
Email: djstava@gmail.com

Android开机执行C程序

软硬件环境

  • OTT BOx with android 5.1.1

前言

之前的Android开机执行shell脚本介绍了如何在android系统开机时执行特定的shell脚本文件,不过在某些情况下不适合用shell实现,又不好做成jni动态库由app调用,这时用C语言程序来实现就有可能帮上你,本文就以创建文件夹为例,来实现android开机启动C可执行程序。

实现步骤

在Android源码中创建文件夹
cd android_src/external
mkdir djstava
创建C源文件及Android.mk

首先是写源码文件test.c

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int ret = mkdir("/system/djstava");//请确保你的用户有对相应目录的权限
    if(ret == -1)
    {
        printf("mkdir failed!\n");
        return -1;
    }
    return 0;
}

这里如果你的system分区只读,可以换成/data/djstava作为测试用

接下来就是Android.mk文件

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := eng 
LOCAL_MODULE := djstava 
LOCAL_SRC_FILES := $(call all-subdir-c-files)
include $(BUILD_EXECUTABLE)
修改Android开机脚本文件init.${platform}.rc文件,增加
service djstava_test /system/bin/djstava
    class main
    user root
    group root
    oneshot
重新编译源码并打包
cd android_src
make
刷机并测试

看看文件夹/system/djstava(或者/data/djstava)是否已经被创建好了。

关于作者

Website: http://www.xugaoxiang.com
Github: https://github.com/djstava
Email: djstava@gmail.com

Android开机执行shell脚本

软硬件环境

  • OTT BOx with android 5.1.1

前言

在应用程序启动之前,往往需要在Android启动过程中去对系统做一些设置,如修改某些文件夹的属主和文件的权限等。本文实现在init.*.rc中调用shell脚本,而所有对系统资源的修改和配置都在此shell脚本中实现,最后讲一下关闭android selinux的三种方法。

Shell脚本

这里以创建蓝牙设备结点为例,shell文件名为makebtusb0.sh,在脚本中创建结点,然后修改结点属性,具体如下

#! /system/bin/sh

mknod /dev/btusb0 c 180 194
chmod 777 /dev/btusb0

修改init.${platform}.rc文件

这个文件一般是放在device目录下,如果没有的话,也可以直接加到init.rc中

service makenode /system/etc/makebtusb0.sh
    class main
    user root
    group root 
    oneshot

上述命令中,包含一些android init language的知识点,如果想了解的话,请见参考资料1,写得非常详细。

关闭Android selinux的几种方法

刚好在集成蓝牙驱动中碰到了这个问题,就在这里一并记录下,希望其他朋友少走弯路

方法一
setenforce 0
方法二
echo 0 > /sys/fs/selinux/enforce
方法三

编辑BoardConfig.mk

BOARD_KERNEL_CMDLINE := console=ttyS0,115200n8 androidboot.hardware=zx2000 androidboot.serialno=01234567890123456789 androidboot.selinux=permissive

方法一和方法二适合在终端中执行,当然放在这篇文章中,也可以利用shell脚本实现。方法三在源码中设定,编译打包镜像后就不用再做设置,推荐用这种方法。

关于作者

Website: http://www.xugaoxiang.com
Github: https://github.com/djstava
Email: djstava@gmail.com

参考资料

https://www.kancloud.cn/digest/shichang-framework/131973

Android应用获取设备序列号

软硬件环境

  • Macbook Pro MGX 72
  • Android studio 2.1.2
  • Android 5.1.1

前言

上一篇介绍了如何获取ethernet的MAC地址,对于厂商来讲,除了MAC号,还有一项数据也很重要,那就是机器序列号,它是机器出厂时确定的,也是主要标识,每台机器都不一样。
要想获取到序列号,必须要先知道序列号从哪里来,写到了哪里。一般情况下,序列号都是厂商自己定义的一串字串,字串中的某几位会有不同含义,比如厂商的ID、出厂时间、机器类型等,另外,运营商定义的序列号几乎也是遵循这样的规律。

出厂时序列号的烧录

这个是烧录程序做的事情。首先,需要设计好flashmap,一般来讲,会拿出一块独立的分区用来存储这些固化信息,这些信息一经烧录,就不会去改变。android镜像中的boot.img、system.img、userdata.img等等也是存放在这样的分区中。Android系统的烧录,一般会采用fastboot去做,简单、方便、快捷。

uboot获取序列号

序列号写入到了flash后,uboot就有办法获取到,然后uboot就可以将其以(key,value)的形式传递给kernel,当然传给kernel的参数并非只有序列号,所以如果你需要传一些自定义的数据,同样也可以通过这种方法去实现。在Android中,传递的是androidboot.ro.serialno。

android app中获取序列号

综上所述,在App中去获取序列号,实际上就是去获取android ro属性中的某个值,明白了这点,事情就好办了。看下面的代码实现

private String getSerialNumber(){
    String serial = null;
    try {
        Class<?> c =Class.forName("android.os.SystemProperties");
        Method get =c.getMethod("get", String.class);
        serial = (String)get.invoke(c, "ro.serialno");
    } catch (Exception e) {
        e.printStackTrace();
    }
    return serial;
}

一点扩展

android中的init.$其中{hardware}.rc,其中$(hardware)是各芯片厂商自己的标识。在这个文件中,可以通过setprop命令设置一些系统属性信息,比如mac、厂商id等,然后在android应用中同样可以通过上述方法去获取相应的

Android TV中获取有线网卡的MAC地址

软硬件环境

  • Macbook Pro MGX 72
  • Android studio 2.1.2
  • Android 5.1.1

前言

在带有Ethernet的Android设备中,在系统信息页面上都会去显示其对应的MAC地址,本文就去解决这个问题。

部分代码

//通过解析这个文件来获取MAC,不同厂家的芯片有可能不同
private static final String ETH0_MAC_ADDR = "/sys/class/net/eth0/address" ;

/*
* 获取mac号
* */
private String getWireMacAddr() {
    try {
        return readLine(ETH0_MAC_ADDR);
    } catch (IOException e) {
        Log.e(TAG,
                "IO Exception when getting eth0 mac address",
                e);
        e.printStackTrace();
        return "unavailable";
    }
}

private static String readLine(String filename) throws IOException {
    BufferedReader reader = new BufferedReader(new FileReader(filename), 256);
    try {
        return reader.readLine();
    } finally {
        reader.close();
    }
}