NDK開發

在Android 開發中,我們多多少少都會接觸到NDK開發,下面就倆講一下NDk的開發流程

1、定義一個普通的Java類 ↓,然後編寫native本地方法;

package com.xykj.imp;

public class JniUtil {

        public static native int add(int a,int b);

        public static native String sayHello();

}

2、將javac文件轉爲class文件,使用javac指令

(如:文件位置為 D:\AT31\AndroidCode\Lesson19_JNI\src\com\xykj\imp\JniUtil.java)

進入:D:\AT31\AndroidCode\Lesson19_JNI\src\com\xykj\imp>

使用:javac JniUtil.java

回車之後得到 class文件,在方法中刷新一下便可得到,

3、將class文件轉爲.h文件,需要回到源碼路徑下(src路徑下)

D:\AT31\AndroidCode\Lesson19_JNI\src>

使用javah命令:   javah -d ../jni/ com.xykj.imp.JniUtil    (注意中間用空格分開)

-d表示將編譯結果放到一個目標目錄下(../jni/)

h文件中jni方法的結果

每個方法均有JNIEXPORT關鍵字,然後有jni返回值類型,然後JNICALL關聯要實現的java本地方法

JNIEXPORT jint JNICALL Java_com_xykj_imp_JniUtil_add(JNIEnv *, jclass, jint, jint);

c功能實現文件

1,複製一個.h文件:

引入要實現的頭文件

#include "JniUtil.h"
/*
* Class: com_xykj_imp_JniUtil
* Method: add
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_xykj_imp_JniUtil_add
(JNIEnv *env, jclass obj, jint a, jint b){
// char buf[150];
// sprintf(buf,"value of a:%d b:%d",a,b);
// __android_log_print(ANDROID_LOG_INFO,"m_tag",buf); //Log.i("m_tag","value of a:5 b:10");
return a+b;
}
/*
* Class: com_xykj_imp_JniUtil
* Method: sayHello
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_xykj_imp_JniUtil_sayHello
(JNIEnv *env, jclass obj){

return (*env)->NewStringUTF(env,"Hello jni");

}

編寫mk文件

要在c文件的同目錄下,創建一個Android.mk文件,配置編譯的庫名稱,以及編譯需要的c文件

LOCAL_PATH:= $(call my-dir)
#LOCAL_CPP_EXTENSION := .cpp
include $(CLEAR_VARS)
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE := hellojni
LOCAL_SRC_FILES := JniUtil.c
LOCAL_LDLIBS += -L$(SYSROOT)/usr/lib -llog
#LOCAL_STATIC_LIBRARIES :=
#LOCAL_SHARED_LIBRARIES :=

include $(BUILD_SHARED_LIBRARY)

編譯so文件

1、首先看看你的環境變量裏有沒有配置ndk,沒有就先將ndk的根目錄配置到系統環境變量的path路徑下

2、cmd,dos界面進入項目根目錄下(如: D:\AT31\AndroidCode\Lesson19_JNI )

3、使用ndk-build命令編譯

D:\AT31\AndroidCode\Lesson19_JNI>ndk-build

使用so

在java中任何地方定義靜態 區

// 加载动态 so 库
static{
System.loadLibrary("hellojni");

}

在java中調用native

int c = JniUtil.add(156, 7894);
String str = JniUtil.sayHello();

tv.setText("156+7894="+c+" \n"+str);

自定義ContentProvider

1、定義一個ContentProvider類管理數據庫,實現對數據表的增刪改查方法

public class MyProvider extends ContentProvider {
重写 onCreate() query() insert() update() delete()

}

2、在mainfest中注冊ContentProvider

<provider
android:name="com.xykj.providerdemo.MyProvider"
android:authorities="com.xykj.providerdemo"
android:exported="true" >

</provider>

注意:android:authorities表示注冊的Uri的唯一標識

3、在ContentProvider中添加功能Uri,一般一個表分兩類,一類是多條操作,一類是單條操作

// Uri 功能校验码
private static final int TYPE_MORE = 1; // 多条操作,针对的目标是表
private static final int TYPE_ITEM = 2; // 单条操作,针对的木目标是一个确定的 item( 用 id 来确定 )
private static final UriMatcher mMatcher;
static {
mMatcher = new UriMatcher(UriMatcher.NO_MATCH);
// 添加一个 Uri-->content://com.xykj.providerdemo/all --> 1
mMatcher.addURI("com.xykj.providerdemo", "all", TYPE_MORE);
// 添加一个 Uri-->content://com.xykj.providerdemo/all/# --> 2
mMatcher.addURI("com.xykj.providerdemo", "all/#", TYPE_ITEM);

}


4、  基於Uri實現各個功能 方法

package com.xykj.providerdemo;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
public class MyProvider extends ContentProvider {
private static final String DB_NAME = "mydb.db";
private static final int VERSION = 1;
// 日记表的表名
private static final String TB_DIARY = "diary";
// Uri 功能校验码
private static final int TYPE_MORE = 1; // 多条操作,针对的目标是表
private static final int TYPE_ITEM = 2; // 单条操作,针对的木目标是一个确定的 item( 用 id 来确定 )
private DbOpenHelper mHelper;
private SQLiteDatabase mDb;
private static final UriMatcher mMatcher;
static {
mMatcher = new UriMatcher(UriMatcher.NO_MATCH);
// 添加一个 Uri-->content://com.xykj.providerdemo/all --> 1
mMatcher.addURI("com.xykj.providerdemo", "all", TYPE_MORE);
// 添加一个 Uri-->content://com.xykj.providerdemo/all/# --> 2
mMatcher.addURI("com.xykj.providerdemo", "all/#", TYPE_ITEM);
}
/**
* Provider 创建成功时触发(安装到系统,第一次被使用时)
*/
@Override
public boolean onCreate() {
mHelper = new DbOpenHelper(getContext());
mDb = mHelper.getWritableDatabase();
return true;
}
/**
* 收到 ContentResolver 的 query 查询时触发
*/
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
SQLiteQueryBuilder sqb = new SQLiteQueryBuilder();
switch (mMatcher.match(uri)) {
case TYPE_MORE:
// 处理多条的查询
sqb.setTables(TB_DIARY);
break;
case TYPE_ITEM:
// 处理单条数据的查询
sqb.setTables(TB_DIARY);
// 取出 # 的内容 item #
String str = uri.getPathSegments().get(1);
// 将 # 内容当做 id 作为单条操作的条件
sqb.appendWhere("_id=" + str);
break;
 }
