Ndk开发笔记
<pre name="code" class="cpp">ndk开发:
1.编译android本地程序的二种方法.q
2.安装ndk编译工具.
3.编写android.apk程序.
4.编写jni接口.定义应用程序接口,
5.编写Java文件,生成相应的字节码文件.
6.使用javah -jni Test 命令生成该java文件相应的c的头文件.
7.使用ndk-build命令生成相应的库文件. 一:创建一个arm本地程序.直接使用arm-linux-gcc 进行编译,假设使用到库的话须要使用 -statickeyword进行静态链接库文件. 1.编译android本地程序的三种方法:
1.使用ndk开发工具进行编译.
a)安装ndk android-ndk-r9d-linux-x86_64.tar.bz2 使用tar -xvf android-ndk-r9d-linux-x86_64.tar.bz2.
b)解压完毕须要配置环境变量:
vim ~/.bashrc
加入以下的行. export PATH=/home/zshh/android-ndk-r9d:$PATH //这个是解压后ndk所在文件文件夹/home/zshh/android-ndk-r9d
c)拷贝一个ndk的例子文件到測试文件夹.例子文件存在/home/zshh/android-ndk-r9d/samples中.
$ cd /home/zshh/android-ndk-r9d/samples 下.
$ cp -a hello-jni/ ~/work/android/JNI/
$ zshh@HP:~/work/android/JNI/hello-jni/jni$ vim Android.mk LOCAL_PATH := $(call my-dir) // LOCAL_PATH 指的是要编译的文件夹. cd ~/work/android/JNI/hello-jni/ 使用ndk-build,该文件夹指的就是~/work/android/JNI/hello-jni/文件夹.
include $(CLEAR_VARS) // 使用ndk进行编译的时候.必须指定这项.它会清空Makefile中全部的变量值.使用android源码进行编译的时候,不能使用该项.
LOCAL_MODULE := hello-jni // 编译完毕之后的模块的名称.
LOCAL_SRC_FILES := hello-jni.c // 生成模块须要的.c文件. //以下的是两者选其一.
include $(BUILD_SHARED_LIBRARY) // 指定生成什么样的文件.还是动态库文件.
include $(BUILD_EXECUTABLE) // 指定生成什么样的文件.是可运行文件 改动一下hello-jni.c输出Hello字符. 2.改动文件.生成可运行文件.
zshh@HP:~/work/android/JNI/hello-jni/jni$ vim hello-jni.c
#if 0 #endif 凝视其它文件.
改动为例如以下:
#include <string.h>
#include <jni.h>
int main(void)
{
printf("Hello\n");
return 0 ;
} zshh@HP:~/work/android/JNI/hello-jni/jni$ ndk-build
/home/zshh/work/android/JNI/hello-jni/jni/hello-jni.c:57:2: warning: incompatible implicit declaration of built-in function 'printf' [enabled by default]
进行编译会输出如上警告.是以为printf没有包括stdlib.h头文件.须要加入#include<stdlib.h>头文件. zshh@HP:~/work/android/JNI/hello-jni/jni$ ndk-build 生成例如以下文件. zshh@HP:~/work/android/JNI/hello-jni/jni$ ndk-build
[armeabi-v7a] Gdbserver : [arm-linux-androideabi-4.6] libs/armeabi-v7a/gdbserver
[armeabi-v7a] Gdbsetup : libs/armeabi-v7a/gdb.setup
[armeabi] Gdbserver : [arm-linux-androideabi-4.6] libs/armeabi/gdbserver
[armeabi] Gdbsetup : libs/armeabi/gdb.setup
[x86] Gdbserver : [x86-4.6] libs/x86/gdbserver
[x86] Gdbsetup : libs/x86/gdb.setup
[mips] Gdbserver : [mipsel-linux-android-4.6] libs/mips/gdbserver
[mips] Gdbsetup : libs/mips/gdb.setup
[armeabi-v7a] Install : hello-jni => libs/armeabi-v7a/hello-jni
[armeabi] Install : hello-jni => libs/armeabi/hello-jni
[x86] Install : hello-jni => libs/x86/hello-jni
[mips] Install : hello-jni => libs/mips/hello-jni 他会编译生成三个平台的可运行文件,平台如上. x86,mips,armeabi-v7a, 3.改动编译生成指定平台的可运行文件. zshh@HP:~/work/android/JNI/hello-jni/jni$ vim Application.mk
APP_ABI := all 这个是生成支持的三种平台的可运行文件.
APP_ABI := armeabi-v7a 仅仅会生成armeabi-v7a平台的可运行代码. 4.将生成的文件下载到开发版运行.
//开机进入系统仅仅会.检查usb是否插好.等待进入系统之后,运行挂载命令.是
zshh@HP:~/work/android/JNI/hello-jni/jni$ adb shell mount -o remount,rw /system //这个命令的作用又一次使用读写权限挂载这个文件. //切换到编译完毕的可运行文件所在文件夹.
zshh@HP:$ cd ~/work/android/JNI/hello-jni/libs/armeabi-v7a zshh@HP:~/work/android/JNI/hello-jni/libs/armeabi-v7a$ adb push hello-jni /system //将应用程序下载到开发版的/system路径下.
208 KB/s (9500 bytes in 0.044s) 5.最后測试能否成功输出,Hello.
zshh@HP:~/work/android/JNI/hello-jni/libs/armeabi-v7a$ adb shell //通过android调试桥登入android操作系统.
root@android:cd /system
root@android:/system # ./hello-jni
Hello
最后測试完毕.输出Hello. 6.假设使用编译完毕的android源码进行编译的话.须要改动Android.MK文件, a. 改动Android.mk
zshh@HP:~/work/android/JNI/hello-jni/jni$ vim Android.mk
LOCAL_PATH := $(call my-dir) // LOCAL_PATH 指的是要编译的文件夹. cd ~/work/android/JNI/hello-jni/ 使用ndk-build,该文件夹指的就是~/work/android/JNI/hello-jni/文件夹.
#include $(CLEAR_VARS) // 这项须要凝视掉,它的作用是清除MK文件里变量的值.使用android源码编译时,不须要这样做.切记凝视.
LOCAL_MODULE := hello-jni // 编译完毕之后的模块的名称.
LOCAL_SRC_FILES := hello-jni.c // 生成模块须要的.c文件. //以下的是两者选其一,指定生成什么样的文件.
include $(BUILD_SHARED_LIBRARY) // 这个是生成动态库文件.
include $(BUILD_EXECUTABLE) // 这个是生成可运行文件 zshh@HP$ cd /home/zshh/work/arm/ARM1/Android/android-4.2.2_r1 b.设置当前shell的运行环境.
zshh@HP:~/work/arm/ARM1/Android/android-4.2.2_r1$ source ~/.bashrc
zshh@HP:~/work/arm/ARM1/Android/android-4.2.2_r1$ source setenv
including device/asus/grouper/vendorsetup.sh
including device/asus/tilapia/vendorsetup.sh
including device/friendly-arm/tiny4412/vendorsetup.sh
including device/generic/armv7-a-neon/vendorsetup.sh
including device/generic/armv7-a/vendorsetup.sh
including device/generic/mips/vendorsetup.sh
including device/generic/x86/vendorsetup.sh
including device/lge/mako/vendorsetup.sh
including device/samsung/maguro/vendorsetup.sh
including device/samsung/manta/vendorsetup.sh
including device/samsung/toroplus/vendorsetup.sh
including device/samsung/toro/vendorsetup.sh
including device/ti/panda/vendorsetup.sh
including sdk/bash_completion/adb.bash c.使用mmm编译须要编译的文件夹.
zshh@HP:~/work/arm/ARM1/Android/android-4.2.2_r1$ mmm ~/work/android/JNI/jni_source_build/jni/ target Executable: hello-jni (out/target/product/tiny4412/obj/EXECUTABLES/hello-jni_intermediates/LINKED/hello-jni)
/home/zshh/work/arm/ARM1/Android/android-4.2.2_r1/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.6
/bin/../lib/gcc/arm-linux-androideabi/4.6.x-google/../../../../arm-linux-androideabi/bin/ld:
out/target/product/tiny4412/obj/lib/crtbegin_dynamic.o: in function _start:crtbrand.c(.text+0x60): error: undefined reference to '__libc_init' 假设出现的这个错误.那么须要做包括libc库,
LOCAL_SHARED_LIBRARIES :=libc
加入完毕之后的Android.mk文件例如以下
LOCAL_PATH := $(call my-dir) // LOCAL_PATH 指的是要编译的文件夹. cd ~/work/android/JNI/hello-jni/ 使用ndk-build,该文件夹指的就是~/work/android/JNI/hello-jni/文件夹.
#include $(CLEAR_VARS) // 这项须要凝视掉,它的作用是清除MK文件里变量的值.使用android源码编译时,不须要这样做.切记凝视.
LOCAL_MODULE := hello-jni // 编译完毕之后的模块的名称.
LOCAL_SRC_FILES := hello-jni.c // 生成模块须要的.c文件.
LOCAL_SHARED_LIBRARIES :=libc
//以下的是两者选其一,指定生成什么样的文件.
include $(BUILD_SHARED_LIBRARY) // 这个是生成动态库文件.
include $(BUILD_EXECUTABLE) // 这个是生成可运行文件 zshh@HP:~/work/arm/ARM1/Android/android-4.2.2_r1$ mmm ~/work/android/JNI/jni_source_build/jni/'
Install: out/target/product/tiny4412/system/bin/hello-jni
假设成功编译,生成的目标文件存在hello-jni文件out/target/product/tiny4412/system/bin/hello-jni d.接下来的步骤,和步骤5.是一样的. 二:创建一个NDK本地程序. 该程序的功能是控制led的亮灭.
1.搭建一个eclipse环境.eclipse.tar.gz
a.解压这文件.
zshh@HP:~/work/android$ tar -xvf eclipse.tar.gz -C software //解压
zshh@HP:~/work/android$ cd software/eclipse/
zshh@HP:~/work/android/software/eclipse$ ./eclipse & //运行eclipse
b.使用这个ide环境创建一个android apk应用程序.
它大概的功能是提供四个button,当按下当中某个button的时候,就让某个灯亮起来. c.创建一个Test文件,当中包括接口文件例如以下:
1.定义c和java之间的接口.控制亮灭,
1.1.第一个接口应该是打开设备文件.
native int openLed();
1.2.最后一个是关闭设备文件.
native int closeLed();
1.3.第二个接口应该是亮,
native int ledOn(int no);
1.4.第三个接口应该是灭.
native int ledOff(int no); 2.
zshh@HP:~/work/android/JNI/NDKnative$ vim Test.java
/*************************************************************************
> File Name: Test.java
> Author: zshh0604
> Mail: zshh0604@.com
> Created Time: Mon 22 Dec 2014 10:48:09 PM
************************************************************************/
public class Test
{
native int openLed();
native int closeLed();
native int onLed(int no);
native int offLed(int no); static{
System.loadLibrary("led");
} public static void main(String[] args)
{ }
} 3.编译生成字节码文件.
zshh@HP:~/work/android/JNI/NDKnative$ javac Test.java 4.生成相应的头文件,该命令运行完毕之后.会生成Test.h头文件.
zshh@HP:~/work/android/JNI/NDKnative$ javah -jni Test 5.拷贝一个NDK代码例子.并把Test.h头文件复制到当前文件的jni文件夹中.
zshh@HP:~/work/android/JNI$ mkdir Jni 6.获取ndk开发工具的代码例子.
zshh@HP:~/work/android/JNI/Jni$ cp -a ../../../../android-ndk-r9d/samples/hello-jni/ ./
zshh@HP:~/work/android/JNI/Jni/jni$ cp ../../NDKnative/Test.h 7.将Test.h改名为led.c, mv Test.h led.c
zshh@HP:~/work/android/JNI/Jni/jni$ mv Test.h led.c 8.获取apk应用的完整类名.com_embsky_MainActivity //讲这个名称替换当前Test类名.
使用vim打开led.c文件,再命令行模式下使用例如以下命令吧Test替换成com_embsky_MainActivity :%s/Test/com_embsky_MainActivity/g.
得到例如以下文件:
#include <jni.h>
#include <sys/types.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h> static int fd;
static int flags = 0;
/*
* Class: com_embsky_MainActivity
* Method: openLed
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_embsky_MainActivity_openLed
(JNIEnv *env, jobject obj)
{
if(flags == 0)
{
fd = open("dev/leds",O_RDWR);
if(fd< 0)
{
return -EPERM;
}
flags = 1;
return 0 ;
}
return -EBUSY;
} /*
* Class: com_embsky_MainActivity
* Method: closeLed
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_embsky_MainActivity_closeLed
(JNIEnv *env , jobject obj)
{
if(flags == 1)
{
close(fd);
flags = 0;
return 0;
}
return -ENODEV;
} /*
* Class: com_embsky_MainActivity
* Method: onLed
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_com_embsky_MainActivity_onLed
(JNIEnv *env , jobject obj, jint no)
{
int ret;
if(flags == 1)
{
ret = ioctl(fd,1 ,no);
if(ret < 0 )
{
return -EPERM;
}
return 0 ;
}
return -ENODEV;
} /*
* Class: com_embsky_MainActivity
* Method: offLed
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_com_embsky_MainActivity_offLed
(JNIEnv * env, jobject obj, jint no)
{
int ret;
if(flags == 1)
{
ret = ioctl(fd, 0, no);
if(ret < 0)
{
return -EPERM;
}
return 0;
}
return -ENODEV;
} 9.改动Android.mk文件,例如以下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := leds
LOCAL_SRC_FILES := led.c
include $(BUILD_SHARED_LIBRARY) 10.zshh@HP:~/work/android/JNI/Jni/jni$ ndk-build 11.生成动态库例如以下:[armeabi-v7a] Install : libleds.so => libs/armeabi-v7a/libleds.so 12.将动态库push到开发板的/system/lib文件夹下.
zshh@HP:~/work/android/JNI/Jni/libs/armeabi-v7a$ adb push libleds.so /system/lib 13.动态库制作完毕. 14.创建一个apk应用,创建一个类: com.embsky.MainActivity.再这个类中载入并调用本地库led. javah -d ../jni com.onesuncomm.JniCallCTest 三: 使用android源码编译apk应用程序.System.loadLibaray("led"); zshh@HP:~/work/android/android/07Jar/JniAndroidSrc$ ls
Android.mk led.c 使用这两个文件编译生成libled.so文件. //zshh@HP:~/work/android/android/06Jni/JniAndroidSrc$ vim Android.mk。
仅仅须要。Android.mk和led.c两个文件. 1.使用android源码编译android应用程序,
LOCAL_PATH := $(call my-dir)
LOCAL_MODULE := libled //注意必须是在led前面加上lib,编译生成的库名是.libled.so,使用
LOCAL_SRC_FILES := led.c
LOCAL_SHARED_LIBRARIES :=libc
include $(BUILD_SHARED_LIBRARY) 2.编译libled.so库文件.
zshh@HP:~/work/arm/ARM1/Android/android-4.2.2_r1$ source setenv
zshh@HP:~/work/arm/ARM1/Android/android-4.2.2_r1$ mmm ~/work/android/android/06Jni/JniAndroidSrc/ 3.输出编译完毕的路径例如以下.
Install: out/target/product/tiny4412/system/lib/libled.so
4.将生成的libled.so push到/system/lib中.
Install: out/target/product/tiny4412/system/lib/libled.so
zshh@HP:~/work/arm/ARM1/Android/android-4.2.2_r1/out/target/product/tiny4412/system/lib$ adb push libled.so /system/lib/
115 KB/s (5276 bytes in 0.044s) 5.生成Android fremework文件夹的 jar包。
zshh@HP:~/work/android/android/07Jar/Jar$ ls
Android.mk com/embsky/Led.java //包括两个java文件. package com.embsky;
public class Led {
native int openLed();
native int closeLed();
native int ledOn(int no);
native int ledOff(int no); static {
System.loadLibrary("led");
} public int ledStart(){
/*nothing*/
return openLed();
} public int ledStop(){
return closeLed();
} public int ledOps(int no, int on){
if(on == 1){
return ledOn(no);
} return ledOff(no);
}
} 6.改动Android.mk文件.
LOCAL_PATH :=$(call my-dir)
LOCAL_SRC_FILES :=$(call all-subdir-java-files) //当前src文件夹下的全部文件.
LOCAL_MODULE :=led
LOCAL_JAVA_LIBRARIES :=
include $(BUILD_JAVA_LIBRARY) //包括这个生成的是Java的类库. 7.完毕之后。能够编译生成这个.jar文件.
zshh@HP:~/work/arm/ARM1/Android/android-4.2.2_r1$ source setenv
zshh@HP:~/work/arm/ARM1/Android/android-4.2.2_r1$ mmm ~/work/android/android/07Jar/Jar/ 8. 生成的jar包会存放在,
Install: out/target/product/tiny4412/system/framework/led.jar
注意编译的时候,该文件夹一定要由读写权限.否则会失败.
假设由于权限问题。能够使用chown zshh:zshh out/target/product/tiny4412/system/framework -R
更改用户属主.
生成完毕之后须要将这个framework下的led.jar放到开发版的/system/framework文件夹下.
zshh@HP:~/work/arm/ARM1/Android/android-4.2.2_r1/out/target/product/tiny4412/system/framework$ adb push led.jar /system/framework/ 9.须要改动开发板中 /etc/permissions //再platform.xml文件里声明我们的框架库文件.否则这个led.jar无法使用.
root@android:/etc/permissions # vim platform.xml
<library name="led" file="/system/framework/led.jar"/>
之后重新启动一下开发版, 10.编译android apk zshh@HP:~/work/android/android/07Jar/Apk$ ls //apk包括例如以下文件和文件夹.
AndroidManifest.xml Android.mk res src
须要改动AndroidManifest.xml文件.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.embsky"
android:versionCode="1"
android:versionName="1.0" > <uses-sdk
android:minSdkVersion="17"
android:targetSdkVersion="17" /> <application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<uses-library android:name="led" /> //声明依赖的led.jar文件.假设不声明能够编译通过,但运行会由错误.
<activity
android:name="com.embsky.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest> 11.zshh@HP:~/work/android/android/07Jar/Apk$ gedit Android.mk
LOCAL_PATH :=$(call my-dir)
LOCAL_SRC_FILES :=$(call all-subdir-java-files)
LOCAL_PACKAGE_NAME :=Led
LOCAL_JAVA_LIBRARIES :=led //注意这里必须声明依赖的java库.
include $(BUILD_PACKAGE)
12.zshh@HP:~/work/arm/ARM1/Android/android-4.2.2_r1$ mmm ~/work/android/android/07Jar/Apk/
这个是编译生成的apk文件Install: out/target/product/tiny4412/system/app/Led.apk
zshh@HP:~/work/arm/ARM1/Android/android-4.2.2_r1/out/target/product/tiny4412/system/app$ adb push Led.apk /system/app/
5099 KB/s (294516 bytes in 0.056s)
Ndk开发笔记的更多相关文章
- [笔记] Android NDK 开发笔记
学习下Android NDK的开发,做些笔记记录下. [笔记] Windows下使用Android Studio 创建缺省工程 [笔记] Windows下使用Android Studio开发NDK的最 ...
- NDK开发_笔记0
自谷歌搜索退出中国以来,谷歌对全球第二大市场中国的态度一直保持冷淡.可是北京时间12月8日,谷歌2016开发者大会在北京召开,同时专门针对中国的谷歌开发者网站已经上线:https://develope ...
- Android NDK开发及OpenCV初步学习笔记
https://www.jianshu.com/p/c29bb20908da Android NDK开发及OpenCV初步学习笔记 Super_圣代 关注 2017.08.19 00:55* 字数 6 ...
- Android(java)学习笔记259:JNI之NDK开发步骤
1. NDK开发步骤(回忆一下HelloWorld案例): (1)创建工程 (2)定义native方法 (3)创建jni文件夹 (4)创建c源文件放到jni文件夹 (5)拷贝jni.h头文件到jni目 ...
- Android(java)学习笔记203:JNI之NDK开发步骤
1. NDK开发步骤(回忆一下HelloWorld案例): (1)创建工程 (2)定义native方法 (3)创建jni文件夹 (4)创建c源文件放到jni文件夹 (5)拷贝jni.h头文件到jni目 ...
- Android NDK 开发(三)--常见错误锦集合Log的使用【转】
转载请注明出处:http://blog.csdn.net/allen315410/article/details/41826511 Android NDK开发经常因某些因素会出现一些意想不到的错误, ...
- Android SDK NDK开发总结
描述:http://talent.baidu.com/external/baidu/index.html#/jobDetail/2/1237247043 android studio实现Jni(C/C ...
- Android NDK开发Hello Word!
在之前的博客中已经为大家介绍了,如何在win环境下配置DNK程序,本篇我将带大家实现一个简单的Hello jni程序,让大家真正感受一下NDK开发的魅力.这里我们选择使用C+JAVA开发Android ...
- Android NDK开发初识
神秘的Android NDK开发往往众多程序员感到兴奋,但又不知它为何物,由于近期开发应用时,为了是开发的.apk文件不被他人解读(反编译),查阅了很多资料,其中有提到使用NDK开发,怀着好奇的心理, ...
随机推荐
- QT开发之旅-Udp聊天室编程
一.概要设计 登录对话框(继承自QDialog类)进行用户登录查询数据库用户是否存在,注册插入数据到用户表.用户表字段: (chatid int primary key, passwd varchar ...
- tensorboard在windows系统浏览器显示空白的解决
一个简单的using_tensorboard.py程序,如下: #using_tensorboard.py import tensorflow as tf a = tf.constant(10,nam ...
- Masonry 原理与使用说明
原理: 1)约束生成:MASConstraintMaker: 2)缺省补齐: - (void)setSecondViewAttribute:(id)secondViewAttribute { if ( ...
- 11Java Server Pages 动作
Java Server Pages 动作 JSP标准动作 分类 JSP标准动作 存取JavaBean相关 <jsp:useBean> <jsp:setProperty> < ...
- UVA - 12589 Learning Vector(dp-01背包)
题目: 思路: dp[j][h]表示选取了j个向量,且高度为h,利用01背包来解决问题. 没选当前的向量:dp[j][h] = dp[j][h]; 选了当前的向量:dp[j][h] = dp[j-1] ...
- Python使用Flask框架,结合Highchart处理jsonl数据
1.html代码 <!DOCTYPE html> <html lang="en"> <head> <meta charset=" ...
- CentOS7 安装、配置 Memcached
点击访问原文地址 介绍 Memcached 是一个分布式.高性能的内存缓存系统,通过缓存内存中的数据和对象,提高和加速动态 web 应用程序的性能.它主要用于加速对数据库重度使用的站点. Memcac ...
- radis入门
redis介绍 是远程的,有客户端.服务端 存内存,吃内存 应用场景 缓存 队列 list操作 push pop 数据存储[根据redis硬盘持久化的机制,这里不展开] 5种数据类型 string 字 ...
- 常用的HTTP测试工具谷歌浏览器插件汇总
网页的开发和测试时最常见的测试就是HTTP测试,作为曾经的测试人员在这方面还是略知一二的.其实做网页测试工作是非常繁琐的时期,有时候甚至是无聊重复的,如果没有网页测试工具的帮助的话,测试人员会越做越怀 ...
- power coefficient calculation -- post processing
input: unscaled moment of one bladeoutput: power coefficient of a 3-blades wind/tidal turbine matlab ...