2014-04-08 13 views
13

मैं स्वीकार करने वाला पहला व्यक्ति हूं कि मैं ग्रैडल और नई एंड्रॉइड बिल्ड सिस्टम के साथ बहुत ही विशेषज्ञ नहीं हूं, लेकिन दुर्भाग्यवश, मुझे समस्या के कारण (एंटी से) आगे बढ़ना पड़ा 21479 (https://code.google.com/p/android/issues/detail?id=21479) और टिप्पणी "यह तय नहीं किया जाएगा। हम ग्रैडल-आधारित बिल्ड सिस्टम को खत्म करने पर ध्यान केंद्रित कर रहे हैं जो चींटी को प्रतिस्थापित करेगा।" दुर्भाग्य से, मैं मिलेनियम मीडिया विज्ञापन लाइब्रेरी को जोड़ने के बाद फिर से सामान बनाने के लिए नहीं मिल सका। यह एंड्रॉइड ओपनसीवी लाइब्रेरी, चिलकट की एन्क्रिप्शन लाइब्रेरी और समर्थन वी 4 लाइब्रेरी के अलावा था, लेकिन एमएमडिया पुस्तकालय वह था जो इसे तोड़ देता था।ग्रैडल एंड्रॉइड बिल्ड सिस्टम एनडीके मुद्दे

तो, मैंने सोचा, किसी भी नए ग्रैडल आधारित निर्माण प्रणाली में माइग्रेट करने का कोई कारण नहीं है। दुर्भाग्यवश, एक टूटी हुई चींटी निर्माण प्रणाली को छोड़ने के बावजूद, नई प्रणाली अभी तक समाप्त नहीं हुई है; विशेष रूप से ndk समर्थन।

जिस एप्लिकेशन पर मैं काम कर रहा हूं, उसके लिए ओपनसीवी का उपयोग कुछ छवि प्रसंस्करण के लिए करता है और कुछ ऑपरेशन बहुत धीरे-धीरे चलते हैं जब तक कि वे देशी (संकलन की बहुत सारी गति और तुलना जेएनआई में धीमी होती हैं) सीमा)। इसलिए, वीएम और देशी कोड के बीच डेटा को वापस और आगे बढ़ाने की कोशिश करने के बजाय, मैं इन सभी चीजों को मूल तरफ छोड़ देता हूं और परिणामों को प्राप्त करने के लिए केवल वीएम से एक कॉल करता हूं।

पहली समस्या संकलन करने के लिए एनएनडी सामान प्राप्त कर रही थी। मैं NDK बंद में सेटिंग्स मैं NDK-निर्माण आदेश का उपयोग का सहारा लेना पड़ा तो काम करते हैं और एक कार्य के रूप में इस पर अमल करने नहीं मिल सका:

task ndkBuild(type: Exec) { 
    String MainDirectory = System.getProperty("user.dir") + '/app/src/main' 
    println "Main app directory for NDK build " + MainDirectory 
    if (Os.isFamily(Os.FAMILY_WINDOWS)) { 
     commandLine 'gradle-ndk-build.cmd', MainDirectory, '-j' 
    } 
    else { 
     commandLine 'gradle-ndk-build', MainDirectory, '-j' 
    } 
} 

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

यह पूरी तरह से काम करता है; यह एनएनडीके कोड संकलित करता है और त्रुटि के बिना .so लाइब्रेरी उत्पन्न करता है। दुर्भाग्यवश, यह अंतिम पैकेज में परिणामस्वरूप .so फ़ाइल नहीं डालेगा। यह सभी अन्य देशी पुस्तकालयों को ठीक से रखता है, लेकिन यह नहीं - हालांकि कोई विचार नहीं।

मैं जैसे इस समस्या के लिए कथित तौर पर फिक्स के बहुत सारे मिल गया है:

tasks.withType(com.android.build.gradle.tasks.PackageApplication) { pkgTask -> 
    pkgTask.jniFolders = new HashSet<File>() 
    pkgTask.jniFolders.add(new File(buildDir, 'native-libs')) 
} 