Cursor c = sqb.query(mDb, projection, selection, selectionArgs, null,
null, sortOrder);
return c;
}
/**
* 针对每个期望的 Uri 定义一个类型 (mime 类型 )
*/
@Override
public String getType(Uri uri) {
switch (mMatcher.match(uri)) {
case TYPE_MORE:
return "vnd.android.cusor.dir/all";
case TYPE_ITEM:
return "vnd.android.cusor.item/item";
}
return null;
}
/**
* 收到 ContentResolver 的 insert 查询时触发
*/
@Override
public Uri insert(Uri uri, ContentValues values) {
// 希望插入数据的目标是一个表 ( 没有具体 id 的指定 )
if(mMatcher.match(uri) != TYPE_MORE){
throw new IllegalArgumentException(" 非法的 Uri:"+uri);
}
//id 为 5
long raw = mDb.insert(TB_DIARY, null, values);
// content://com.xykj.providerdemo/all/5
if(raw>0){
// 插入成功 , 拼接该条数据的 uri
return ContentUris.withAppendedId(uri, raw);
}
return null;
}
/**
* 收到 ContentResolver 的 delete 查询时触发
*/
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
// TODO Auto-generated method stub
return 0;
}
/**
* 收到 ContentResolver 的 update 查询时触发
*/
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
// TODO Auto-generated method stub
return 0;
}
class DbOpenHelper extends SQLiteOpenHelper {
public DbOpenHelper(Context context) {
super(context, DB_NAME, null, VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
String sql = "create table "
 + TB_DIARY
+ " (_id integer primary key autoincrement,title text,content text)";
db.execSQL(sql);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}

}


使用 端使用ContentResolve來訪問

Uri uri = Uri.parse("content://com.xykj.providerdemo/all");
// 插入数据
ContentValues values = new ContentValues();
values.put("title", "android");
values.put("content", "abc12345");
Uri iUri1 = getContentResolver().insert(uri, values);
String[] projection = { "_id", "title", "content" };
// 多条查询
Cursor c = getContentResolver()
.query(uri, projection, null, null, null);
while (c.moveToNext()) {
int id = c.getInt(0);
String title = c.getString(1);
String content = c.getString(2);
Log.e("m_tag", "id:" + id + " title:" + title + "\tcontent:"
+ content);
}
c.close();
// 单条查询
// 查询
Uri uri2 = Uri.parse("content://com.xykj.providerdemo/all/2");
Cursor c1 = getContentResolver().query(uri2, projection, null, null,
null);
while (c1.moveToNext()) {
int id = c1.getInt(0);
String title = c1.getString(1);
String content = c1.getString(2);
Log.e("m_tag", "id:" + id + " title:" + title + "\tcontent:"
+ content);
}

c1.close();


Uri的特殊的操作

Uri 中获取子路径内容
// 取出 # 的内容 item #
String str = uri.getPathSegments().get(1);
Uri 后拼接内容 ( 拼接 id)

Uri nUri = ContentUris.withAppendedId(uri, raw);




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值