精华内容
下载资源
问答
  • 这篇主要写到的是,Android Studio中怎样进行项目设置,进行调用C的函数。 在android中调用C的代码有两类: 方法一 . 自己写的C代码,通过JNI编程,用native修饰函数,用javah来关联,再在android java代码中调用...

    这篇主要写到的是,Android Studio中怎样进行项目设置,进行调用C的函数。

    在android中调用C的代码有两类:

    方法一 . 自己写的C代码,通过JNI编程,用native修饰函数,用javah来关联,再在android java代码中调用。

    方法二 . 用已经编译好的.so动态链接库文件,将它放在指定的位置,再调用即可。


    用了一上午的时间捯饬方法一,没弄出来。只差一点点。。。回头再来弄,先记下来。

    参考了:

    android studio2.0 NDK开发教程http://blog.csdn.net/xiqingnian/article/details/51307880

        AS NDK环境配置:http://www.cnblogs.com/zhuyp1015/p/4976116.html

    javah: http://ikinglai.blog.51cto.com/6220785/1225069/



    先空着,弄完了,来填上。

    展开全文
  • 该文件提供可供JNI调用的函数lzma(sf: String, df: String, isEncode: Boolean): String,以实现压缩/解压缩文件的功能 // // lzma.c // Created by rumia on 2021/3/12. // /* Edit from LzmaUtil

    添加源码

    官网下载源码后,将其中的C目录拷贝到src/main/cpp,并重命名为lzma

    精简文件

    删除lzma/Util,并新建文件夹lzma/jni,在其下写入如下文件lzma.c,内容见下节。lzma目录下只需保留如下文件即可
    lzma_dir_structure

    添加JNI函数

    该文件提供可供JNI调用的函数lzma(sf: String, df: String, isEncode: Boolean): String,以实现压缩/解压缩某目录文件的功能

    //
    // lzma.c
    // Created by rumia on 2021/3/12.
    //
    
    /* Edit from LzmaUtil.c -- Test application for LZMA compression
    2018-07-04 : Igor Pavlov : Public domain */
    
    #include <jni.h>
    #include "../Precomp.h"
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #include "../CpuArch.h"
    
    #include "../Alloc.h"
    #include "../7zFile.h"
    #include "../7zVersion.h"
    #include "../LzmaDec.h"
    #include "../LzmaEnc.h"
    
    static const char * const kCantReadMessage = "Can not read input file";
    static const char * const kCantWriteMessage = "Can not write output file";
    static const char * const kCantAllocateMessage = "Can not allocate memory";
    static const char * const kDataErrorMessage = "Data error";
    
    static int PrintError(char *buffer, const char *message) {
    	strcat(buffer, "\nError: ");
    	strcat(buffer, message);
    	strcat(buffer, "\n");
    	return 1;
    }
    
    static int PrintErrorNumber(char *buffer, SRes val) {
    	sprintf(buffer + strlen(buffer), "\nError code: %x\n", (unsigned)val);
    	return 1;
    }
    
    
    #define IN_BUF_SIZE (1 << 16)
    #define OUT_BUF_SIZE (1 << 16)
    
    
    static SRes Decode2(CLzmaDec *state, ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 unpackSize) {
    	int thereIsSize = (unpackSize != (UInt64)(Int64)-1);
    	Byte inBuf[IN_BUF_SIZE];
    	Byte outBuf[OUT_BUF_SIZE];
    	size_t inPos = 0, inSize = 0, outPos = 0;
    	LzmaDec_Init(state);
    	for (;;)
    	{
    		if (inPos == inSize)
    		{
    			inSize = IN_BUF_SIZE;
    			RINOK(inStream->Read(inStream, inBuf, &inSize));
    			inPos = 0;
    		}
    		{
    			SRes res;
    			SizeT inProcessed = inSize - inPos;
    			SizeT outProcessed = OUT_BUF_SIZE - outPos;
    			ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
    			ELzmaStatus status;
    			if (thereIsSize && outProcessed > unpackSize)
    			{
    				outProcessed = (SizeT)unpackSize;
    				finishMode = LZMA_FINISH_END;
    			}
    			
    			res = LzmaDec_DecodeToBuf(state, outBuf + outPos, &outProcessed,
    				inBuf + inPos, &inProcessed, finishMode, &status);
    			inPos += inProcessed;
    			outPos += outProcessed;
    			unpackSize -= outProcessed;
    			
    			if (outStream)
    				if (outStream->Write(outStream, outBuf, outPos) != outPos)
    					return SZ_ERROR_WRITE;
    				
    			outPos = 0;
    			
    			if (res != SZ_OK || (thereIsSize && unpackSize == 0))
    				return res;
    			
    			if (inProcessed == 0 && outProcessed == 0)
    			{
    				if (thereIsSize || status != LZMA_STATUS_FINISHED_WITH_MARK)
    					return SZ_ERROR_DATA;
    				return res;
    			}
    		}
    	}
    }
    
    
    static SRes Decode(ISeqOutStream *outStream, ISeqInStream *inStream) {
    	UInt64 unpackSize;
    	int i;
    	SRes res = 0;
    
    	CLzmaDec state;
    
    	/* header: 5 bytes of LZMA properties and 8 bytes of uncompressed size */
    	unsigned char header[LZMA_PROPS_SIZE + 8];
    
    	/* Read and parse header */
    
    	RINOK(SeqInStream_Read(inStream, header, sizeof(header)));
    
    	unpackSize = 0;
    	for (i = 0; i < 8; i++)
    		unpackSize += (UInt64)header[LZMA_PROPS_SIZE + i] << (i * 8);
    
    	LzmaDec_Construct(&state);
    	RINOK(LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc));
    	res = Decode2(&state, outStream, inStream, unpackSize);
    	LzmaDec_Free(&state, &g_Alloc);
    	return res;
    }
    
    static SRes Encode(ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 fileSize, char *rs) {
    	CLzmaEncHandle enc;
    	SRes res;
    	CLzmaEncProps props;
    
    	UNUSED_VAR(rs);
    
    	enc = LzmaEnc_Create(&g_Alloc);
    	if (enc == 0)
    		return SZ_ERROR_MEM;
    
    	LzmaEncProps_Init(&props);
    	res = LzmaEnc_SetProps(enc, &props);
    
    	if (res == SZ_OK)
    	{
    		Byte header[LZMA_PROPS_SIZE + 8];
    		size_t headerSize = LZMA_PROPS_SIZE;
    		int i;
    
    		res = LzmaEnc_WriteProperties(enc, header, &headerSize);
    		for (i = 0; i < 8; i++)
    			header[headerSize++] = (Byte)(fileSize >> (8 * i));
    		if (outStream->Write(outStream, header, headerSize) != headerSize)
    			res = SZ_ERROR_WRITE;
    		else
    		{
    			if (res == SZ_OK)
    				res = LzmaEnc_Encode(enc, outStream, inStream, NULL, &g_Alloc, &g_Alloc);
    		}
    	}
    	LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc);
    	return res;
    }
    
    extern JNIEXPORT jstring JNICALL
    Java_com_my_app_MainActivity_lzma(JNIEnv* env, jobject obj, jstring sf, jstring df, jboolean encodeMode) {
        char rs[800] = { 0 };
        const char *inputFileDir = (*env)->GetStringUTFChars(env, sf, JNI_FALSE);
        const char *outputFileDir = (*env)->GetStringUTFChars(env, df, JNI_FALSE);
        CFileSeqInStream inStream;
        CFileOutStream outStream;
    
        FileSeqInStream_CreateVTable(&inStream);
        File_Construct(&inStream.file);
        FileOutStream_CreateVTable(&outStream);
        File_Construct(&outStream.file);
    
        if (InFile_Open(&inStream.file, inputFileDir) != 0) PrintError(rs, "Can not open input file");
        else if (OutFile_Open(&outStream.file, outputFileDir) != 0) PrintError(rs, "Can not open output file");
        else {
            int res;
            if (encodeMode) {
                UInt64 fileSize;
                File_GetLength(&inStream.file, &fileSize);
                res = Encode(&outStream.vt, &inStream.vt, fileSize, rs);
            } else res = Decode(&outStream.vt, &inStream.vt);
    
            File_Close(&outStream.file);
            File_Close(&inStream.file);
    
            if (res != SZ_OK) {
                if (res == SZ_ERROR_MEM) PrintError(rs, kCantAllocateMessage);
                else if (res == SZ_ERROR_DATA) PrintError(rs, kDataErrorMessage);
                else if (res == SZ_ERROR_WRITE) PrintError(rs, kCantWriteMessage);
                else if (res == SZ_ERROR_READ) PrintError(rs, kCantReadMessage);
                PrintErrorNumber(rs, res);
            }
        }
        return (*env)->NewStringUTF(env, rs);
    }
    

    添加CMakeLists

    1. cpp目录下新建CMakeLists.txt,写入如下内容
    cmake_minimum_required(VERSION 3.10.2)
    
    project("myapp")
    
    add_subdirectory(lzma)
    
    1. cpp/lzma目录下新建CMakeLists.txt,写入如下内容
    cmake_minimum_required(VERSION 3.10.2)
    
    project("myapp")
    
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_7ZIP_ST")
    
    add_library(
            lzma
            SHARED
            jni/lzma.c Alloc.c LzFind.c LzmaDec.c LzmaEnc.c 7zFile.c 7zStream.c
    )
    

    配置gradle

    在模块级build.gradle中增加如下内容

    android {
        externalNativeBuild {
            cmake {
                path "src/main/cpp/CMakeLists.txt"
                version "3.10.2"
            }
        }
        ......
    }
    

    加载库

    MainActivity增加

    class MainActivity : Activity() {
        ......
        private external fun lzma(sf: String, df: String, isEncode: Boolean): String
    
        companion object {
            // Used to load the 'native-lib' library on application startup.
            init {
                System.loadLibrary("lzma")
            }
        }
    }
    

    之后即可在代码中调用

    展开全文
  • 一必备的工具二开始三JAVA调用四修改Andoidmk文件五编译六生成apk与测试七其他  目前我在做HM(HEVC测试软件)移植到Android平台,在移植过程中出现了一些问题,顺便记录下来,供大家分享。也让大家在出现...
    


             目前我在做HM(HEVC测试软件)移植到Android平台,在移植过程中出现了一些问题,顺便记录下来,供大家分享。也让大家在出现问题是能够有一个参照。这些天忙着调试程序中出现的BUG,没有来得及更新。

    移植HM详细请看另外一篇日志:http://blog.csdn.net/luofl1992/article/details/8736149

    一、必备的工具

            开始之前请确认你有这样几个工具 :

            Java JDK(Java Development Toolkit )

            Android SDK (简称ADK )可以直接下载Eclipse+ADT二合一版本

            Eclipse (需要集成 CDT,直接使用上面的ADK开发的无视这个)

            NDK (Android NDK)

            这些工具没有的安装,可以去官方网站下载。各个工具的安装教程网络上很多,自己找一找,这里就不再列出了。


    二、开始

      1、使用IDE工具

            用Eclipse建立一个工程,配置相关选项,建立工程完毕,我们可以进入工程目录(即 PROJECT_DIR )。

            然后建立一个新的文件夹,叫做 jni 的目录。

            自己在里面添加两个文件 Application.mk 和 Android.mk (我没有装NDK的时候说一直再找哪里有这两个文件)

            然后,修改一下这两个文件的内容,具体说明请看:

           Android-ndk/docs/Android-mk.html  等等一系列参考文档,说明了参数的意义之类的。


      2、使用命令行

    cd到任意目录下,首先执行这条命令查看一下Android对应的版本号(下面会用到)

    1. android list targets  
    android list targets
    然后执行这样的指令:

    1. android create project \  
    2. --target <target-id> \  
    3. --name MyFirstApp \  
    4. --path <path-to-workspace>/MyFirstApp \  
    5. --activity MainActivity 、  
    6. --package com.example.myfirstapp  
    android create project \
    --target <target-id> \
    --name MyFirstApp \
    --path <path-to-workspace>/MyFirstApp \
    --activity MainActivity 、
    --package com.example.myfirstapp

    这里  <target-id>是上面一条指令列出的版本号,数字,比如我执行上面一条指令的结果是9表示 Android 2.3.3,是我需要生成的目标平台版本号,

    --name 后面为项目名称,比如我的是 --name NcHevcPlayer

    --path 后面跟的是项目的路径,为文件夹的名字,比如我要在当前目录下建立 NcHevcPlayer 的文件夹作为工程目录,就是 --path NcHevcPlayer

    --activity 后面跟的是主Activity的类名字,随意指定。

    --package 后面跟着包名字,可以像这样 --package com.NcHevc

    (先卖个关子,包的名字会对后面使用NDK、JNI造成影响)

    那么整个命令就像这样子:

    1. android create project \  
    2. --target 9 \  
    3. -name NcHevcPlayer \  
    4. --path NcHevcPlayer \  
    5. --activity NcHevcPlayerActivity \  
    6. --package com.NcHevc  
    android create project \
    --target 9 \
    -name NcHevcPlayer \
    --path NcHevcPlayer \
    --activity NcHevcPlayerActivity \
    --package com.NcHevc

    更加详细的说明可以参考NDK的网站,或者在本机NDK目录下的docs里面阅读相关说明。

    http://developer.android.com/tools/projects/projects-cmdline.html

    如果没有错误,那么在当前目录下会出现一个NcHevcPlayer目录,由上面的--path指定。

    或者可以对已有Android项目更新,其语法如下:

    1. android update project \  
    2. --name <project_name> \  
    3. --target <target_ID> \  
    4. --path <path_to_your_project>  
    android update project \
    --name <project_name> \
    --target <target_ID> \
    --path <path_to_your_project>


    这个步骤完成之后工程的目录结构如下图:



    三、JAVA调用

          JAVA调用C/C++的函数需要使用JNI,需要使用的指令有 javac 和 javah

          详细的介绍请参考这篇文章:http://www.cnblogs.com/hibraincol/archive/2011/05/30/2063847.html

          首先在某个类(比如Activity类)增加native函数,然后运行javac指令编译该类的java文件,

          生成一个class文件,再用javah命令,生成对应的头文件。

          建议cd到src目录,不要再进去了,执行

         javac com/NcHevc/NcHevcDecoder.java

         javah com.NcHevc.NcHevcDecoder

        就可以得到一个头文件了,见下面JNI目录的图中NcHevcDecoder.h。

    其内容如下:

    1. /* DO NOT EDIT THIS FILE - it is machine generated */  
    2. #include <jni.h>  
    3. /* Header for class com_NcHevc_NcHevcDecoder */  
    4.   
    5. #ifndef _Included_com_NcHevc_NcHevcDecoder  
    6. #define _Included_com_NcHevc_NcHevcDecoder  
    7.   
    8. // 这三行是额外添加的  
    9. #include "TLibCommon/CommonDef.h"  
    10.   
    11. typedef unsigned char byte; // typedefine type as unsigned char  
    12.   
    13. // 以下为JAVAH生成的函数原型  
    14. #ifdef __cplusplus  
    15. extern "C" {  
    16. #endif  
    17. /* 
    18.  * Class:     com_NcHevc_NcHevcDecoder 
    19.  * Method:    Open 
    20.  * Signature: (Ljava/lang/String;)Z 
    21.  */  
    22. JNIEXPORT jboolean JNICALL Java_com_NcHevc_NcHevcDecoder_Open  
    23.   (JNIEnv *, jobject, jstring);  
    24.   
    25. /* 
    26.  * Class:     com_NcHevc_NcHevcDecoder 
    27.  * Method:    GetPixelsBuffer 
    28.  * Signature: ([I)V 
    29.  */  
    30. JNIEXPORT void JNICALL Java_com_NcHevc_NcHevcDecoder_GetPixelsBuffer  
    31.   (JNIEnv *, jobject, jintArray);  
    32.   
    33. /* 
    34.  * Class:     com_NcHevc_NcHevcDecoder 
    35.  * Method:    DecodeFrame 
    36.  * Signature: ()Z 
    37.  */  
    38. JNIEXPORT jboolean JNICALL Java_com_NcHevc_NcHevcDecoder_DecodeFrame  
    39.   (JNIEnv *, jobject);  
    40.   
    41. #ifdef __cplusplus  
    42. }  
    43. #endif  
    44. #endif  
    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class com_NcHevc_NcHevcDecoder */
    
    #ifndef _Included_com_NcHevc_NcHevcDecoder
    #define _Included_com_NcHevc_NcHevcDecoder
    
    // 这三行是额外添加的
    #include "TLibCommon/CommonDef.h"
    
    typedef unsigned char byte;	// typedefine type as unsigned char
    
    // 以下为JAVAH生成的函数原型
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     com_NcHevc_NcHevcDecoder
     * Method:    Open
     * Signature: (Ljava/lang/String;)Z
     */
    JNIEXPORT jboolean JNICALL Java_com_NcHevc_NcHevcDecoder_Open
      (JNIEnv *, jobject, jstring);
    
    /*
     * Class:     com_NcHevc_NcHevcDecoder
     * Method:    GetPixelsBuffer
     * Signature: ([I)V
     */
    JNIEXPORT void JNICALL Java_com_NcHevc_NcHevcDecoder_GetPixelsBuffer
      (JNIEnv *, jobject, jintArray);
    
    /*
     * Class:     com_NcHevc_NcHevcDecoder
     * Method:    DecodeFrame
     * Signature: ()Z
     */
    JNIEXPORT jboolean JNICALL Java_com_NcHevc_NcHevcDecoder_DecodeFrame
      (JNIEnv *, jobject);
    
    #ifdef __cplusplus
    }
    #endif
    #endif
    



    四、修改Andoid.mk文件

            我的是这样子的:

    1. LOCAL_PATH := $(call my-dir)  
    2. # 是否采用改进了的 HM 库  
    3. USING_IMPROVED_HM := true  
    4. # 一些路径的设置,相对路径和绝对路径  
    5. ifeq ($(USING_IMPROVED_HM),true)  
    6. # 优化的版本,加快运行效率  
    7. PATH_HM := libHM  
    8. else  
    9. # 标准版本(只修改错误使其能够正常在Android平台运行)  
    10. PATH_HM := libHMStandard  
    11. endif  
    12. PATH_HM_ABSOLUTE := $(LOCAL_PATH)/$(PATH_HM)  
    13.   
    14. #include $(CLEAR_VARS)  
    15. #LOCAL_MODULE := HmDecoder      # name it whatever  
    16. #LOCAL_SRC_FILES := libHM.a   
    17. #include $(PREBUILT_STATIC_LIBRARY)  
    18.   
    19. # Here we give our module name and source file(s)  
    20. include $(CLEAR_VARS)  
    21. LOCAL_MODULE := NcHevcDecoder  
    22. LOCAL_CPP_EXTENTION := .cpp  
    23. LOCAL_CXXFLAGS := -D__cplusplus -g  
    24. # LOCAL_CPPFLAGS += -fexceptions  
    25. #设置系统默认包含路径,避免编译时出现找不到头文件的情况  
    26. LOCAL_C_INCLUDES := ~/android-ndk/sources/cxx-stl/stlport/stlport:$(LOCAL_PATH)  
    27. LOCAL_C_INCLUDES += $(PATH_HM_ABSOLUTE)  
    28. LOCAL_CPP_INCLUDES := ~/android-ndk/sources/cxx-stl/stlport/stlport:$(LOCAL_PATH)  
    29. LOCAL_CPP_INCLUDES += $(PATH_HM_ABSOLUTE)  
    30. # find . -name '*.c*' 编码器相关的库实际上没有使用到,可以不予添加  
    31. LOCAL_SRC_FILES := NcHevcDecoder.cpp TAppDecTop.cpp JNI_OnLoad.cpp \  
    32. $(PATH_HM)/libmd5/libmd5.c \  
    33. $(PATH_HM)/TLibEncoder/TEncEntropy.cpp \  
    34. $(PATH_HM)/TLibEncoder/TEncBinCoderCABAC.cpp \  
    35. $(PATH_HM)/TLibEncoder/TEncSbac.cpp \  
    36. $(PATH_HM)/TLibEncoder/SyntaxElementWriter.cpp \  
    37. $(PATH_HM)/TLibEncoder/TEncGOP.cpp \  
    38. $(PATH_HM)/TLibEncoder/TEncSearch.cpp \  
    39. $(PATH_HM)/TLibEncoder/TEncPic.cpp \  
    40. $(PATH_HM)/TLibEncoder/NALwrite.cpp \  
    41. $(PATH_HM)/TLibEncoder/TEncCavlc.cpp \  
    42. $(PATH_HM)/TLibEncoder/TEncPreanalyzer.cpp \  
    43. $(PATH_HM)/TLibEncoder/TEncBinCoderCABACCounter.cpp \  
    44. $(PATH_HM)/TLibEncoder/WeightPredAnalysis.cpp \  
    45. $(PATH_HM)/TLibEncoder/TEncAnalyze.cpp \  
    46. $(PATH_HM)/TLibEncoder/TEncRateCtrl.cpp \  
    47. $(PATH_HM)/TLibEncoder/SEIwrite.cpp \  
    48. $(PATH_HM)/TLibEncoder/TEncSlice.cpp \  
    49. $(PATH_HM)/TLibEncoder/TEncSampleAdaptiveOffset.cpp \  
    50. $(PATH_HM)/TLibEncoder/TEncCu.cpp \  
    51. $(PATH_HM)/TLibEncoder/TEncTop.cpp \  
    52. $(PATH_HM)/TLibDecoder/SyntaxElementParser.cpp \  
    53. $(PATH_HM)/TLibDecoder/TDecGop.cpp \  
    54. $(PATH_HM)/TLibDecoder/TDecTop.cpp \  
    55. $(PATH_HM)/TLibDecoder/TDecEntropy.cpp \  
    56. $(PATH_HM)/TLibDecoder/TDecCAVLC.cpp \  
    57. $(PATH_HM)/TLibDecoder/TDecCu.cpp \  
    58. $(PATH_HM)/TLibDecoder/NALread.cpp \  
    59. $(PATH_HM)/TLibDecoder/TDecSbac.cpp \  
    60. $(PATH_HM)/TLibDecoder/SEIread.cpp \  
    61. $(PATH_HM)/TLibDecoder/TDecSlice.cpp \  
    62. $(PATH_HM)/TLibDecoder/AnnexBread.cpp \  
    63. $(PATH_HM)/TLibDecoder/TDecBinCoderCABAC.cpp \  
    64. $(PATH_HM)/TAppCommon/program_options_lite.cpp \  
    65. $(PATH_HM)/TLibVideoIO/TVideoIOYuv.cpp \  
    66. $(PATH_HM)/TLibCommon/TComRdCostWeightPrediction.cpp \  
    67. $(PATH_HM)/TLibCommon/TComCABACTables.cpp \  
    68. $(PATH_HM)/TLibCommon/TComPic.cpp \  
    69. $(PATH_HM)/TLibCommon/TComSampleAdaptiveOffset.cpp \  
    70. $(PATH_HM)/TLibCommon/TComPattern.cpp \  
    71. $(PATH_HM)/TLibCommon/TComLoopFilter.cpp \  
    72. $(PATH_HM)/TLibCommon/TComPrediction.cpp \  
    73. $(PATH_HM)/TLibCommon/SEI.cpp \  
    74. $(PATH_HM)/TLibCommon/TComPicYuvMD5.cpp \  
    75. $(PATH_HM)/TLibCommon/TComRdCost.cpp \  
    76. $(PATH_HM)/TLibCommon/TComBitStream.cpp \  
    77. $(PATH_HM)/TLibCommon/TComTrQuant.cpp \  
    78. $(PATH_HM)/TLibCommon/TComSlice.cpp \  
    79. $(PATH_HM)/TLibCommon/TComPicYuv.cpp \  
    80. $(PATH_HM)/TLibCommon/TComDataCU.cpp \  
    81. $(PATH_HM)/TLibCommon/TComWeightPrediction.cpp \  
    82. $(PATH_HM)/TLibCommon/TComInterpolationFilter.cpp \  
    83. $(PATH_HM)/TLibCommon/ContextModel.cpp \  
    84. $(PATH_HM)/TLibCommon/TComRom.cpp \  
    85. $(PATH_HM)/TLibCommon/TComMotionInfo.cpp \  
    86. $(PATH_HM)/TLibCommon/ContextModel3DBuffer.cpp \  
    87. $(PATH_HM)/TLibCommon/TComYuv.cpp \  
    88. $(PATH_HM)/TLibCommon/TComPicSym.cpp  
    89. LOCAL_STATIC_LIBRARIES := ~/android-ndk/sources/cxx-stl/stlport/libs/armeabi/libstlport_static.a  
    90. LOCAL_LDLIBS := -llog  
    91. # 导出动态库  
    92. include $(BUILD_SHARED_LIBRARY)  
    LOCAL_PATH := $(call my-dir)
    # 是否采用改进了的 HM 库
    USING_IMPROVED_HM := true
    # 一些路径的设置,相对路径和绝对路径
    ifeq ($(USING_IMPROVED_HM),true)
    # 优化的版本,加快运行效率
    PATH_HM := libHM
    else
    # 标准版本(只修改错误使其能够正常在Android平台运行)
    PATH_HM := libHMStandard
    endif
    PATH_HM_ABSOLUTE := $(LOCAL_PATH)/$(PATH_HM)
    
    #include $(CLEAR_VARS)
    #LOCAL_MODULE := HmDecoder      # name it whatever
    #LOCAL_SRC_FILES := libHM.a 
    #include $(PREBUILT_STATIC_LIBRARY)
    
    # Here we give our module name and source file(s)
    include $(CLEAR_VARS)
    LOCAL_MODULE := NcHevcDecoder
    LOCAL_CPP_EXTENTION := .cpp
    LOCAL_CXXFLAGS := -D__cplusplus -g
    # LOCAL_CPPFLAGS += -fexceptions
    #设置系统默认包含路径,避免编译时出现找不到头文件的情况
    LOCAL_C_INCLUDES := ~/android-ndk/sources/cxx-stl/stlport/stlport:$(LOCAL_PATH)
    LOCAL_C_INCLUDES += $(PATH_HM_ABSOLUTE)
    LOCAL_CPP_INCLUDES := ~/android-ndk/sources/cxx-stl/stlport/stlport:$(LOCAL_PATH)
    LOCAL_CPP_INCLUDES += $(PATH_HM_ABSOLUTE)
    # find . -name '*.c*' 编码器相关的库实际上没有使用到,可以不予添加
    LOCAL_SRC_FILES := NcHevcDecoder.cpp TAppDecTop.cpp JNI_OnLoad.cpp \
    $(PATH_HM)/libmd5/libmd5.c \
    $(PATH_HM)/TLibEncoder/TEncEntropy.cpp \
    $(PATH_HM)/TLibEncoder/TEncBinCoderCABAC.cpp \
    $(PATH_HM)/TLibEncoder/TEncSbac.cpp \
    $(PATH_HM)/TLibEncoder/SyntaxElementWriter.cpp \
    $(PATH_HM)/TLibEncoder/TEncGOP.cpp \
    $(PATH_HM)/TLibEncoder/TEncSearch.cpp \
    $(PATH_HM)/TLibEncoder/TEncPic.cpp \
    $(PATH_HM)/TLibEncoder/NALwrite.cpp \
    $(PATH_HM)/TLibEncoder/TEncCavlc.cpp \
    $(PATH_HM)/TLibEncoder/TEncPreanalyzer.cpp \
    $(PATH_HM)/TLibEncoder/TEncBinCoderCABACCounter.cpp \
    $(PATH_HM)/TLibEncoder/WeightPredAnalysis.cpp \
    $(PATH_HM)/TLibEncoder/TEncAnalyze.cpp \
    $(PATH_HM)/TLibEncoder/TEncRateCtrl.cpp \
    $(PATH_HM)/TLibEncoder/SEIwrite.cpp \
    $(PATH_HM)/TLibEncoder/TEncSlice.cpp \
    $(PATH_HM)/TLibEncoder/TEncSampleAdaptiveOffset.cpp \
    $(PATH_HM)/TLibEncoder/TEncCu.cpp \
    $(PATH_HM)/TLibEncoder/TEncTop.cpp \
    $(PATH_HM)/TLibDecoder/SyntaxElementParser.cpp \
    $(PATH_HM)/TLibDecoder/TDecGop.cpp \
    $(PATH_HM)/TLibDecoder/TDecTop.cpp \
    $(PATH_HM)/TLibDecoder/TDecEntropy.cpp \
    $(PATH_HM)/TLibDecoder/TDecCAVLC.cpp \
    $(PATH_HM)/TLibDecoder/TDecCu.cpp \
    $(PATH_HM)/TLibDecoder/NALread.cpp \
    $(PATH_HM)/TLibDecoder/TDecSbac.cpp \
    $(PATH_HM)/TLibDecoder/SEIread.cpp \
    $(PATH_HM)/TLibDecoder/TDecSlice.cpp \
    $(PATH_HM)/TLibDecoder/AnnexBread.cpp \
    $(PATH_HM)/TLibDecoder/TDecBinCoderCABAC.cpp \
    $(PATH_HM)/TAppCommon/program_options_lite.cpp \
    $(PATH_HM)/TLibVideoIO/TVideoIOYuv.cpp \
    $(PATH_HM)/TLibCommon/TComRdCostWeightPrediction.cpp \
    $(PATH_HM)/TLibCommon/TComCABACTables.cpp \
    $(PATH_HM)/TLibCommon/TComPic.cpp \
    $(PATH_HM)/TLibCommon/TComSampleAdaptiveOffset.cpp \
    $(PATH_HM)/TLibCommon/TComPattern.cpp \
    $(PATH_HM)/TLibCommon/TComLoopFilter.cpp \
    $(PATH_HM)/TLibCommon/TComPrediction.cpp \
    $(PATH_HM)/TLibCommon/SEI.cpp \
    $(PATH_HM)/TLibCommon/TComPicYuvMD5.cpp \
    $(PATH_HM)/TLibCommon/TComRdCost.cpp \
    $(PATH_HM)/TLibCommon/TComBitStream.cpp \
    $(PATH_HM)/TLibCommon/TComTrQuant.cpp \
    $(PATH_HM)/TLibCommon/TComSlice.cpp \
    $(PATH_HM)/TLibCommon/TComPicYuv.cpp \
    $(PATH_HM)/TLibCommon/TComDataCU.cpp \
    $(PATH_HM)/TLibCommon/TComWeightPrediction.cpp \
    $(PATH_HM)/TLibCommon/TComInterpolationFilter.cpp \
    $(PATH_HM)/TLibCommon/ContextModel.cpp \
    $(PATH_HM)/TLibCommon/TComRom.cpp \
    $(PATH_HM)/TLibCommon/TComMotionInfo.cpp \
    $(PATH_HM)/TLibCommon/ContextModel3DBuffer.cpp \
    $(PATH_HM)/TLibCommon/TComYuv.cpp \
    $(PATH_HM)/TLibCommon/TComPicSym.cpp
    LOCAL_STATIC_LIBRARIES := ~/android-ndk/sources/cxx-stl/stlport/libs/armeabi/libstlport_static.a
    LOCAL_LDLIBS := -llog
    # 导出动态库
    include $(BUILD_SHARED_LIBRARY)
    
    
    

    同时可以在JNI目录下建立一个Application.mk文件,内容如下:

    1. APP_PROJECT_PATH := $(call my-dir)/..    
    2. APP_PLATFORM := android-10    
    3. APP_STL := stlport_static    
    4. APP_ABI := armeabi-v7a    
    5. APP_CPPFLAGS += -fexceptions  
    APP_PROJECT_PATH := $(call my-dir)/..  
    APP_PLATFORM := android-10  
    APP_STL := stlport_static  
    APP_ABI := armeabi-v7a  
    APP_CPPFLAGS += -fexceptions
    
    JNI目录的结构是这样子的::


    五、编译


          命令行下cd到工程文件目录,即 PROJECT_DIR ,然后执行 ndk-build 指令即可。

          不知到在什么情况下需要JNI_OnLoad,想知道怎么弄可以看这里:http://blog.csdn.net/luhuajcdd/article/details/7750146

          完毕后在Eclipse下执行build,生成并且 Run 就会生成apk文件

         命令行模式下需要安装ant工具,首先执行 sudo apt-get install ant

          安装完毕后创建一个签名文件,详细请看http://blog.csdn.net/aeolus1019/article/details/8121031

          为了使ant编译工程时能够自动打包签名文件,在工程目录的ant.properties文件的末尾增加这样几行:

    1. key.alias=mNcDecoder.keystore  
    2. key.store=mNcDecoder.keystore  
    3. key.store.password=这里该成密码  
    4. key.alias.password=这里改成密码  
    key.alias=mNcDecoder.keystore
    key.store=mNcDecoder.keystore
    key.store.password=这里该成密码
    key.alias.password=这里改成密码
          上述操作都完成后最后执行:

          ant release

    (如果编译出错,请查看local.properties中的 SDK 路径是否正确,这只针对自己出于某些需要移动了SDK目录的情况)

    六、生成apk与测试

            用Eclipse选择 Run as Android app,然后会自动启动模拟器或者连接Android设备,

            大家可以用自己的手机进行测试,模拟器太慢了啊。

            怎么创建模拟器这里不讨论了。

            命令行模式下,需要用adb指令。可以这么弄:

            abd install -r bin/NcHevcPlayer-release.apk

            其中-r参数表示重新安装,可以在此之前先卸载  adb uninstall com.NcHevc

    最后为了使整个过程简单完成,可以写这样的一个shell脚本,保存成run.sh文件放到工程目录下,并且附加执行权限:

    1. echo -e "\033[41;32;1m 清除 bin 文件目录下的内容 \033[0m"  
    2. rm -r bin  
    3. echo -e "\033[41;32;1m 建立共享库 NcHevcDecoder  \033[0m"  
    4. ndk-build  
    5. echo -e "\033[41;32;1m 编译生成 APK \033[0m"  
    6. ant release  
    7. echo -e "\033[41;32;1m 清除原先安装版本 \033[0m"  
    8. adb devices  
    9. adb uninstall com.NcHevc  
    10. echo -e "\033[41;32;1m 安装最新版到手机或模拟设备 \033[0m"  
    11. adb install -r bin/NcHevcPlayer-release.apk  
    12. echo -e "\033[41;32;1m 正在清除系统日志 \033[0m"  
    13. adb logcat -c  
    14. echo -e "\033[41;32;1m 操作完成,请进行手机测试 \033[0m"  
    15. echo -e "\033[41;32;1m 以下为调试信息,结束查看日志按Ctrl+C即可 \033[0m"  
    16. # adb logcat -v time *:I > logcat.txt  
    17. adb logcat -v time NcHevcPlayerActivity:I *:S  
    echo -e "\033[41;32;1m 清除 bin 文件目录下的内容 \033[0m"
    rm -r bin
    echo -e "\033[41;32;1m 建立共享库 NcHevcDecoder  \033[0m"
    ndk-build
    echo -e "\033[41;32;1m 编译生成 APK \033[0m"
    ant release
    echo -e "\033[41;32;1m 清除原先安装版本 \033[0m"
    adb devices
    adb uninstall com.NcHevc
    echo -e "\033[41;32;1m 安装最新版到手机或模拟设备 \033[0m"
    adb install -r bin/NcHevcPlayer-release.apk
    echo -e "\033[41;32;1m 正在清除系统日志 \033[0m"
    adb logcat -c
    echo -e "\033[41;32;1m 操作完成,请进行手机测试 \033[0m"
    echo -e "\033[41;32;1m 以下为调试信息,结束查看日志按Ctrl+C即可 \033[0m"
    # adb logcat -v time *:I > logcat.txt
    adb logcat -v time NcHevcPlayerActivity:I *:S

    以后修改了源代码只要运行这个脚本,就可以了,

    停止该脚本的方法是按住 左Ctrl + C 两个键,就会自动终止。

    最后的几条语句是使用logcat输出调试信息,具体可以查看:http://blog.csdn.net/czbever/article/details/5910640

    或者:http://blog.chinaunix.net/uid-23173926-id-109068.html



    七、其他

          JAVA的对象其实是C++的指针,所以使用之前必须要赋值。否则会出现 NullPointerException,自己还不知道怎么回事。

          特别注意:在ARM平台(Android开发)下,char类型默认为 unsigned char,而GCC和MSVC默认为 signed char.

                             使用不慎会导致严重BUG。

            例如这样的程序:

    1. char k = -1;  
    2. int i = k + 1;  // 值应该为0吧。(但是最终结果是256,瞎了把)  
    3. int a[20];  
    4. int j;  
    5. j = a[i];   // 只是举例说明,最后这里会出现动态时错误  
    char k = -1;
    int i = k + 1;  // 值应该为0吧。(但是最终结果是256,瞎了把)
    int a[20];
    int j;
    j = a[i];   // 只是举例说明,最后这里会出现动态时错误
    


    展开全文
  • 请问一下,一个soc是这么调用的 uint8_t* id = NULL; uint32_t length = 0; func(&id, &length); 那么用java jni调用的时候参数怎么写呢,,,小白一个,比较急求大神帮助 传func(String a, Long b)...
  • ===步骤:========================================= ...2.定义本地调用接口(动态导出函数); 3.javah生成头文件; 4.实现c/cpp; 5.编译; 6.加载System.loadLibrary(""); =========================

    ===步骤:=========================================

    1.eclipse下搭建ndk(android-ndk-r10c)环境;

    2.定义本地调用接口(动态库导出函数);

    3.javah生成头文件;

    4.实现c/cpp;

    5.编译;

    6.加载System.loadLibrary("");

    ================================================


    1.eclipse下搭建ndk(android-ndk-r10c)环境:

       ndk:交叉编译环境,内含虚拟机;

    2.定义本地调用接口(动态库导出函数):

    
    package com.rdaonicelk.dev.com.comaccess;
    
    public class SerialPortNative
    {
    
    ...
     static private native int open(String path, int bandrate);
     static private native void close(int fd);
     static private native int write(int fd, byte[] data);
     static private native int write(int fd, byte[] data, int off, int len);
     static private native int read(int fd, byte[] data);
     static private native int read(int fd, byte[] data, int off, int readLen);
     static private native int getErrno();
     
     static
     {
      System.loadLibrary("SerialPortNative");
     }
    }
    

    3.javah生成头文件:

    (对SerialPortNative.class文件生成头文件)

    javah com.rdaonicelk.dev.com.comaccess.SerialPortNative

    4.实现c/cpp:

    注意:"*.c"和"*.cpp"对应的JNIEnv宏的定义不一样,以下是"*.c"的使用方法

    #include "com_rdaonicelk_dev_com_comaccess_SerialPortNative.h"
    #include <termios.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <stdio.h>
    
    
    /*
     * Class:     com_rdaonicelk_dev_com_comaccess_SerialPortNative
     * Method:    open
     * Signature: (Ljava/lang/String;IIII)I
     */
    JNIEXPORT jint JNICALL Java_com_rdaonicelk_dev_com_comaccess_SerialPortNative_open
      (JNIEnv *env, jclass thiz, jstring path, jint baud)
    {
    	int fd; /* File descriptor for the port */
    	int nRet;
    
    	speed_t speed;
    
    	/* Check arguments */
    	speed = getBaudrate(baud);
    	if (speed == -1)
    	{
    		return -1;
    	}
    
    	jboolean iscopy;
    	const char *path_utf = (*env)->GetStringUTFChars(env, path, &iscopy);
    	fd = open(path_utf, O_RDWR | O_NOCTTY | O_NDELAY);
    	(*env)->ReleaseStringUTFChars(env, path, path_utf);
    	if (fd == -1)
    	{
    		return -2;
    	}
    
    	fcntl(fd, F_SETFL, 1);//async
    	//fcntl(fd, F_SETFL, 0);//sync
    
    	/* Configure device */
    	struct termios cfg;
    
    	if (tcgetattr(fd, &cfg) != 0)
    	{
    		//LOGE("tcgetattr() failed");
    		close(fd);
    		return -3;
    	}
    
    	cfmakeraw(&cfg);
    	cfsetispeed(&cfg, speed);
    	cfsetospeed(&cfg, speed);
    	/*
    	 * Enable the receiver and set local mode...
    	 */
    	cfg.c_cflag |= (CLOCAL | CREAD);
    
    	cfg.c_cflag &= ~PARENB;
    	cfg.c_cflag &= ~CSTOPB;
    	cfg.c_cflag &= ~CSIZE;
    	cfg.c_cflag |= CS8;
    
    	nRet=ioctl(fd, TCSETS, &cfg);
    //		if (tcsetattr(fd, TCSANOW, &cfg) != 0)
    //		{
    //			close(fd);
    //			return -4;
    //		 }
    
    	return fd;
    }
    
    
    
    
    JNIEXPORT void JNICALL Java_com_rdaonicelk_dev_com_comaccess_SerialPortNative_close
      (JNIEnv *env, jclass thiz, jint fd)
    {
     if(fd < 0)
     {
      return;
     }
    
     close(fd);
    
     return;
    }
    
    /*
     * Class:     com_rdaonicelk_dev_com_comaccess_SerialPortNative
     * Method:    write
     * Signature: (I[B)I
     */
    JNIEXPORT jint JNICALL Java_com_rdaonicelk_dev_com_comaccess_SerialPortNative_write__I_3B
      (JNIEnv *env, jclass thiz, jint fd, jbyteArray data)
    {
     int dataSize=(*env)->GetArrayLength(env, data);
     unsigned char * p=(*env)->GetByteArrayElements(env, data, JNI_FALSE);
    
     int nRet=write(fd,  p, dataSize);
    
     (*env)->ReleaseByteArrayElements(env,data,p,0);
    
     return nRet;
    }
    
    /*
     * Class:     com_rdaonicelk_dev_com_comaccess_SerialPortNative
     * Method:    write
     * Signature: (I[BII)I
     */
    JNIEXPORT jint JNICALL Java_com_rdaonicelk_dev_com_comaccess_SerialPortNative_write__I_3BII
      (JNIEnv *env, jclass thiz, jint fd, jbyteArray data, jint off, jint len)
    {
     int dataSize=(*env)->GetArrayLength(env, data);
     unsigned char * p=(*env)->GetByteArrayElements(env, data, JNI_FALSE);
    
     int nRet=write(fd,  p+off, len);
    
     (*env)->ReleaseByteArrayElements(env,data,p,0);
    
     return nRet;
    }
    

    5.编译:

    创建Android.mk.声明需ndk编译的源文件

    LOCAL_PATH := $(call my-dir)
    include $(CLEAR_VARS)
    LOCAL_MODULE := SerialPortNative
    LOCAL_SRC_FILES := com_<span style="font-family: Arial, Helvetica, sans-serif;">rdaonicelk</span><span style="font-family: Arial, Helvetica, sans-serif;">_dev_com_comaccess_SerialPortNative.c</span>
    include $(BUILD_SHARED_LIBRARY)

    创建Application.mk,指定交叉编译的目标CPU架构

    可指定编译输出多个不同CPU架构目标文件,用空格分隔.或使用关键字"all"指定生成所有支持的CPU架构的目标文件

    APP_ABI := armeabi


    6.加载System.loadLibrary(""):

     static
     {
      System.loadLibrary("SerialPortNative");
     }


    
    展开全文
  • NDK全称是Native Development Kit,NDK提供了一系列的工具,帮助开发者快速开发C(或C++)的动态,并能自动将so和java应用一起打包成apk。NDK集成了交叉编译器(交叉编译器需要UNIX或LINUX系统环境),并提供了...
  • 本博客主要说明在Android Studio中使用jin调用C中代码打开设备节点并且发送命令,在安卓中不能直接调用C方法,只能通过.c文件生成So,使用安卓代码调用so调用C文件中的方法 废话不多说,直接上代码: 我的Android ...
  • 一.Android平台如果要调用一些C/C++语言的所编译生成的的函数一般要进行一下几个步骤。  1.确保我们的so是用 ndk 或者 arm-linux-androideabi-gcc编译而成,如何编译参考上一篇文章。  2.如果我们的安卓...
  • Aid Learning比较好的支持了gcc、gfortran!具体搭建方式见下文:myastrotong:把安卓手机性能发挥到极致之-Termux/Aid Learning使用Fortran因此...最好的方式当然是C调用Fortran的遗留!我才不会用Fortran去调用...
  • 安卓HAL层 so文件加载原理

    千次阅读 2016-07-04 15:18:22
    本文分析代码基于安卓6.0 上层app通过jni调用hal层的hw_get_module函数获取硬件模块,这个函数是上层与hal打交道的入口 这里我们就具体来看看hw_get_module的实现 文件路径: vim hardware/libhardware/...
  • Android 调用C方法,在Android Studio中新建.C文件,使用命令生成对应的So,用安卓jin调用so库调用C方法
  • Java调用C/C++

    2016-10-30 16:14:21
    大家都知道java虽然有着...感觉在安卓上这个技术用的很多。 注:本次实验在Mac下进行,Windows和Linux的原理类似,只是动态的命名以及一些路径问题 1.编写Java文件 Temp.class package cn.limbo.pojo; /** *
  • 一.Android平台如果要调用一些C/C++语言的所编译生成的的函数一般要进行一下几个步骤。  1.确保我们的so是用 ndk 或者 arm-linux-androideabi-gcc编译而成,如何编译参考上一篇文章。  2.如果我们的...
  • 比如数据库的调用,当我们下载一个JDBC的jar包之后,解压可以看到里面包含了不同平台的动态链接: 这篇文章介绍如何为Android,Mac和Windows平台,创建一个最简单的JNI动态链接。参考文章:Android下...
  • 安卓JNI

    2020-03-03 11:20:36
    一: 什么是安卓的JNI JNI是Java Native ...JAVA代码如何调用C/C++ (1)创建安卓JAVA工程时选中 include C++ support (2)C/C++是在JAVA中通过System.loadLibrary动态加载的. (3)在JAVA类中添加对应C...
  • 其实不然,因为Linux系统的程序在调用动态的时候有个首先需要访问的动态就是ld-linux.so这个,由这个去访问你自己定义的动态,然后Android上没有这个,所以无法调用自己生成的动态...
  • Android 安卓 H.264软件解码,内部使用JNI调用C库实现
  • android应用如何访问C库

    千次阅读 2016-04-26 11:52:57
    最近由于项目的开发需要,需要用到安卓系统,由此开始安卓的一些学习,下面只作为个人的一些记录。  安卓应用是由java编写的,而在android底层,如安卓底层的硬件驱动程序,...本例要实现的就是JAVA如何访问底层C库
  • 安卓硬件访问服务

    2020-06-22 22:45:53
    1 安卓应用程序通过加载 c库 来访问硬件服务程序 2 安卓 app 通过 loadlibrary 加载 c库 3 一旦c库被加载 JNI_Onload 函数就会被调用,通过jniRegisterNativeMethods 对方法进行调用 4 app 使用 方法调用 硬件 使用...
  • 什么是 NDK? Android NDK 是一套可以让开发者在安卓应用开发...游戏引擎使用 Native 的 C/C++ ,便于跨平台移植,开发游戏应用,使用NDK可以直接调用这些通用应用开发中,像加密、解密以及其他一些核心算法等
  • Android NDK开发之引用纯C库文件

    千次阅读 2017-01-13 10:59:48
    假设你正在做的项目中需要引用一个第三方的C库文件(.so动态库文件),首先判断这个C库是否符合android中规范的JNI标准。 1.如果符合JNI标准,我们就不需要另外写jni文件,而是直接导入库文件(创建jniLibs文件夹,...
  • 二、C代码中引入头文件 三、打印日志的代码(跟C语言中printf的使用方式一样) 四、给jni日志添加开关 一、引入log 1.如果是使用android.mk的方式手动生成so,在android.mk的配置文件中加入配置: ...
  • vargrind 安卓apk

    2017-06-05 09:55:00
    上层为安卓, 下层为调用c/c++ 1、将vargind 按官网方法下载源代码编译 得Inst文件夹 2、通过win 下安卓sdk 中 platform-tools 中的adb push Inst 到/data/local 下 3、可把adb.exe所在文件夹 设置到...
  • gdbserver 安卓apk

    2014-10-31 16:29:00
    底层调用c/c++ 动态, 动态带调试选项 查看手机IP 192.168.1.177 包所调用的c/c++ 是在/data/data/包名/lib/ 下 1、将安卓ndk 文件夹/usr/local/src/android-ndk-r9d/prebuilt/android-arm/gdbserver/...
  • 在我的之前的测评中,我利用Termux和Aid Learning测试过基于C/C++的openmp并行程序,基于...这是主要是因为Android并没有采用glibc作为C库,而是采用了Google自己开发的Bionic Libc,它的官方Toolchain也是基于Bioni...
  • 里面包括博文里介绍的所有Android代码,欢迎下载,包括jni文件夹下的Android.mk、MyString.c、MyString.h文件,libpandasince.so文件,mydemo.apk,mydemo安卓项目代码工程,资源截图如下: Android...
  • 对于一个只懂得如何用Java去调用C++来实现某一种效果的初学者来说,Android编程中jni目录下的Android.mk这样的配置文件几乎是完全有理解障碍的。 Android.mk是eclipse告诉它的插件NDK如何去编译C语言编写的源文件,...

空空如也

空空如也

1 2 3 4 5 ... 7
收藏数 137
精华内容 54
关键字:

安卓调用c库