Xưởng Android, lớp và NDK


153

Tôi rất mới với toàn bộ lớp này và hỗ trợ Android Studio. Tôi đã quản lý để chuyển đổi dự án Android của mình sang cấp bằng cách sử dụng tùy chọn xuất.

Nhưng tôi đang tìm kiếm một số tài liệu hoặc điểm bắt đầu làm thế nào để tích hợp bản dựng NDK vào quy trình xây dựng lớp.

Nếu có thể tôi cũng cần một số giai đoạn "sau" sao chép các tệp nhị phân xây dựng (tệp .so) vào thư mục nội dung.


Tôi đã đăng câu trả lời của mình trong liên kết được đề cập bên dưới stackoverflow.com/questions/20900814/ Kẻ
Ahmad Ali Nasir

24
Độc giả mới: Hãy biết rằng câu hỏi này ban đầu được hỏi trong giai đoạn thử nghiệm Android Studio; câu trả lời đã thay đổi theo thời gian. Hãy chú ý đến phiên bản Gradle được đề cập trong các câu trả lời, cũng như khi các câu trả lời thực sự được đăng.
Sean Beach

Nếu có điều gì đó thực sự thay đổi, tôi sẽ chỉnh sửa câu hỏi để chọn lại trạng thái
plaisthos

Android Studio 1.3 tại kênh canary hỗ trợ đầy đủ NDK. Tham khảo: tools.android.com/doad/studio/canary/latest
Vikasdeep Singh

Ngày 18 tháng 6 năm 2015: Android Studio 1.3 Beta hiện có sẵn trong kênh beta! Xin lỗi, bản dựng này chưa có hỗ trợ C / C ++; nguồn: tools.android.com/recent/androidstudio13betaav Available
fastr.de

Câu trả lời:


85

Chúng tôi đã phát hành phiên bản đầu tiên của tích hợp dưới dạng bản xem trước trong 1.3: http://tools.android.com/tech-docs/android-ndk-preview

Việc tích hợp sẽ ở lại một bản xem trước ngay cả sau khi 1.3 trở thành cuối cùng. Không có ETA hiện tại khi nào nó sẽ là trận chung kết (kể từ 2015/07/10).

Thêm thông tin tại đây: http://tools.android.com/tech-docs/android-ndk-preview


2
Sẽ thật tuyệt nếu tôi có thể sử dụng NDK và hoàn thành lệnh với gỡ lỗi trong Android Studio (và hỗ trợ Gradle)
Powder366

1
@GREnvoy - Làm cách nào để định cấu hình trình tạo NDK phù hợp trong studio Android? Bạn có thể cho tôi các bước? :)
Shravan

7
@DentyBeach Tại sao nó đã lỗi thời? Vẫn chưa có sự tích hợp của NDK trong Studio. Chúng tôi đang làm việc trên nó nhưng không có ETA tại thời điểm này.
Xavier Ducrohet

2
Hành động của tôi dựa trên cách tôi xác định "tích hợp". Tôi hiểu nó có nghĩa là "một cách sử dụng NDK với gradle" hiện đang tồn tại, mặc dù không có giải pháp nào trong số chúng là giải pháp tuyệt vời. Tuy nhiên, dựa trên nhận xét của bạn, có vẻ như nhóm của bạn có ý tưởng khác về việc tích hợp thực sự có thể là gì. Tôi rút lại tuyên bố trước đây của tôi.
Sean Beach

2
Tích hợp NDK đã được công bố trong Google IO 2015. Nó có sẵn trong Android Studio 1.3 (có thể tải xuống bản xem trước. Tôi sẽ đăng một liên kết khi có sẵn).
Cypress Frankenfeld

43

CẬP NHẬT: Hiện tại Android Studio có hỗ trợ NDK: http://tools.android.com/tech-docs/android-ndk-preview

Để xây dựng với một kịch bản, giải pháp lớp dưới đây sẽ hoạt động:

Tôi đang sử dụng tập lệnh xây dựng của mình và thêm vào tệp của mình (Có vẻ như để làm việc 0.8+): Điều này có vẻ tương đương với giải pháp bên dưới (nhưng trông đẹp hơn trong tệp lớp):

 android {
    sourceSets {
        main {
            jniLibs.srcDirs = ['native-libs']
            jni.srcDirs = [] //disable automatic ndk-build
        }
    }
 }

Rất tiếc, bản dựng không bị lỗi nếu thư mục không có hoặc không chứa .sotệp.


5
Điều này không hoạt động nữa với phiên bản Android Studio mới, giải pháp thay thế?
bột366

@ Powder366 Xem câu trả lời của tôi.
Leandros

2
Một chút phép thuật Groovy : tasks.withType(com.android.build.gradle.tasks.PackageApplication) { it.jniFolders = [file("libs")] as Set }. Cảm ơn các bạn đã giúp đỡ!
trnl

Quy trình cho android Studio 0.8.9
Pandiri Deepak

