• android 源码下的JNI编译 2017-05-02 12:03:40
    本文仅作为记录之 案例: BitmapBlur 图片虚化库. 编译JAVA package com.a.b.c; import android.content.Context; import android.graphics.Bitmap; import android.os.Build.VERSION; import android....

    本文仅作为记录之用

    案例: BitmapBlur 图片虚化库.

    编译JAVA

    package com.a.b.c;
    
    import android.content.Context;
    import android.graphics.Bitmap;
    import android.os.Build.VERSION;
    import android.renderscript.Allocation;
    import android.renderscript.Element;
    import android.renderscript.RenderScript;
    import android.renderscript.ScriptIntrinsicBlur;
    
    public class BitmapBlur {
    	static{
    		System.loadLibrary("BitmapBlur");
    	}
    	
    	/**
    	 * blur src bitmap
    	 * @param src
    	 * @param cxt
    	 * @param radius 0 <= radius <= 25
    	 * @return
    	 */
    	public static Bitmap getBlurBitmap(Bitmap src, Context cxt, int radius){
    		return getBlurBitmap(src, cxt, radius, false);
    	}
    	
    	/**
    	 * blur src bitmap by JNI
    	 * @param src
    	 * @param radius
    	 * @return
    	 */
    	public static Bitmap getBlurBitmapJNI(Bitmap src, int radius){
    		return getBlurBitmap(src, null, radius, true);
    	}
    	
    	/**
    	 * blur src, if SDK > 16, use SDK, else use JNI;
    	 * @param src
    	 * @param cxt
    	 * @param radius radius 0 <= radius <= 25
    	 * @param forceJNI
    	 * @return
    	 */
    	public static Bitmap getBlurBitmap(Bitmap src, Context cxt, int radius, boolean forceJNI){
    		if (VERSION.SDK_INT > 16 && !forceJNI) {
                Bitmap bitmap = src.copy(src.getConfig(), true);
    
                final RenderScript rs = RenderScript.create(cxt);
                final Allocation input = Allocation.createFromBitmap(rs, src, Allocation.MipmapControl.MIPMAP_NONE,
                        Allocation.USAGE_SCRIPT);
                final Allocation output = Allocation.createTyped(rs, input.getType());
                final ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
                script.setRadius(radius /* e.g. 3.f */);
                script.setInput(input);
                script.forEach(output);
                output.copyTo(bitmap);
                return bitmap;
            }else{
            	blur(src, radius);
            }
    		return src;
    	}
    	public native static void blurArray(int[] bm, int w, int h, int radius);
    	public native static void blur(Bitmap bm, int radius);
    }
    

    拷贝BitmapBlur.class到JNI目录下:

    mkdir -p com/a/b/c/

    cp xxx/BitmapBlur.class com/a/b/c/


    生成JNI 头文件

    javah -classpath . -d jni com.a.b.c.BitmapBlur

    生成jni/com_a_b_c_BitmapBlur.h

    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class com_a_b_c_BitmapBlur */
    
    #ifndef _Included_com_a_b_c_BitmapBlur
    #define _Included_com_a_b_c_BitmapBlur
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     com_a_b_c_BitmapBlur
     * Method:    blurArray
     * Signature: ([IIII)V
     */
    JNIEXPORT void JNICALL Java_com_a_b_c_BitmapBlur_blurArray
      (JNIEnv *, jclass, jintArray, jint, jint, jint);
    
    /*
     * Class:     com_a_b_c_BitmapBlur
     * Method:    blur
     * Signature: (Landroid/graphics/Bitmap;I)V
     */
    JNIEXPORT void JNICALL Java_a_b_c_BitmapBlur_blur
      (JNIEnv *, jclass, jobject, jint);
    
    #ifdef __cplusplus
    }
    #endif
    #endif
    

    编写CPP文件com_a_b_c_BitmapBlur.cpp

    /* DO NOT EDIT THIS FILE - it is machine generated */
    
    #include <com_a_b_c_BitmapBlur.h>
    #include <android/bitmap.h>
    #include <android/log.h>
    #include <blur.c>
    #include <stdio.h>
    
    JNIEXPORT void JNICALL Java_a_b_c_BitmapBlur_blurArray
      (JNIEnv *env, jclass thiz, jintArray arrIn, jint w, jint h, jint r)
    {
    	jint *pix;
    	pix = env->GetIntArrayElements(arrIn, 0);
    	if (pix == NULL)
    		return;
    	//Start
    	pix = blurIntArray(pix, w, h, r);
    	//End
    	//int size = w * h;
    	//jintArray result = env->NewIntArray(size);
    	//env->SetIntArrayRegion(result, 0, size, pix);
    	env->ReleaseIntArrayElements(arrIn, pix, 0);
    	//return result;
    }
    
    
    JNIEXPORT void JNICALL Java_a_b_c_BitmapBlur_blur
      (JNIEnv *env, jclass thiz, jobject bitmapIn, jint r)
    {
    
    /***************************************/
    	AndroidBitmapInfo infoIn;
    
    	void* pixelsIn;
    	int ret;
    
    	// Get image info
    	if ((ret = AndroidBitmap_getInfo(env, bitmapIn, &infoIn)) < 0)
    		return;
    	// Check image
    	if (infoIn.format != ANDROID_BITMAP_FORMAT_RGBA_8888)
    		return;
    	// Lock all images
    	if ((ret = AndroidBitmap_lockPixels(env, bitmapIn, &pixelsIn)) < 0) {
    		//AndroidBitmap_lockPixels failed!
    	}
    	//height width
    	int h = infoIn.height;
    	int w = infoIn.width;
    
    	//Start
    	pixelsIn = blurIntArray((int*)pixelsIn, w, h, r);
    	//End
    
    	// Unlocks everything
    	AndroidBitmap_unlockPixels(env, bitmapIn);
    /**********************************/
    }
    
    
    
    


    blur.c

    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    #include <math.h>
    #include <android/bitmap.h>
    #include <android/log.h>
    #include <stdio.h>
    
    /* Header for class com_a_b_c_BitmapBlur */
    #include<malloc.h>
    
    #define ABS(a) ((a)<(0)?(-a):(a))
    #define MAX(a,b) ((a)>(b)?(a):(b))
    #define MIN(a,b) ((a)<(b)?(a):(b))
    
    /*
     * Class:     com_a_b_c_BitmapBlur
     * Method:    blur
     * Signature: (Landroid/graphics/Bitmap;)V
     */
    
    static int* blurIntArray(int* pix, int w, int h, int radius) {
        int wm = w - 1;
        int hm = h - 1;
        int wh = w * h;
        int div = radius + radius + 1;
    
        int *r = (int *)malloc(wh * sizeof(int));
        int *g = (int *)malloc(wh * sizeof(int));
        int *b = (int *)malloc(wh * sizeof(int));
        int rsum, gsum, bsum, x, y, i, p, yp, yi, yw;
    
        int *vmin = (int *)malloc(MAX(w,h) * sizeof(int));
    
        int divsum = (div + 1) >> 1;
        divsum *= divsum;
        int *dv = (int *)malloc(256 * divsum * sizeof(int));
        for (i = 0; i < 256 * divsum; i++) {
            dv[i] = (i / divsum);
        }
    
        yw = yi = 0;
    
        int(*stack)[3] = (int(*)[3])malloc(div * 3 * sizeof(int));
        int stackpointer;
        int stackstart;
        int *sir;
        int rbs;
        int r1 = radius + 1;
        int routsum, goutsum, boutsum;
        int rinsum, ginsum, binsum;
    
        for (y = 0; y < h; y++) {
            rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
            for (i = -radius; i <= radius; i++) {
                p = pix[yi + (MIN(wm, MAX(i, 0)))];
                sir = stack[i + radius];
                sir[0] = (p & 0xff0000) >> 16;
                sir[1] = (p & 0x00ff00) >> 8;
                sir[2] = (p & 0x0000ff);
    
                rbs = r1 - ABS(i);
                rsum += sir[0] * rbs;
                gsum += sir[1] * rbs;
                bsum += sir[2] * rbs;
                if (i > 0) {
                    rinsum += sir[0];
                    ginsum += sir[1];
                    binsum += sir[2];
                }
                else {
                    routsum += sir[0];
                    goutsum += sir[1];
                    boutsum += sir[2];
                }
            }
            stackpointer = radius;
    
            for (x = 0; x < w; x++) {
    
                r[yi] = dv[rsum];
                g[yi] = dv[gsum];
                b[yi] = dv[bsum];
    
                rsum -= routsum;
                gsum -= goutsum;
                bsum -= boutsum;
    
                stackstart = stackpointer - radius + div;
                sir = stack[stackstart % div];
    
                routsum -= sir[0];
                goutsum -= sir[1];
                boutsum -= sir[2];
    
                if (y == 0) {
                    vmin[x] = MIN(x + radius + 1, wm);
                }
                p = pix[yw + vmin[x]];
    
                sir[0] = (p & 0xff0000) >> 16;
                sir[1] = (p & 0x00ff00) >> 8;
                sir[2] = (p & 0x0000ff);
    
                rinsum += sir[0];
                ginsum += sir[1];
                binsum += sir[2];
    
                rsum += rinsum;
                gsum += ginsum;
                bsum += binsum;
    
                stackpointer = (stackpointer + 1) % div;
                sir = stack[(stackpointer) % div];
    
                routsum += sir[0];
                goutsum += sir[1];
                boutsum += sir[2];
    
                rinsum -= sir[0];
                ginsum -= sir[1];
                binsum -= sir[2];
    
                yi++;
            }
            yw += w;
        }
        for (x = 0; x < w; x++) {
            rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
            yp = -radius * w;
            for (i = -radius; i <= radius; i++) {
                yi = MAX(0, yp) + x;
    
                sir = stack[i + radius];
    
                sir[0] = r[yi];
                sir[1] = g[yi];
                sir[2] = b[yi];
    
                rbs = r1 - ABS(i);
    
                rsum += r[yi] * rbs;
                gsum += g[yi] * rbs;
                bsum += b[yi] * rbs;
    
                if (i > 0) {
                    rinsum += sir[0];
                    ginsum += sir[1];
                    binsum += sir[2];
                }
                else {
                    routsum += sir[0];
                    goutsum += sir[1];
                    boutsum += sir[2];
                }
    
                if (i < hm) {
                    yp += w;
                }
            }
            yi = x;
            stackpointer = radius;
            for (y = 0; y < h; y++) {
                // Preserve alpha channel: ( 0xff000000 & pix[yi] )
                pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum];
    
                rsum -= routsum;
                gsum -= goutsum;
                bsum -= boutsum;
    
                stackstart = stackpointer - radius + div;
                sir = stack[stackstart % div];
    
                routsum -= sir[0];
                goutsum -= sir[1];
                boutsum -= sir[2];
    
                if (x == 0) {
                    vmin[y] = MIN(y + r1, hm) * w;
                }
                p = x + vmin[y];
    
                sir[0] = r[p];
                sir[1] = g[p];
                sir[2] = b[p];
    
                rinsum += sir[0];
                ginsum += sir[1];
                binsum += sir[2];
    
                rsum += rinsum;
                gsum += ginsum;
                bsum += binsum;
    
                stackpointer = (stackpointer + 1) % div;
                sir = stack[stackpointer];
    
                routsum += sir[0];
                goutsum += sir[1];
                boutsum += sir[2];
    
                rinsum -= sir[0];
                ginsum -= sir[1];
                binsum -= sir[2];
    
                yi += w;
            }
        }
    
        free(r);
        free(g);
        free(b);
        free(vmin);
        free(dv);
        free(stack);
        return(pix);
    }
    
    
    

    编写Android.mk文件

    LOCAL_PATH := $(call my-dir)
    
    include $(CLEAR_VARS)
    
    LOCAL_MODULE    := libBitmapBlur
    LOCAL_SRC_FILES := com_a_b_c_BitmapBlur.cpp
    LOCAL_SHARED_LIBRARIES := \
            libandroid_runtime \
            libcutils \
            libjnigraphics
    
    include $(BUILD_SHARED_LIBRARY)

    普通的JNI编译到此结束.

    接下来只需要通过mm / mmm命令编译即可生成相应lib库.


    以下补充一些遇到的问题:

    1. 引用让部lib库.

        在编译当前的lib时, 需要依赖到libExt1.so, libExt2.so, 我们把两个lib库放在编译目录的lib/目录下, 同时, 新建lib/Android.mk文件, 内容如下:

    LOCAL_PATH := $(call my-dir)
    
    include $(CLEAR_VARS)
    LOCAL_MODULE := libExt1.so
    LOCAL_MODULE_TAGS := optional
    LOCAL_MODULE_CLASS := SHARED_LIBRARIES
    LOCAL_MODULE_STEM := $(LOCAL_MODULE)
    LOCAL_SRC_FILES := $(LOCAL_MODULE)
    LOCAL_MODULE_SUFFIX := 
    include $(BUILD_PREBUILT)
    
    include $(CLEAR_VARS)
    LOCAL_MODULE := libExt2.so
    LOCAL_MODULE_TAGS := optional
    LOCAL_MODULE_CLASS := SHARED_LIBRARIES
    LOCAL_MODULE_STEM := $(LOCAL_MODULE)
    LOCAL_SRC_FILES := $(LOCAL_MODULE)
    LOCAL_MODULE_SUFFIX := 
    include $(BUILD_PREBUILT)

    在需要编译的模块的Android.mk中, 添加如下:

    LOCAL_SHARED_LIBRARIES := libExt1 libExt2

    在这之前曾错误的使用了: include $(call all-subdir-makefiles), 导致编译出现很多问题:

    最常见的make: *** No rule to make target 'packages/jni/BTP_S80/lib/com_example_testscanprn_Printer.cpp', needed by 'out/target/product/XXX/obj/SHARED_LIBRARIES/libScanPrnWrap_intermediates/com_example_testscanprn_Printer.o'.  Stop.


    2. 源码文件,

    LOCAL_SRC_FILES := com_a_b_c_BitmapBlur.cpp

    使用错误的文件名, 也同样可以编译通过, 并生成so库, 但so库在JAVA调用时, 会提示

    java.lang.UnsatisfiedLinkError: No implementation found for 后面紧跟的是函数名.


    3. 关于javah.

    javah -classpath . -d jni a.b.c.Printer 这里需注意classpath后面的参数

    如, 刚开始是把native函数写在Activity中, 后面发现, 会出现找不到android.app.Activity类的错误

    网上也有对应的解决方案, 但没时间去细细研究, 建议, 把native函数放在单的类中定义, 这样用javah生成.h文件时会少走些弯路.

    展开全文
  • 在eclipse或者Android Studio下可以通过NDK实现JNI编译生成so库文件,那么在Android系统环境下,我们应该怎么做?直接使用eclipse或者AS的配置?NO,NO,NO 我们需要在项目的根目录下编写一个Android.mk文件如下:...
  • Android源码编译JNI 2017-11-09 10:07:57
    APP编译 Android.mkifneq ($(TARGET_BUILD_JAVA_SUPPORT_LEVEL),)LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE_TAGS := testsLOCAL_PROGUARD_ENABLED := disabled# comment it out for now ...
  • 1、在对应app工程目录下新建jni目录 mkdir jni LINUX/android/packages/apps/Dialer$ ls AndroidManifest.xml Android.mk assets java jni LICENSE 2、CallTimeNvWriter.java文件中加载soku文件,并声明了...
  • Android Studio 中编译 JNI 代码 经常需要实现一些 C,C++ 接口的功能模块,提供给 java 层调用。 那么就需要利用 JNI 写接口提供 java 的 native 调用。 必不可少的一步就是编译 JNI 代码。 需要的文件 (项目) ...
  • 以下只是自己的一些总结,欢迎讨论通过NDK编译jni网上有很多例子,在这我只总结在Android源码下编译1、android源码环境下编译so包,编出来的.so的包前面不会自动给添加lib,NDK编译会自动给添加lib,即使Android.mk...
  • Android源码编译并预装带JNI的apk说明:以下文档中使用 *android_src 目录代表我的android6.0源码的根目录。*1.在eclipse或者androidstudio中新建一个工程HelloWorld。 在包com/sk/helloworld 下面新建一个java文件...
  • 这些问题是都是坑,有的问题晚上都找不到解决方法,是因为这些问题只要用到源码编译的时候才会遇到,这里我的是源码编译。 问题如下;问题1.dlopen(“/data/app/xxx.xxx.so”)failed,dlopen”/data/app/xxx.xxx.so...
  • 1、代码和Android.mk编写 ├── jni │ ├── Android.mk │ └── led.c //led.c #include #include jboolean Java_com_lhw_led_Led_turnOn(JNIEnv *env, jclass thiz) { return JNI_TRUE; } ...
  • Android系统源码分析-JNI 2019-02-27 19:32:33
    因为在接下来的源码分析中将涉及大量的Java和Native的互相调用。当然对于我们的代码分析没有什么影响,但是,这样一个黑盒子摆在面前,对于其实现原理还是充满了好奇心。本篇将从JNI最基本的概念到简单的代码实例和...
  • Android 源码中新增JNI 2016-10-24 17:15:39
    Android 新增JNI
  • android开发---6在源码目录与ndk-build下编译jni与apk(附demo)
  • Android源码编译环境下APK文件签名命令
  • android源码编译sdk 2016-05-31 15:55:37
    在/frameworks/base/Android.mk中,找到如下行:  packages_to_document :=  在该变量的赋值语句最后添加  xxxxx (这里是你的包的名称,比如com/sina/ui,其实这里就是你的源代码在/frameworks/base//java/下面...
  • Android Studio中编译jni和so库,可以使用app/CMakeList.txt,也可以使用Android.mk AndroidStudio 进行 JNI / NDK 开发:初步配置及使用 2017年09月08日 12:03:44 阅读数:5118 说干就干! JNI:Java ...
  • 最简单的办法就是将android studio生成的工程方到源码中,然后添加Android.mk,指定代码和资源路径以及依赖库即可。 LOCAL_SRC_FILES := $(call all-java-files-under, Application/src/main/java) LOCAL_...
  • 简单实例说明如何使用Android Studio NDK编译so库
  • Android 手动编译jni动态库 2018-05-22 18:05:31
    能快速,简单(主要是指脱离AndroidStudio)的把c/c++ 源码进行交叉编译Android上的动态库,静态库,或者可执行文件。从而为逆向分析构建demo节省时间。 编译环境配置 电脑:Mac OS 10.13.4 NDK:官网下载,...
  • android源码编译AS工程
  • 原文网址:...不过最终我的代码虽然只有几行,但需要libdl,因为用到了dlopen一类的函数,只能又换到用android源码体系下编译。不过两个都了下,就发现了些不同。我其实并不能确定这些是不是实际存在...
1 2 3 4 5 ... 20
收藏数 18,237
精华内容 7,294