लेकिन यह सिर्फ सब पर में कोई देशी पुस्तकालयों के साथ एक apk फ़ाइल में परिणाम जोड़ने। मैंने देखा है कि अन्य लोगों में एक ही समस्या है (जैसे https://groups.google.com/forum/#!msg/adt-dev/QbDHM41QT2E/J4jHCC_RuIEJ) लेकिन मैंने सभी प्रस्तावित समाधानों का प्रयास किया है और उनमें से कोई भी मेरे लिए काम नहीं करता है।

जैसा कि मैं अक्सर देशी कोड नहीं बदलता हूं, मैंने ऐप/src/main/libs से/app/src/main/से जेनरेट की गई मूल लाइब्रेरी (libndklib.so) की प्रतिलिपि बनाने के लिए एक हैक किया है। संकलित होने के बाद जेनी; तो यह एपीके पैकेज में समाप्त होता है। जाहिर है, यह थोड़ा बुरा है, अगर कोई इस कोड को ले लेता है, तो वे सोचेंगे कि मूल कोड में उनके परिवर्तन कभी भी ऐप में क्यों नहीं दिखाई देते हैं।

तो, मेरे प्रश्न हैं: क्या कुछ ऐसा है जो मैं स्प्रिंग स्क्रिप्ट के भीतर चला सकता हूं जो कि ndk कमांड (gradle-ndk-build) चलाने के बाद निष्पादित होगा जो जेनरेट की गई फाइलों को ऐप से कॉपी करेगा /src/main/libs/armeabi/libndklib.so से /app/src/main/jni/armeabi/libndklib.so (प्रत्येक आर्किटेक्चर के लिए - आर्मेबी, आर्मेबी-वी 7, x86, mips) ताकि यह समाप्त हो जाए एपीके पैकेज? Application.mk

APP_STL := gnustl_static 
APP_CPPFLAGS := -frtti -fexceptions 
APP_ABI := all 
APP_PLATFORM := android-8 

एंड्रॉयड:

या

वहाँ Gradle NDK बंद संभाल बनाने के लिए किसी भी तरह से NDK निम्न फ़ाइलें ठीक से करते हैं।mk

LOCAL_PATH := $(call my-dir) 
include $(CLEAR_VARS) 
# OpenCV 
OPENCV_CAMERA_MODULES:=on 
OPENCV_INSTALL_MODULES:=on 
OPENCV_LIB_TYPE:=SHARED 
include /home/myname/tools/OpenCV-2.4.8-android-sdk/sdk/native/jni/OpenCV.mk 
LOCAL_MODULE := ndklib 
LOCAL_SRC_FILES := ndklib.cpp motion.cpp 
LOCAL_LDLIBS += -lm -llog 
include $(BUILD_SHARED_LIBRARY) 
# Add prebuilt chilkat library 
include $(CLEAR_VARS) 
LOCAL_MODULE := lib-chilkat 
LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/libchilkatemail.so 
include $(PREBUILT_SHARED_LIBRARY) 

मैं प्लग-इन के लिए Gradle स्रोत को देखा है, लेकिन मैं इन समर्थित निर्देशों के कई नहीं देख सकता था।

या

मैं सिर्फ उत्पन्न apk में (सही वास्तुकला के लिए) हैक किसी प्रकार का है कि Gradle स्क्रिप्ट है कि बस libndklib.so की उचित प्रतिलिपि बलों के अंत में चलाता है जोड़ सकते हैं? जब तक मैं एंड्रॉइड प्लग-इन के लिए ग्रेडल बिल्ड के लिए एनएनडी सामान समाप्त नहीं कर लेता तब तक मैं बाद के साथ रह सकता हूं।

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

संपादित करें - Ph0b के उत्तर के बाद यह अंतिम build.gradle फ़ाइल में प्रस्तावित मोड के साथ है। .apk के पूरी तरह से build.gradle (एप्लिकेशन निर्देशिका में)

buildscript { 
    repositories { 
     mavenCentral() 
    } 
    dependencies { 
     classpath 'com.android.tools.build:gradle:0.9.+' 
    } 
} 

apply plugin: 'android' 

import org.apache.tools.ant.taskdefs.condition.Os 

android { 
    compileSdkVersion 19 
    buildToolsVersion "19.0.3" 

    signingConfigs { 
     debug { 
      storeFile file("dbgkeystore") 
      storePassword "nopass" 
      keyAlias "mainkeyname" 
      keyPassword "nopass" 
     } 

     release { 
      storeFile file("keystore") 
      storePassword "xxxxxxxx" 
      keyAlias "mainkeyname" 
      keyPassword "yyyyyyyy" 
     } 
    } 

    // Autoincrement the version properties file 
    // ****************************************** 
    def versionPropsFile = file('version.properties') 
    def code = 1 

    def majorversion = 1 
    def minorversion = 1 

    defaultConfig { 
     versionCode code 
     versionName "${majorversion}.${minorversion}.${code}" 
     minSdkVersion 10 
     targetSdkVersion 19 
    } 

    buildTypes { 
     release { 
      runProguard true 
      proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' 
      signingConfig signingConfigs.release 
     } 

     debug { 
      runProguard false 
      proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' 
      packageNameSuffix ".debug" 
      versionNameSuffix "-debug" 
      signingConfig signingConfigs.debug 
     } 
    } 

    sourceSets { 
     main { 
      jni.srcDirs = [] 
      // jniLibs.srcDir 'src/main/jni' // - Doesn't work, leaves out the .so files generated by ndk-build 
      jniLibs.srcDir 'src/main/libs' 
     } 
    } 

    flavorDimensions "version", "abi" 

    productFlavors { 
     pro { 
      flavorDimension "version" 
      packageName "org.somedomainname.myAppPro1" 
     } 

     lite { 
      flavorDimension "version" 
      packageName "org.somedomainname.myAppLite1" 
     } 

     arm { 
      flavorDimension "abi" 

      ndk { 
       abiFilter "armeabi" 
      } 

      if (versionPropsFile.canRead()){ 
       def Properties versionProps = new Properties() 

       versionProps.load(new FileInputStream(versionPropsFile)) 

       code = versionProps['VERSION_CODE'].toInteger() + 1 

       versionProps['VERSION_CODE']=code.toString() 
       versionProps.store(versionPropsFile.newWriter(), null) 

       versionCode code 
       versionName "${majorversion}.${minorversion}.${code}" 
      } 
      else { 
       throw new GradleException("Could not read version.properties!") 
      } 

     } 

     armv7 { 
      flavorDimension "abi" 

      ndk { 
       abiFilter "armeabi-v7a" 
      } 

      if (versionPropsFile.canRead()){ 
       def Properties versionProps = new Properties() 

       versionProps.load(new FileInputStream(versionPropsFile)) 

       code = versionProps['VERSION_CODE'].toInteger() + 1 

       versionProps['VERSION_CODE']=code.toString() 
       versionProps.store(versionPropsFile.newWriter(), null) 

       versionCode code 
       versionName "${majorversion}.${minorversion}.${code}" 
      } 
      else { 
       throw new GradleException("Could not read version.properties!") 
      } 
     } 

     x86 { 
      flavorDimension "abi" 

      ndk { 
       abiFilter "x86" 
      } 

      if (versionPropsFile.canRead()){ 
       def Properties versionProps = new Properties() 

       versionProps.load(new FileInputStream(versionPropsFile)) 

       code = versionProps['VERSION_CODE'].toInteger() + 1 

       versionProps['VERSION_CODE']=code.toString() 
       versionProps.store(versionPropsFile.newWriter(), null) 

       versionCode code 
       versionName "${majorversion}.${minorversion}.${code}" 
      } 
      else { 
       throw new GradleException("Could not read version.properties!") 
      } 
     } 
    } 

    lintOptions { 
     checkReleaseBuilds false 
     // Or, if you prefer, you can continue to check for errors in release builds, 
     // but continue the build even when errors are found: 
     abortOnError false 
    } 

repositories { 
    mavenCentral() 
    flatDir { 
     dirs '/home/myname/maindrive/work/dynamic/android/UtilLib/aarlib' 
    } 
} 

dependencies { 
    compile 'com.android.support:appcompat-v7:+' 
    compile fileTree(dir: 'libs', include: ['*.jar']) 

    // Note: org.somedomainname.UtilLib on the depency below is ignored when usng flatdir 
    compile 'org.somedomainname.UtilLib:library:[email protected]' 
} 

task ndkBuild(type: Exec) { 
    String MainDirectory = System.getProperty("user.dir") + '/app/src/main' 
    println '************************************************************************' 
    println "Main app directory for NDK build " + MainDirectory 
    println '************************************************************************' 

    if (Os.isFamily(Os.FAMILY_WINDOWS)) { 
     commandLine 'gradle-ndk-build.cmd', MainDirectory, '-j' 
    } 
    else { 
     commandLine 'gradle-ndk-build', MainDirectory, '-j' 
    } 
} 

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


android.applicationVariants.all { variant -> 
    variant.assemble.doLast { 
      rename_and_moveout_apk(variant) 
    } 
} 

// allprojects { 
//  tasks.withType(Compile) { 
//   options.compilerArgs << "-Xlint:deprecation" 
//  } 
// } 

def rename_and_moveout_apk(targetVariant) { 
    // replace output apk name to <product>-<version>-<buildtype>-<githash>.apk 
    def versionSuffix = targetVariant.buildType.versionNameSuffix ? targetVariant.buildType.versionNameSuffix : "" 
    def versionName = targetVariant.mergedFlavor.versionName + versionSuffix; 

    if (targetVariant.zipAlign) { 
     def apkFinal = targetVariant.outputFile; 
     def apkFinalNewName = "myApp-" + apkFinal.name.replace(targetVariant.buildType.name, versionName); 
     copy { 
      from "$apkFinal" 
      into "$rootProject.projectDir/apk_release" 
      rename ("$apkFinal.name", "$apkFinalNewName") 
      println "*************** Renaming zipalign apk file from: ${apkFinal.name} to ${apkFinalNewName}" 
     } 
    } 

} 

Gradle-NDK-निर्माण (पैरामीटर डीबगिंग के लिए इस्तेमाल किया NDK-निर्माण के संशोधित संस्करण) बनाता है

#!/bin/bash 
export NDK_PROJECT_PATH=$1 
export NDK_PROJECT_DIRECTORY=$1 
bash -c "ndk-build" 

निर्देशिका संरचना

------ apk_release 
------ app 
-- -- ---- src 
--  ------ lite 
--  --  -- ---- java 
--  --   -- ---- org 
--  --    -- ---- somedomainname 
--  --     -- ---- myApp 
--  ------ main 
--  --  ------ assets 
--  --  ------ java 
--  --  --  -- ---- org 
--  --  --   ------ chilkatsoft 
--  --  --   -- ---- somedomainname 
--  --  --    -- ---- myApp 
--  --  ------ jni 
--  --  --  ------ armeabi 
--  --  --  ------ armeabi-v7a 
--  --  --  ------ mips 
--  --  --  -- ---- x86 
--  --  ------ libs 
--  --  --  ------ armeabi 
--  --  --  ------ armeabi-v7a 
--  --  --  ------ mips 
--  --  --  -- ---- x86 
--  --  ------ obj 
--  --  --  -- ---- local 
--  --  --   ------ armeabi 
--  --  --   --  -- ---- objs 
--  --  --   --   -- ---- ndklib 
--  --  --   ------ armeabi-v7a 
--  --  --   --  -- ---- objs 
--  --  --   --   -- ---- ndklib 
--  --  --   ------ mips 
--  --  --   --  -- ---- objs 
--  --  --   --   -- ---- ndklib 
--  --  --   -- ---- x86 
--  --  --    -- ---- objs 
--  --  --     -- ---- ndklib 
--  --  -- ---- res 
--  --   ------ drawable 
--  --   ------ drawable-hdpi 
--  --   ------ drawable-ldpi 
--  --   ------ drawable-mdpi 
--  --   ------ drawable-xhdpi 
--  --   ------ drawable-xxhdpi 
--  --   ------ layout 
--  --   ------ raw 
--  --   ------ values 
--  --   -- ---- xml 
--  -- ---- pro 
--   -- ---- java 
--    -- ---- somedomainname 
--     -- ---- myApp 
+0

कमांडलाइन 'Gradle-NDK-निर्माण':

आप इसे यह आपके build.gradle अंदर फ़ाइल सेट करके अपने नियमित libs निर्देशिका का उपयोग करने के लिए इस व्यवहार को बदल सकते हैं ए। इसके लिए कामकाजी फ़िर ---/ऐप बी है। यह निम्न त्रुटि का कारण बनता है: निष्पादन कार्य के लिए विफल रहा ': app: ndkBuild'। ', MainDirectory': ' कमांडलाइन समाधान' ./gradle-ndk-build -j ' स्क्रिप्ट कार्यक्रम में ही –

+0

"मैं सहारा लेना पड़ा नहीं है > एक समस्या प्रक्रिया' कमांड 'gradle_ndk_build' शुरू करने आई ndk-build कमांड का उपयोग करने और इसे कार्य के रूप में निष्पादित करने के लिए: ... यह पूरी तरह से काम करता है ... " कैसे? क्यूं कर? मुझे यह त्रुटि मिल रही है: "प्रक्रिया शुरू करने में एक समस्या हुई 'कमांड' ndk-build ''"। मैं यह समझ नहीं सकता कि सही ढंग से निष्पादित करने के लिए उस पंक्ति को कैसे प्राप्त किया जाए। –

उत्तर

15

ग्रेडल jniLibs/ABI/ के अंदर स्वचालित रूप से .so फ़ाइलों को देखेगा। , MainDirectory, '-j'

android { 
    sourceSets.main { 
     jniLibs.srcDir 'src/main/libs' 
    } 
} 
+1

धन्यवाद - पूरी तरह से काम किया। मैं अपना मूल प्रश्न संपादित करूंगा और अंतिम बिल्ड.ग्रेडल जोड़ूंगा यदि यह किसी और के लिए उपयोगी है। – Johnny

+0

भगवान आपको आशीर्वाद देते हैं! :-) एसओ पुराने ग्रैडल संस्करण के लिए विभिन्न समाधानों से भरा है ... – JerabekJakub

+0

मुझे "jniLibs हल नहीं किया जा सकता" त्रुटि ... से शुरू करने के लिए मिलता है। – Josh

संबंधित मुद्दे