1
@plaisthos Cảm ơn rất nhiều vì đã chỉ ra hướng đi đúng đắn! Dòng thứ hai trong tập lệnh gradle jni.srcDirs = [] //disable automatic ndk-buildrất quan trọng vì nó sẽ ngăn Android Studio xây dựng lại mã nguồn C / C ++. Tôi đã cố gắng để tìm ra điều này trong hai ngày cho đến khi tôi thấy bài viết của bạn và điều này đã giải quyết vấn đề của tôi. Tôi thực sự nghĩ rằng bản dựng NDK được xây dựng riêng biệt tốt hơn chỉ bằng cách tạo dòng lệnh Android.mk chứ không phải bằng tập lệnh phân lớp vì C / C ++ đã được Makefile xây dựng trong hơn 40 năm!
tonga

40

Với việc cập nhật Android Studio lên 1.0, hỗ trợ chuỗi công cụ NDK đã cải thiện rất nhiều ( lưu ý: vui lòng đọc các cập nhật của tôi ở cuối bài đăng này để xem cách sử dụng với plugin Gradle thử nghiệm mới và Android Studio 1.5 ).

Android Studio và NDK được tích hợp đủ tốt để bạn chỉ cần tạo một khối ndk {} trong build.gradle của mô-đun và đặt các tệp nguồn của bạn vào thư mục (mô-đun) / src / main / jni - và bạn làm xong!

Không còn ndk-build từ dòng lệnh.

Tôi đã viết tất cả về nó trong bài đăng trên blog của tôi ở đây: http://www.sureshjoshi.com/mobile/android-ndk-in-android-studio-with-swig/

Các điểm nổi bật là:

Có hai điều bạn cần biết ở đây. Theo mặc định, nếu bạn có các lib bên ngoài mà bạn muốn tải vào ứng dụng Android, chúng sẽ được tìm kiếm trong (mô-đun) / src / main / jniLibs theo mặc định. Bạn có thể thay đổi điều này bằng cách sử dụng cài đặt sourceSets.main.jniLibs.srcDirs trong build.gradle của mô-đun. Bạn sẽ cần một thư mục con với các thư viện cho mỗi kiến ​​trúc bạn đang nhắm mục tiêu (ví dụ: x86, arm, mips, arm64-v8a, v.v ...)

Mã bạn muốn được biên dịch theo mặc định bởi công cụ NDK sẽ được đặt trong (mô-đun) / src / main / jni và tương tự như trên, bạn có thể thay đổi mã bằng cách đặt sourceSets.main.jni.srcDirs trong build.gradle của mô-đun của bạn

và đặt cái này vào build.gradle của mô-đun của bạn:

ndk {
  moduleName "SeePlusPlus" // Name of C++ module (i.e. libSeePlusPlus)
  cFlags "-std=c++11 -fexceptions" // Add provisions to allow C++11 functionality
  stl "gnustl_shared" // Which STL library to use: gnustl or stlport
}

Đó là quá trình biên dịch mã C ++ của bạn, từ đó bạn cần tải nó và tạo các hàm bao - nhưng đánh giá từ câu hỏi của bạn, bạn đã biết cách thực hiện tất cả điều đó, vì vậy tôi sẽ không băm lại.

Ngoài ra, tôi đã đặt một repo Github của ví dụ này tại đây: http://github.com/sureshjoshi/android-ndk-swig-example

CẬP NHẬT: ngày 14 tháng 6 năm 2015

Khi Android Studio 1.3 xuất hiện, cần có sự hỗ trợ tốt hơn cho C ++ thông qua plugin JetBrains CLion. Tôi hiện đang theo giả định rằng điều này sẽ cho phép phát triển Java và C ++ từ bên trong Android Studio; tuy nhiên tôi nghĩ rằng chúng ta vẫn cần sử dụng phần Gradle NDK như tôi đã nêu ở trên. Ngoài ra, tôi nghĩ vẫn sẽ cần phải viết các tệp trình bao bọc Java <-> C ++, trừ khi CLion sẽ tự động thực hiện chúng.

CẬP NHẬT: ngày 5 tháng 1 năm 2016

Tôi đã cập nhật blog và Github repo (trong nhánh phát triển) để sử dụng Android Studio 1.5 với plugin Gradle thử nghiệm mới nhất (0.6.0-alpha3).

http://www.sureshjoshi.com/mobile/android-ndk-in-android-studio-with-swig/ http://github.com/sureshjoshi/android-ndk-swig-example

Bản dựng Gradle cho phần NDK bây giờ trông như thế này:

android.ndk {
    moduleName = "SeePlusPlus" // Name of C++ module (i.e. libSeePlusPlus)
    cppFlags.add("-std=c++11") // Add provisions to allow C++11 functionality
    cppFlags.add("-fexceptions")
    stl = "gnustl_shared" // Which STL library to use: gnustl or stlport
}

Ngoài ra, khá khủng khiếp, Android Studio đã tự động hoàn thành cho C ++ - các trình bao bọc được tạo bởi Java bằng cách sử dụng từ khóa 'gốc':

