zoukankan      html  css  js  c++  java
  • 只能用Android studio做平台移植了! 在Windows10下, 开发Android。

     安装好IDE后, 会一直显示同步失败, 看看如下步骤:

    需要注意的是: 

    -> 安装NDK      自带的NDK版本有问题    自己去下一个15版本的

    -> 按照系统提示一步一步安装其他未安装的组件

    -> 最终代码写好后, 需要安装自己的需要创建 android模拟器, 新建一个 X86-android4.4的模拟器;

    开发android程序 - 结构:

    -> AndroidManifest.xml    设置权限, 注册AppCompatActive窗口, 设置主函数入口。

    -> 图片存储在res-drawable,  res-layout调用图片等资源。

    使用android-studio ndk生成 so文件。

    -> 创建C++接口加载器 

     

    ->  手动创建插件

    $JDKPath$injavah
    -d $ModuleFileDir$srcmainjni -jni $FileClass$
    $ModuleFileDir$uildintermediatesclassesdebug
    

      

    ->  build project 一下

    -> 在OpenCVHelper类上右键, 选择External Tool 使用插件

    -> 编辑C文件

    #include "com_admin_opencv4android_OpenCVHelper.h"
    #include <sstream>
    
    
    JNIEXPORT jstring JNICALL
    Java_com_admin_opencv4android_OpenCVHelper_getStringTmp(JNIEnv *env, jclass instance){
        std::stringstream ss;
        ss << "Hello from c++ " << std::endl;
        return env->NewStringUTF(ss.str().c_str());
    }
    

      

    新建 Android.mk
    
    
    LOCAL_PATH := $(call my-dir)
    include $(CLEAR_VARS)
    
    LOCAL_MODULE := OpenCVHelper
    LOCAL_SRC_FILES := MyLib.cpp
    include $(BUILD_SHARED_LIBRARY)
    

      

    新建  Application.mk
    
    
    APP_ABI := all
    APP_STL:=stlport_static
    

      

    ->  使用命令行进入jni目录,  使用ndk命令编译so

    ->  调用刚才生成好的 so

    在app/build 下

    android { ... sourceSets { main() { jniLibs.srcDirs = ['src/main/libs'] jni.srcDirs = [] //屏蔽掉默认的jni编译生成过程 } } }

      

    在主程序中:
    
    
    public class MainActivity extends AppCompatActivity {
    
        private TextView textView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            textView = (TextView) findViewById(R.id.sample_text);
            textView.setText(OpenCVHelper.getStringTmp());
    }
    }
    

      

    使用android studio 整合 opencv第三方库:

    ->  在OpenCVHelper中新增接口函数:

    public class OpenCVHelper {
    
        static {
            System.loadLibrary("OpenCVHelper");
        }
    
        public static native String getStringTmp();
        public static native int[] getGrayImage(int[] pixels, int w, int h);
    }
    

      

    ->  重写MyLib.cpp:

    #include "com_admin_opencv4android_OpenCVHelper.h"
    #include <sstream>
    #include <opencv2/opencv.hpp>
    
    
    
    
    JNIEXPORT jstring JNICALL
    Java_com_admin_opencv4android_OpenCVHelper_getStringTmp(JNIEnv *env, jclass instance){
        std::stringstream ss;
        ss << "Hello from c++ " << std::endl;
        return env->NewStringUTF(ss.str().c_str());
    }
    
    JNIEXPORT jintArray JNICALL
    Java_com_admin_opencv4android_OpenCVHelper_getGrayImage(JNIEnv *env, jobject, jintArray buf, int w, int h){
        jint *pixels = env->GetIntArrayElements(buf, NULL);
        if(pixels == NULL){
            return NULL;
        }
        cv::Mat imgData(h, w, CV_8UC4, pixels);
        uchar *ptr = imgData.ptr(0);
        for(int i=0; i<w*h; i++){
            int grayScale = (int)(ptr[4*i+2]*0.299 + ptr[4*i+1]*0.587 + ptr[4*i+0]*0.114);
            ptr[4*i+0] = (uchar)grayScale;
            ptr[4*i+1] = (uchar)grayScale;
            ptr[4*i+2] = (uchar)grayScale;
        }
        int size = w * h;
        jintArray result = env->NewIntArray(size);
        env->SetIntArrayRegion(result, 0, size, pixels);
        env->ReleaseIntArrayElements(buf, pixels, 0);
        return result;
    }
    

      

    所有配置请参照opencv官网,    https://docs.opencv.org/2.4/doc/tutorials/introduction/android_binary_package/dev_with_OCV_on_Android.html#native-c

    -> Android.mk :

    LOCAL_PATH := $(call my-dir)
    include $(CLEAR_VARS)
    
    OPENCV_CAMERA_MODULES:=on
    OPENCV_INSTALL_MODULES:=on
    OPENCV_LIB_TYPE:=STATIC
    include D:/library/OpenCV-android-sdk/sdk/native/jni/OpenCV.mk
    
    LOCAL_MODULE := OpenCVHelper
    LOCAL_SRC_FILES := MyLib.cpp
    include $(BUILD_SHARED_LIBRARY)
    

      

    -> Application.mk

    APP_ABI := all
    APP_STL := gnustl_static
    APP_CPPFLAGS := -frtti -fexceptions
    

      

    ->  配置好之后, 使用ndk-build

    -> activity_main.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.constraint.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.admin.opencv4android.MainActivity">
    
        <TextView
            android:id="@+id/sample_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="aa!"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
        <ImageView
            android:id="@+id/img"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:srcCompat="@drawable/tutu"
            android:layout_centerInParent="true" />
        <Button
            android:id="@+id/bt_Gray"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_alignParentEnd="true"
            android:text="Gray"  />
    
    </android.support.constraint.ConstraintLayout>
    

      

    -> MainActivity类:

    public class MainActivity extends AppCompatActivity {
    
        private TextView textView;
        private Button bt_photo;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            textView = (TextView) findViewById(R.id.sample_text);
            textView.setText(OpenCVHelper.getStringTmp());
    
    
            bt_photo = (Button) findViewById(R.id.bt_Gray);
            bt_photo.setOnClickListener(new Button.OnClickListener() {
                @Override
                public void onClick(View v) {
                    // TODO Auto-generated method stub
                    ImageView img = (ImageView) findViewById(R.id.img);
                    Bitmap bitmap = ((BitmapDrawable) getResources().getDrawable(
                            R.drawable.tutu)).getBitmap();
                    int w = bitmap.getWidth(), h = bitmap.getHeight();
                    int[] pix = new int[w * h];
                    bitmap.getPixels(pix, 0, w, 0, 0, w, h);
                    int[] resultPixes = OpenCVHelper.getGrayImage(pix, w, h);
                    Bitmap result = Bitmap.createBitmap(w, h, Bitmap.Config.RGB_565);
                    result.setPixels(resultPixes, 0, w, 0, 0, w, h);
                    img.setImageBitmap(result);
                }
            });
    
    
    
    
    
        }
    }
    

      

    ->   至于Cmake之类的,  可以全部注释,  jni全部删除都可以,  因为已经有so了, 甚至头文件都不需要:

    ##################################################################################

    -> 在上述案例中, 是在 jni文件夹中  使用Android.mk 导入存储在本地(项目文件外面)的第三方静态库, 使得jni中需要编译的程序 MyLib.cpp可以引用opencv,   并指定 LOCAL_MODULE := OpencvHelper

    -> 编译好后的 .so 通过build.gradle   jniLibs.srcDirs = ['src/main/libs']  在编译器链接动态库,

    -> 在实现native的接口类中,  System.loadLibrary("OpenCVHelper"); 在java程序中加载动态库。

    编译zbar生成其动态库, 并调用摄像头扫描二维码。

    ->  使用zbar, libiconv编译 .so,  并使用java编写扫描程序的项目:   https://blog.csdn.net/yanzhenjie1003/article/details/71641368

    -> 添加完整工程zbar, 对第一次使用android studio ndk的人来说 难度不小,  不如先从一个小案例做起: 

    新建一个 first.h  头文件
    
    #ifndef OPENCV4ANDROID_COMPILE_ZBAR_FIRST_H
    #define OPENCV4ANDROID_COMPILE_ZBAR_FIRST_H
    int add(int input);
    #endif //OPENCV4ANDROID_COMPILE_ZBAR_FIRST_H 
    
    
    first.cpp
    
    #include "first.h"
    
    int add(int input)
    {
        return input * 2;
    }
    
    
    在交叉接口 MyLib.cpp 中:
    
    #include "com_admin_opencv4android_ZbarHelper.h"
    #include <sstream>
    #include "first.h"
    
    JNIEXPORT jstring JNICALL
    Java_com_admin_opencv4android_ZbarHelper_getStringTmp(JNIEnv *env, jclass instance, jint prompt){
    
        int c = prompt;
        int result = add(c);
    
        std::stringstream ss;
        ss << "Hello from c++ " << std::endl;
        ss << result << std::endl;
    
        return env->NewStringUTF(ss.str().c_str());
    }
    

      

    Android.mk
    
    LOCAL_PATH := $(call my-dir)
    include $(CLEAR_VARS)
    
    LOCAL_MODULE := ZbarHelper
    
    LOCAL_SRC_FILES := 
    first.cpp 
    MyLib.cpp
    
    LOCAL_C_INCLUDES := 
    			$(LOCAL_PATH)/first.h 
    
    include $(BUILD_SHARED_LIBRARY)
    

      

    在第一次使用ndk编译时,   总提示    undefine   function  add() ..... ,     我反复检查 无论是在 LOCAL_SRC_FILES, LOCAL_C_INCLUDES 中该函数的 头文件 或 实现函数 都在classpath下, 不会有错!

    最终查明,  在使用ndk编译时,  需要将CMakeLists.txt 中的所有选项都注释掉,  就不会找不到引用。

      

    在使用ndk编译c++时, 报错 找不到 #include exception , 因为ndk编译器 默认最小库编译,  因此在 Application.mk里添加   APP_STL := gnustl_static    APP_CPPFLAGS := -frtti -fexceptions

    在做平台移植时, 最麻烦的问题在于 要考虑 目标平台编译器的问题。

     android.mk 使用进阶: 

    对编译成功的so库  进行预编译加载
    
    LOCAL_PATH := $(call my-dir)
    include $(CLEAR_VARS)
    LOCAL_MODULE := zbar
    LOCAL_SRC_FILES := libs/libzbar.so
    
    LOCAL_EXPORT_C_INCLUDES := 
                       $(LOCAL_PATH)/include 
                       $(LOCAL_PATH)/zbar
    include $(PREBUILT_SHARED_LIBRARY)
    
    
    调用该库
    ## -------------------------------------
    
    include $(CLEAR_VARS)
    
    LOCAL_MODULE := ZbarHelper
    
    LOCAL_C_INCLUDES += 
                       $(LOCAL_PATH)/include 
                       $(LOCAL_PATH)/zbar 
    
    LOCAL_SRC_FILES := MyLib.cpp
    
    LOCAL_SHARED_LIBRARIES := 
                       zbar
    
    
    include $(BUILD_SHARED_LIBRARY)
    

      

     一些参考资料地址:             https://www.cnblogs.com/tt2015-sz/p/6148723.html

    ndk-build 时, 找不到 mathcalls.h 系统库,   将 APP_PLATFORM := android-19,  因为之前的系统库 没有相应的库。

    
    
    
  • 相关阅读:
    jdbc连接数据库 url
    解决IntelliJ IDEA 使用 TOMCAT 中文乱码问题
    web.xml 4.0 头部信息
    jar包冲突解决方案
    idea 快捷键
    基于单片机的车辆防碰撞及自动刹车系统(STC89C52RC芯片+超声波传感器HC-SR04+液晶屏1602+继电器+蜂鸣器)
    电子时钟万年历+51单片机+1602液晶屏+DS1302+DS18B20+按键
    1008 数组元素循环右移问题(PAT)
    1007 素数对猜想(PAT)
    1006 换个格式输出整数(PAT)
  • 原文地址:https://www.cnblogs.com/ruili07/p/9891233.html
Copyright © 2011-2022 走看看