首页 技术 正文
技术 2022年11月9日
0 收藏 906 点赞 2,947 浏览 4853 个字

本文将介绍如何使用eclipse和ndk-build来编写一个基于Android4.4版本的包含有.so动态库的安卓程序。

前提是已经安装和配置好了诸如SDK,NDK等编译环境。下面开始编程!

1 程序逻辑

我们要编写的程序包含两部分:java部分——负责界面和调用JNI native函数;JNI native 部分——负责native函数的具体实现(本文使用C语言)。

native 函数伪代码如下:

/*
funtion: 传入两个整形变量,计算他们之和
return : 返回字符串“The result is ” +sum
*/
char* test(int fisrt, int second){
sum = first + scond;
return “The result is ” +sum;
}

2 程序实现

2.1 创建项目

如编写普通apk一样创建一个apk项目。然后在该项目的根目录添加一个文件夹 jni,然后在这个文件夹下面添加hello.c和Android.mk两个文件,完成效果如下图所示:

Android jni 编程入门

2.2 开始JNI编程

hello.c代码如下:

 /*hello.c*/
1 #include <string.h>
#include <stdio.h>
#include <jni.h> //一定不要忘了 JNIEXPORT关键字!
JNIEXPORT jstring Java_com_wan_firstjniprogram_MainActivity_test( JNIEnv* env,
jobject thiz , jint first, jint second)
{
#if defined(__arm__)
#if defined(__ARM_ARCH_7A__)
#if defined(__ARM_NEON__)
#define ABI "armeabi-v7a/NEON"
#else
#define ABI "armeabi-v7a"
#endif
#else
#define ABI "armeabi"
#endif
#elif defined(__i386__)
#define ABI "x86"
#elif defined(__mips__)
#define ABI "mips"
#else
#define ABI "unknown"
#endif const char* format = "The result is %d\n";
char *ret;
//add two values
jint sum = first + second;
//malloc room for the ret
ret = malloc(sizeof(format) + );
//standard sprintf
sprintf(ret, format, sum);
jstring stringRet = (*env)->NewStringUTF(env, ret);
free(ret);
return stringRet;
}

关于JNI函数名的编写,网上有很多资料,这里主要提醒两点:1、包名需要全小写,类名和函数名要大小写一致;2、一定要在函数名前加上关键字 JNIEXPORT 。

再来编写Android.mk,代码如下:

 LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE    := hello
LOCAL_SRC_FILES := hello.c include $(BUILD_SHARED_LIBRARY)

如何编写Android.mk就不过多解释了,网上资料也是一大堆,这里直接给出代码。

现在,我们的JNI 编写代码部分算是结束了,就还剩下最后一步——编译。编译很简单:使用cmd命令行进入你的apk工程所在的文件夹的jni目录(我的目录是D:\androidWorkSpace\firstJniProgram\jni),然后输入ndk-build命令即可自动编译,结果如下图所示:

Android jni 编程入门

从上图可以看出,我们已经成功生成了libhello.so库。到这里,JNI编程部分已经完结。下面就是进入JAVA部分了。

2.2 java编写

如何编写界面我就不多说了,这里指出我所遇到的一个问题。

问题:由于Android4.4的apk项目会创建两个layout.xml布局文件,如下图所示:

Android jni 编程入门且首先展示给developer的是fragment_main.xml。这同Android2.3.3是不一样的(默认只有一个布局文件——activity_main.xml)!所以如果要添加组件的话,最好添加到activity_main中,这样才不会发生各种activity错误~。

activity_main.xml代码如下:

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.wan.firstjniprogram.MainActivity"
tools:ignore="MergeRootFrame" > <TextView
android:id="@+id/info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text ="JNItest"/> </LinearLayout>

下面展示MainActivity.java的代码:

 package com.wan.firstjniprogram; import junit.framework.Test;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.ActionBar;
import android.support.v4.app.Fragment;
import android.R.string;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView; public class MainActivity extends ActionBarActivity { static{
System.loadLibrary("hello");
} public native String test(int first, int second); private TextView info = null;
private Button button = null; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment())
.commit();
} this.info = (TextView)super.findViewById(R.id.info);
this.button = (Button)super.findViewById(R.id.button); this.button.setOnClickListener(new MyonclickListen()); } private class MyonclickListen implements OnClickListener{ @Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
//MainActivity.this.info.setText("123"/*test(1, 2)*/);
int first = 1, second = 2;
String ret = test(first, second);
MainActivity.this.info.setText(ret);
} } @Override
public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
} @Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
} /**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment { public PlaceholderFragment() {
} @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
return rootView;
}
} }

OK!到此,整个程序的代码已经编写完毕,可以鼠标右击项目,run as->android application了。点击JNItest按钮后,效果如下图所示:

Android jni 编程入门

3 修改

如果需要修改hello.c文件,那么在修改完成后,同样的方式编译即可,无需其他操作。还有一点需要指出的是,程序在运行的时候,eclipse的DDMS的logcat会提示:

NO JNIOnLoad….,这是一个warmming,是因为我们使用的javah方式编写native代码,而非使用jni_onload方式动态注册native函数,初学JNI编程可以不用理会。

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,497
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,910
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,744
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,498
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:8,135
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:5,298