Ví dụ về tự động hoàn thành C ++ - Trình bao bọc Java

Tuy nhiên, nó không hoàn toàn màu hồng ... Nếu bạn đang sử dụng SWIG để bọc thư viện để tự động tạo mã, sau đó thử sử dụng tự động tạo từ khóa gốc, nó sẽ đặt mã sai vị trí trong Swig _wrap của bạn Tệp .cxx ... Vì vậy, bạn cần di chuyển nó vào khối "extern C":

C ++ - Trình bao bọc Java di chuyển đến vị trí chính xác

CẬP NHẬT: ngày 15 tháng 10 năm 2017

Tôi sẽ cảm thấy hối hận nếu tôi không đề cập rằng Android Studio 2.2 trở đi về cơ bản có hỗ trợ 'bản địa' (không chơi chữ) cho chuỗi công cụ NDK thông qua Gradle và CMake. Bây giờ, khi bạn tạo một dự án mới, chỉ cần chọn hỗ trợ C ++ và bạn đã sẵn sàng.

Bạn vẫn sẽ cần tạo mã lớp JNI của riêng mình hoặc sử dụng kỹ thuật SWIG mà tôi đã đề cập ở trên, nhưng giàn giáo của một dự án C ++ trong Android là không đáng kể.

Các thay đổi trong tệp CMakeLists (là nơi bạn đặt các tệp nguồn C ++ của mình) sẽ được Android Studio chọn và nó sẽ tự động biên dịch lại bất kỳ thư viện liên quan nào.


1
đặt * .so trong (mô-đun) / src / main / jniLibs
fawkes 16/1/2015

tại sao NDEBUG luôn được đặt khi sử dụng Android Studio, ngay cả trên các bản dựng gỡ lỗi
pt123

35

Trong Google IO 2015, Google đã công bố tích hợp NDK đầy đủ trong Android Studio 1.3.

Hiện tại nó đã được xem trước và có sẵn cho tất cả mọi người: https://developer.android.com/studio/projects/add-native-code.html

Câu trả lời cũ: Gradle tự động gọi ndk-buildnếu bạn có một jnithư mục trong các nguồn dự án của bạn.

Điều này đang làm việc trên Android studio 0.5.9 (xây dựng canary).

  1. Tải xuống NDK

  2. Thêm ANDROID_NDK_HOMEvào các biến môi trường của bạn hoặc thêm ndk.dir=/path/to/ndkvào local.propertiesdự án Android Studio của bạn. Điều này cho phép studio Android chạy ndk tự động.

  3. Tải về các dự án mẫu lớp mới nhất để xem ví dụ về dự án ndk. (Họ ở cuối trang). Một dự án mẫu tốt là ndkJniLib.

  4. Sao chép gradle.buildtừ các dự án mẫu NDK. Nó sẽ trông giống như thế này. Điều này gradle.buildtạo ra một apk khác nhau cho mỗi kiến ​​trúc. Bạn phải chọn kiến ​​trúc nào bạn muốn bằng cách sử dụng build variantskhung. xây dựng các biến thể khung

    apply plugin: 'android'
    
    dependencies {
        compile project(':lib')
    }
    
    android {
        compileSdkVersion 19
        buildToolsVersion "19.0.2"
    
        // This actual the app version code. Giving ourselves 100,000 values [0, 99999]
        defaultConfig.versionCode = 123
    
        flavorDimensions "api", "abi"
    
        productFlavors {
            gingerbread {
                flavorDimension "api"
                minSdkVersion 10
                versionCode = 1
            }
            icecreamSandwich {
                flavorDimension "api"
                minSdkVersion 14
                versionCode = 2
            }
            x86 {
                flavorDimension "abi"
                ndk {
                    abiFilter "x86"
                }
                // this is the flavor part of the version code.
                // It must be higher than the arm one for devices supporting
                // both, as x86 is preferred.
                versionCode = 3
            }
            arm {
                flavorDimension "abi"
                ndk {
                    abiFilter "armeabi-v7a"
                }
                versionCode = 2
            }
            mips {
                flavorDimension "abi"
                ndk {
                    abiFilter "mips"
                }
                versionCode = 1
            }
            fat {
                flavorDimension "abi"
                // fat binary, lowest version code to be
                // the last option
                versionCode = 0
            }
        }
    
        // make per-variant version code
        applicationVariants.all { variant ->
            // get the version code of each flavor
            def apiVersion = variant.productFlavors.get(0).versionCode
            def abiVersion = variant.productFlavors.get(1).versionCode
    
            // set the composite code
            variant.mergedFlavor.versionCode = apiVersion * 1000000 + abiVersion * 100000 + defaultConfig.versionCode
        }
    
    }

Lưu ý rằng điều này sẽ bỏ qua các tệp Android.mk và Application.mk của bạn. Như một giải pháp thay thế, bạn có thể yêu cầu gradle tắt cuộc gọi ndk-build atuomatic, sau đó chỉ định thư mục cho các nguồn ndk theo cách thủ công.

sourceSets.main {
    jniLibs.srcDir 'src/main/libs' // use the jni .so compiled from the manual ndk-build command
    jni.srcDirs = [] //disable automatic ndk-build call
}

Ngoài ra, bạn có thể muốn gọi ndk-build trong tập lệnh xây dựng lớp của bạn một cách rõ ràng, bởi vì bạn vừa tắt cuộc gọi tự động.

task ndkBuild(type: Exec) {
   commandLine 'ndk-build', '-C', file('src/main/jni').absolutePath
}

tasks.withType(JavaCompile) {
    compileTask -> compileTask.dependsOn ndkBuild
}

Đúng. Nhưng điều đó chỉ hoạt động trong các nền tảng Unix và cũng bị giới hạn nếu bạn phức tạp hơn cấu hình / makefiles rất đơn giản.
plaisthos

Có, nó sẽ tự động tạo các tệp tạo tệp cho những thứ giới hạn mà bạn có thể đặt trong tệp xây dựng lớp, tuy nhiên có một cách giải quyết. Tôi đã thêm nó vào câu trả lời của tôi.
Cypress Frankenfeld

1
Cuộc gọi đến ndk-build sẽ chỉ hoạt động ở dòng lệnh không có trong Android Studio.
Cameron Lowell Palmer

Mặc dù đây không phải là câu trả lời gần đây nhất, nhưng dường như nó là chính xác nhất. Đặc biệt chú ý đến bước 3: "Tải xuống các dự án mẫu lớp mới nhất ".
Sean Beach

4
Tôi sử dụng bản hack này thay vì vô hiệu hóa src dir để tôi có thể chỉnh sửa các tệp c / c ++ trong idetasks.all { task -> if (task.name.contains('Ndk')) task.enabled = false }
sherpya

23

Tôi đã tìm thấy "gradle 1.11 com.android.tools.build:gradle 0.9.+" hỗ trợ trước khi xây dựng ndk, bạn chỉ có thể đặt * .so trong dir src / main / jniLibs. khi xây dựng lớp sẽ đóng gói ndk đến đúng nơi.

đây là dự án của tôi

Dự án:
| -
| - | - chính
| - | - | --java
| - | - | --jniLib
| - | - | - | --armeabi
| - | - | - | - | -.
|
| - | --ther.jar


16

Đến bây giờ (Android Studio v0.8.6) nó khá đơn giản. Dưới đây là các bước để tạo ứng dụng loại "Hello world":

  1. Tải xuống Android NDK và đặt thư mục gốc ở đâu đó lành mạnh - có thể ở cùng vị trí với thư mục SDK.

  2. Thêm phần sau vào local.propertiestập tin của bạn : ndk.dir=<path-to-ndk>

  3. Thêm phần sau vào tệp build.gradle của bạn bên trong bao defaultConfigđóng, ngay sau versionNamedòng:ndk { moduleName="hello-world" }

  4. Trong mainthư mục mô-đun ứng dụng của bạn , tạo một thư mục mới được gọi là jni.

  5. Trong thư mục đó, tạo một tệp có tên hello-world.c, bạn sẽ thấy bên dưới.

  6. Xem Activitymã ví dụ dưới đây để biết ví dụ về cách gọi một phương thức (hoặc nó là một hàm?) Trong hello-world.c.


hello-world.c

#include <string.h>
#include <jni.h>

jstring
Java_me_mattlogan_ndktest_MainActivity_stringFromJNI(JNIEnv* env, jobject thiz)
{
    return (*env)->NewStringUTF(env, "Hello world!");
}

MainActivity.java

public class MainActivity extends Activity {

    static {
        System.loadLibrary("hello-world");
    }

    public native String stringFromJNI();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        String testString = stringFromJNI();

        TextView mainText = (TextView) findViewById(R.id.main_text);
        mainText.setText(testString);
    }
}

build.gradle

apply plugin: 'com.android.application'

android {
    compileSdkVersion 20
    buildToolsVersion "20.0.0"

    defaultConfig {
        applicationId "me.mattlogan.ndktest"
        minSdkVersion 15
        targetSdkVersion 20
        versionCode 1
        versionName "1.0"

        ndk {
            moduleName "hello-world"
        }
    }
    buildTypes {
        release {
            runProguard false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
}

Tìm mã nguồn đầy đủ của một ứng dụng rất giống nhau ở đây (trừ NDK).


Tôi đang làm chính xác như được hướng dẫn trong dự án hiện tại của mình, nhưng công cụ NDK vẫn chưa được xây dựng. Có ý kiến ​​gì không? Có vẻ như nó đang xây dựng mọi thứ khác, nhưng chỉ bỏ qua những thứ jni.
alice.harrison

@NannuoLei cảm ơn, tôi đã thử nhưng tôi đang gặp vấn đề trong đó .so không được tạo. Mọi thứ khác dường như hoạt động, nhưng khi tôi chạy apkg trong trình giả lập, nó phàn nàn rằng nó không thể tải đối tượng chia sẻ.
aaa90210

@ aaa90210 là trình giả lập của bạn dựa trên hình ảnh x86? Theo mặc định, NDK sẽ chỉ tạo thư viện ARMEABI, nếu bạn muốn xây dựng hình ảnh x86, bạn có thể thêm dòng này vào Application.mk: APP_ABI: = armeabi x86
Leo hỗ trợ Monica Cellio vào

1
nó đã làm việc với tôi Tái bút: bất cứ ai nhìn thấy câu trả lời này, đừng quên đổi Java_me_mattlogan_ndktest_MainActivity_stringFromJNIsang câu trả lời của riêng bạn :)
AbdulMomen عبدالمؤمن

8

Nếu bạn đang unix phiên bản mới nhất (0.8) sẽ thêm ndk-build. Đây là cách thêm nó:

android.ndk {
    moduleName "libraw"
}

Nó hy vọng sẽ tìm thấy JNI trong 'src / main / jni', nếu không bạn có thể định nghĩa nó bằng:

sourceSets.main {
    jni.srcDirs = 'path'
}

Kể từ 28 JAN 2014 với phiên bản 0.8, bản dựng bị hỏng trên windows, bạn phải tắt bản dựng với:

sourceSets.main {
    jni.srcDirs = [] //disable automatic ndk-build call (currently broken for windows)
}

1
Có tài liệu nào cho tính năng đó không? Tôi không thể tìm thấy bất kỳ. Tại thời điểm đó dường như hoàn toàn bỏ qua Android.mk/Application.mk của tôi.
plaisthos

Tôi chưa tìm thấy. Nó có thể đã lẻn vào tòa nhà nửa nướng. Tôi đang ở trên windows nên tôi chỉ có thể xác nhận rằng nó không thành công khi cố gắng gọi tập lệnh unix ndk-build. Không có lý do nào khác để gọi điều đó sau đó để tích hợp trình biên dịch gốc trong lớp. Bạn đang ở unix?
Anthony


nó thực sự mong đợi tìm thấy các tệp * .so dựng sẵn trong jniLibs.srcDirs
Alpine

Tôi không đồng ý dựa trên thực tế là nó gặp sự cố khi gọi ndk-build, điều này hoàn toàn không cần thiết nếu nó yêu cầu các thư viện được xây dựng. Tôi không thể xác nhận vì tôi không có thời gian để vm Linux ngay bây giờ.
Anthony

7

Một cách giải quyết tao nhã được hiển thị trong https://groups.google.com/d/msg/adt-dev/nQobKd2Gl_8/Z5yWAvCh4h4J .

Về cơ bản, bạn tạo một cái bình chứa "lib / armeabi / yourlib.so" và sau đó bao gồm cái bình trong bản dựng.


Vâng. Điều đó chỉ hoạt động tốt nếu bạn không thay đổi mã nguồn thường xuyên. Và bạn sẽ phải bao gồm các tệp jar nhị phân trong kho lưu trữ. Nếu không, bạn kết thúc với một kịch bản xây dựng tạo ra một cái bình.
plaisthos

1
Tôi đã sửa đổi ví dụ Hello-JNI của Android bằng một tập lệnh bash đơn giản bao bọc ndk-build, tạo .jars cho mỗi .sovà đặt chúng vào đường dẫn xây dựng của lớp để giảm bớt nỗi đau này. Kiểm tra nó ra.
dbro

4

Một câu trả lời tốt tự động hóa việc đóng gói các .sotệp được biên dịch sẵn được đưa ra trong một luồng (đóng) khác . Để làm việc đó, tôi đã phải thay đổi dòng:

from fileTree(dir: 'libs', include: '**/*.so')

vào:

from fileTree(dir: 'src/main/libs', include: '**/*.so') 

Nếu không có sự thay đổi này, các .sotệp không được tìm thấy và do đó, nhiệm vụ đóng gói chúng sẽ không bao giờ chạy được.


Cập nhật: xin lưu ý rằng trong Android Studios mới hơn (ít nhất là 1,5), mã gốc được kết hợp tốt hơn nhiều và không cần thực hiện nhiệm vụ riêng biệt này để đóng gói mã của bạn.
HYS

4

Câu trả lời từ @plaisthos đã phá vỡ trong phiên bản lớp mới nhất, nhưng vẫn có một cách để làm điều đó. Tạo mộtnative-libs thư mục trong thư mục gốc của thư mục dự án của bạn và sao chép tất cả các lib của chúng tôi vào thư mục này.

Thêm các dòng sau vào build.gradle của bạn. Xây dựng và hạnh phúc.

task copyNativeLibs(type: Copy) {
    from(new File(project(':<your project>').getProjectDir(), 'native-libs')) { include '**/*.so' }
    into new File(buildDir, 'native-libs')
}

tasks.withType(Compile) { compileTask -> compileTask.dependsOn copyNativeLibs }

clean.dependsOn 'cleanCopyNativeLibs'

3

Đây là mã tôi sử dụng để xây dựng bằng android-ndk từ gradle. Đối với điều này thêm đường dẫn thư mục ndk trong gradle.propertiestức là. thêm ndkdir=/home/user/android-ndk-r9dvà đặt tất cả các file JNI trong một thư mục nativetrong src/main/khi bạn có thể nhìn thấy từ mã đăng tải dưới đây. Nó sẽ tạo jar với libs gốc mà bạn có thể sử dụng bình thường như trongSystem.loadLibrary("libraryname");

dependencies {
    compile fileTree(dir: "$buildDir/native-libs", include: '*.jar')
}

task ndkBuild(type: Exec) {
    commandLine "$ndkdir/ndk-build", "--directory", "$projectDir/src/main/native", '-j', Runtime.runtime.availableProcessors(),
            "APP_PLATFORM=android-8",
            "APP_BUILD_SCRIPT=$projectDir/src/main/native/Android.mk",
            "NDK_OUT=$buildDir/native/obj",
            "NDK_APP_DST_DIR=$buildDir/native/libs/\$(TARGET_ARCH_ABI)"
}

task nativeLibsToJar(type: Jar, description: 'create a jar with native libs') {
    destinationDir file("$buildDir/native-libs")
    baseName 'native-libs'
    from fileTree(dir: "$buildDir/native/libs", include: '**/*.so')
    into 'lib/'
}

tasks.withType(JavaCompile) {
    compileTask -> compileTask.dependsOn nativeLibsToJar
}

nativeLibsToJar.dependsOn 'ndkBuild'

3

Tôi đã sử dụng đoạn mã sau để biên dịch các thư viện dropbox gốc, tôi đang sử dụng Android Studio v1.1.

task nativeLibsToJar(type: Zip) {
    destinationDir file("$buildDir/native-libs")
    baseName 'native-libs'
    extension 'jar'
    from fileTree(dir: 'src/main/libs', include: '**/*.so')
    into 'lib/'
}

tasks.withType(JavaCompile) {
    compileTask -> compileTask.dependsOn(nativeLibsToJar)
}


1

Để mở rộng những gì Naxos đã nói (Cảm ơn Naxos đã gửi cho tôi đúng hướng!), Tôi đã học được khá nhiều từ các ví dụ NDK được phát hành gần đây và đăng một câu trả lời trong một câu hỏi tương tự ở đây.

Cách định cấu hình NDK với plugin Android Gradle 0.7

Bài đăng này có đầy đủ chi tiết về việc liên kết các thư viện gốc dựng sẵn vào ứng dụng của bạn cho các kiến ​​trúc khác nhau cũng như thông tin về cách thêm hỗ trợ NDK trực tiếp vào tập lệnh build.gradle. Đối với hầu hết các phần, bạn không cần phải thực hiện công việc xung quanh zip và sao chép nữa.


1

Dưới đây là các bước mà tôi đã sử dụng để NDK hoạt động trong dự án Android Studio của mình. Tôi đã sử dụng hướng dẫn này để giúp tôi hiểu https://software.intel.com/en-us/ideo/USE-the-ndk-with-android-studio

Để sử dụng NDK, bạn phải thêm một dòng NDK vào local.properations. Vì vậy, dưới sdk.dir của bạn thêm

ndk.dir=C\:\\MyPathToMyNDK\ndk

Trong ứng dụng build.gradle của tôi, tôi có đoạn mã sau

        ndk {
            moduleName "myLib"
            ldLibs "log"
            stl "gnustl_shared"
            cFlags "-std=c++11 -frtti -fexceptions -pthread"
        }

moduleName là tên bạn muốn cung cấp mã gốc của mình. Tôi tin rằng đây là những gì thư viện chia sẻ sẽ được gọi. ldLibs cho phép tôi đăng nhập vào LogCat, stl là stl mà bạn muốn nhập. Có rất nhiều tùy chọn, giống như NDK của Eclipse. ( http://www.kandroid.org/ndk/docs/CPLUSPLUS-SUPPORT.html )

cFlags vẫn là một lượng ma thuật đen nhất định đối với tôi. Tôi đã không tìm thấy một nguồn tốt cho tất cả các tùy chọn và những gì họ cung cấp cho tôi. Tìm kiếm xung quanh StackOverflow cho bất cứ điều gì bạn cần, đó là nơi tôi tìm thấy nó. Tôi biết rằng c ++ 11 cho phép tôi sử dụng tiêu chuẩn c ++ 11 mới.

Dưới đây là một ví dụ về cách tôi đăng nhập vào LogCat từ mã gốc

__android_log_print(ANDROID_LOG_DEBUG, "TestApp", "Adding - String %d has a field name of %s and a value of %s", i, lKeyUTF8.c_str(), lValueUTF8.c_str());

1

cấu hình dự án trong studio android từ nhật thực: bạn phải nhập dự án nhật thực ndk vào studio android mà không xuất sang gradle và nó hoạt động, bạn cũng cần thêm đường dẫn của ndk trong local.properations , nếu hiển thị lỗi thì thêm

sourceSets.main {
        jniLibs.srcDir 'src/main/libs' 
        jni.srcDirs = [] //disable automatic ndk-build callenter code here
    }

trong tệp build.gradle, sau đó tạo thư mục jni và tệp bằng terminal và chạy nó sẽ hoạt động


1
Xem thấy câu trả lời của riêng tôi. Đó là cách giải quyết tôi hiện đang sử dụng nhưng nó không thực sự là một giải pháp.
plaisthos

1

Bây giờ Android Studio đang ở trong kênh ổn định, việc chạy các mẫu android-ndk khá đơn giản . Các mẫu này sử dụng plugin thử nghiệm ndk và mới hơn các mẫu được liên kết từ tài liệu trực tuyến NDK của Android. Khi bạn biết chúng hoạt động, bạn có thể nghiên cứu các tệp build.gradle, local.properies và gradle-wrapper.properIES và sửa đổi dự án của bạn cho phù hợp. Sau đây là các bước để làm cho họ làm việc.

  1. Chuyển đến cài đặt, Giao diện & Hành vi, Cài đặt hệ thống, SDK Android, chọn tab Công cụ SDK và kiểm tra phiên bản Android NDK 1.0.0 ở cuối danh sách. Điều này sẽ tải về NDK.

  2. Chỉ vào vị trí của NDK mới tải xuống. Lưu ý rằng nó sẽ được đặt trong thư mục sdk / ndk-bundle. Thực hiện việc này bằng cách chọn Tệp, Cấu trúc dự án, Vị trí SDK (bên trái) và cung cấp đường dẫn bên dưới vị trí NDK của Android. Điều này sẽ thêm một mục ndk vào local.properies tương tự như sau:

    Mac / Linux: ndk.dir = / Android / sdk / ndk-bundle
    Windows: ndk.dir = C: \ Android \ sdk \ ndk-bundle

Tôi đã xây dựng và triển khai thành công tất cả các dự án trong kho theo cách này, ngoại trừ gles3gni, codec gốc và trình xây dựng. Tôi đang sử dụng như sau:

Android Studio 1.3 xây dựng các mẫu AI-141.2117773
android-ndk được xuất bản vào ngày 28 tháng 7 năm 2015 (liên kết ở trên)
Công cụ SDK 24.3.3
NDK r10e được trích xuất sang C: \ Android \ sdk \ ndk-bundle
Gradle 2.5
Gradle plugin 0.2.0
Windows 8.1 64 bit


1

NDK Xây dựng và phân loại (cơ bản)

Nói chung, việc xây dựng với NDK cũng đơn giản như chỉ định chính xác đường dẫn ndkBuild đến Android.mk hoặc đường dẫn cmake tới CMakeLists.txt. Tôi khuyên dùng CMake so với Android.mk cũ hơn vì hỗ trợ C / C ++ của Android Studio dựa trên CLion và nó sử dụng CMake làm định dạng dự án. Điều này theo kinh nghiệm của tôi có xu hướng làm cho IDE phản ứng nhanh hơn trong các dự án lớn hơn. Mọi thứ được biên dịch trong dự án của bạn sẽ được xây dựng và sao chép tự động vào APK.

apply plugin: 'com.android.library'

android {
    compileSdkVersion 19
    buildToolsVersion "25.0.2"

    defaultConfig {
        minSdkVersion 19
        targetSdkVersion 19

        ndk {
            abiFilters 'armeabi', 'armeabi-v7a', 'x86'
            // 64-bit support requires an Android API level higher than 19; Namely 21 and higher
            //abiFilters 'armeabi', 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
        }

        externalNativeBuild {
            cmake {
                arguments '-DANDROID_TOOLCHAIN=clang',
                        '-DANDROID_PLATFORM=android-19',
                        '-DANDROID_STL=gnustl_static',
                        '-DANDROID_ARM_NEON=TRUE'

            }
        }
    }

    externalNativeBuild {
        cmake {
            path 'src/main/jni/CMakeLists.txt'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
}

Thêm thư viện dựng sẵn vào dự án (nâng cao)

Các thư viện tĩnh (.a) trong bản dựng NDK của bạn sẽ tự động được bao gồm, nhưng các thư viện động dựng sẵn (.so) sẽ cần được đặt vào jniLibs. Điều này có thể được cấu hình bằng cách sử dụng sourceSets, nhưng bạn nên áp dụng tiêu chuẩn. Bạn KHÔNG CẦN bất kỳ lệnh bổ sung nào trongbuild.gradle nào khi bao gồm các thư viện dựng sẵn.

Bố cục của jniLibs

Bạn có thể tìm thêm thông tin về cấu trúc trong Hướng dẫn sử dụng Plugin Android Gradle .

|--app:
|--|--build.gradle
|--|--src:
|--|--|--main
|--|--|--|--java
|--|--|--|--jni
|--|--|--|--|--CMakeLists.txt
|--|--|--|--jniLibs
|--|--|--|--|--armeabi
|--|--|--|--|--|--.so Files
|--|--|--|--|--armeabi-v7a
|--|--|--|--|--|--.so Files
|--|--|--|--|--x86
|--|--|--|--|--|--.so Files

Sau đó, bạn có thể xác thực APK kết quả chứa các tệp .so của bạn, thường là dưới build/outputs/apk/, bằng cách sử dụngunzip -l myApp.apk để liệt kê nội dung.

Xây dựng thư viện dùng chung

Nếu bạn đang xây dựng một thư viện chia sẻ trong NDK, bạn không cần phải làm gì thêm. Nó sẽ được gói chính xác trong APK.


0

Chỉ cần thêm dòng này vào ứng dụng build.gradle

dependencies {
    ...
    compile fileTree(dir: "$buildDir/native-libs", include: 'native-libs.jar')
}

task nativeLibsToJar(type: Zip, description: 'create a jar archive of the native libs') {
    destinationDir file("$buildDir/native-libs")
    baseName 'native-libs'
    extension 'jar'
    from fileTree(dir: 'libs', include: '**/*.so')
    into 'lib/armeabi/'
}

tasks.withType(JavaCompile) {
    compileTask -> compileTask.dependsOn(nativeLibsToJar)
}

Tôi nghĩ rằng cách tiếp cận jniLibs.srcDirs sạch hơn phương pháp này vì bạn có thể sử dụng abiFilter / hương vị nhưng cách tiếp cận của bạn cũng sẽ hiệu quả.
plaisthos

0

Bây giờ tôi có thể tải thành công như vậy!

1. thêm tệp .so vào đường dẫn này

Project:

| --src | - | - chính | - | - | --java | - | - | --jniLibs | - | - | - | --armeabi | - | - | - | - | -. Vì vậy, tập tin

2. thêm mã này để gradle.build

android {
splits {
    abi {
        enable true
        reset()
        include 'x86', 'x86_64', 'arm64-v8a', 'armeabi-v7a', 'armeabi'
        universalApk false
    }
}

}

3.System.loadLibrary("yousoname");

  1. goodluck cho bạn, nó ổn với lớp 1.2.3

0
  1. Nếu dự án của bạn xuất từ ​​nhật thực, hãy thêm các mã bên dưới vào tập tin gradle

    android {
       sourceSets{
            main{
               jniLibs.srcDir['libs']  
          }  
        }
    }

2.Nếu bạn tạo một dự án trong studio Android:

tạo một thư mục có tên jniLibs trong src / main / và đặt các tệp * .so của bạn vào thư mục jniLibs.

Và sao chép mã như dưới đây trong tập tin lớp của bạn

android {
    sourceSets{  
       main{  
         jniLibs.srcDir['jniLibs']  
      }  
    }
}

0

Mặc dù tôi tin rằng SJoshi (anh chàng tiên tri) có câu trả lời đầy đủ nhất, dự án SWIG là một trường hợp đặc biệt, thú vị và hữu ích, nhưng không được khái quát cho phần lớn các dự án đã làm tốt với các dự án dựa trên kiến ​​SDK tiêu chuẩn + NDK. Hiện tại tất cả chúng ta đều muốn sử dụng studio Android, hoặc muốn có một công cụ xây dựng thân thiện với CI hơn cho thiết bị di động, theo lý thuyết mà dần dần cung cấp.

Tôi đã đăng cách tiếp cận của mình, mượn từ đâu đó (tôi tìm thấy điều này trên SO, nhưng đã đăng một ý chính cho việc xây dựng ứng dụng.gradle: https://gist.github.com/truedat101/c45ff2b69e91d5c8e9c7962d4b96e841 ). Tóm lại, tôi khuyên bạn nên như sau:

  • Đừng nâng cấp dự án của bạn lên bản dựng lớp mới nhất
  • Sử dụng com.android.tools.build:gradle:1.5.0 trong gốc Project của bạn
  • Sử dụng com.android.application trong dự án ứng dụng của bạn
  • Đảm bảo gradle.properies có: android.useDeprecatedNdk = true (trong trường hợp nó phàn nàn)
  • Sử dụng phương pháp trên để đảm bảo rằng hàng giờ và hàng giờ nỗ lực của bạn để tạo các tệp Android.mk sẽ không bị loại bỏ. Bạn kiểm soát mục tiêu nào để xây dựng. Và những hướng dẫn này tốt cho người dùng Windows, về mặt lý thuyết có thể xây dựng trên windows mà không gặp vấn đề gì đặc biệt.

Theo tôi, Gradle cho Android là một mớ hỗn độn, vì tôi thích các khái niệm maven mượn và cấu trúc các thư mục cho một dự án. Tính năng NDK này đã "đến sớm" trong gần 3 năm qua.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.