【问题标题】:How to support osgi in android gradle plugin environment?android gradle插件环境如何支持osgi?
【发布时间】:2015-10-08 10:19:32
【问题描述】:

我想将 apk 用作 osgi 包,然后将其加载到主机应用程序中。

现在,一切正常。但在将 osgi 包推送到手机之前,我必须手动执行这些操作:

  1. 用 WinRAR 打开 osgi bundle apk 文件。
  2. 将构建的类(在 extension-a\build\intermediates\classes\debug\com 中)拖到包文件的根目录。
  3. 将修改后的 MANIFEST.MF(包括 OSGI 配置信息)拖到包文件的 META-INFO/MANIFEST.MF 中。
  4. 最后签署捆绑包 apk。

我想知道如何编写一些 gradle 脚本来自动完成这些事情?

我使用 gradle 2.2.1 和 'com.android.tools.build:gradle:1.2.3'。

ps: 我知道有一个 gradle 插件“osgi”可以为 osgi bunlde 生成 MANIFEST.MF,但它只适用于“java”gradle 插件。 我不能将它与“android”gradle 插件一起使用。

我试过这样:

android.applicationVariants.all { variant ->
    variant.outputs[0].packageApplication.doLast {
        String zipFileName = variant.outputs[0].outputFile.name
        String inputFile = 'MANIFEST.MF'  

        def zipIn = variant.outputs[0].outputFile
        def zip = new ZipFile(zipIn.getAbsolutePath())
        def zipTemp = new File(zipFileName + "_temp") 
        zipTemp.deleteOnExit()
        def zos = new ZipOutputStream(new FileOutputStream(zipTemp))
        def toModify = 'META-INFO/MANIFEST.MF'

        for(e in zip.entries()) {
            if(!e.name.equalsIgnoreCase(toModify)) {
                zos.putNextEntry(e)
                zos << zip.getInputStream(e).bytes
            } else {
                zos.putNextEntry(new ZipEntry(toModify))
                zos << new File(inputFile).bytes
            }
            zos.closeEntry()
        }

        zos.close()
        zipIn.delete()
        zipTemp.renameTo(zipIn)
    }
}

但没有成功:

  1. 如果使用“gradle clean build”,则会报告“out-file.apk”未找到。
  2. 如果out-file.apk存在,报异常:

    java.util.zip.ZipException:无效的条目压缩大小(预期为 400,但得到了 401 个字节) 在 java.util.zip.ZipOutputStream.closeEntry(Unknown Source)

任何帮助将不胜感激!

【问题讨论】:

    标签: android groovy gradle osgi


    【解决方案1】:

    我找到了解决它的方法。

    buildscript {
        repositories {
            jcenter()
        }
        dependencies {
            classpath 'com.android.tools.build:gradle:1.2.3'
    
            // NOTE: Do not place your application dependencies here; they belong
            // in the individual module build.gradle files
        }
    }
    
    allprojects {
        repositories {
            jcenter()
        }
    }
    
    apply plugin: 'com.android.application'
    
    import java.util.zip.*
    
    android {
        compileSdkVersion 21
        buildToolsVersion "21.1.2"
    
        defaultConfig {
            minSdkVersion 19
            targetSdkVersion 21
            sourceCompatibility = '1.7'
            targetCompatibility = '1.7'
            versionCode 1
            versionName "1.0"
        }
    
        signingConfigs {
            release {
                storeFile file("debug.keystore") // should move debug.keystore to build.gradle directory
                keyAlias "androiddebugkey"
                storePassword "android"
                keyPassword "android"
            }
        }
    
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
                signingConfig signingConfigs.release            
            }
    
            android.applicationVariants.all { variant ->
                variant.outputs[0].packageApplication.doLast {
                    println "Add osgi files after packageApplication ..."
    
                    def manifestFile = 'MANIFEST.MF'  
                    def toModify = 'META-INF/MANIFEST.MF'
                    def classesPath =  "build/intermediates/classes/"+variant.buildType.name+"/com"
                    def zipFile = variant.outputs[0].outputFile.getAbsolutePath()
    
                    //if (variant.buildType.name.equals("debug"))
                    // After config release signingConfig, should change apk name, so remove this if statement
                    zipFile = zipFile.replace(".apk", "-unaligned.apk")
    
                    //release should change 3 positions: (If without release signingConfig)
                    //  1. no need replace name with -unaligned.apk; 
                    //  2. copy intermediates/classes/release/com; 
                    //  3. should add META-INF/MANIFEST.MF, not replace.
                    updateZipEntry(zipFile, toModify, manifestFile, classesPath)
    
                    signApkFile(zipFile)
                    //println project.buildDir
                    //println System.getenv('JAVA_HOME')
                }
            }
        }
    }
    
    dependencies {
        provided fileTree(dir: 'src/main/libs', include: ['*.jar'])
        provided 'org.apache.felix:org.apache.felix.framework:5.0.0'
    }
    
    void updateZipEntry(String zipFile, String zipEntry, String newFile, String classesPath){
        def zin = new ZipFile(zipFile)
        def tmp = File.createTempFile("temp_${System.nanoTime()}", '.zip')
        tmp.withOutputStream { os ->
            def hasReplaced = false
            def zos = new ZipOutputStream(os)
            zin.entries().each { entry ->
                def isReplaced = entry.name == zipEntry
                entry.setCompressedSize(-1);
                zos.putNextEntry(isReplaced ? new ZipEntry(zipEntry) : entry)
                zos << (isReplaced ? new File(newFile).bytes : zin.getInputStream(entry).bytes )
                zos.closeEntry()
                if (isReplaced) hasReplaced = true
            }
            if (!hasReplaced) { // Add META-INF/MANIFEST.MF for release build.
                zos.putNextEntry(new ZipEntry(zipEntry))
                zos << new File(newFile).bytes
                zos.closeEntry()
            }
            addDirToArchive(zos, new File(classesPath), "com")
            zos.close()
        }
        zin.close()
        assert new File(zipFile).delete()
        tmp.renameTo(zipFile)
    }
    
    void addDirToArchive(ZipOutputStream zos, File srcDir, String dstDir) {
        //System.out.println("Adding directory: " + srcDir.getName() + " -> " + dstDir);
    
        File[] files = srcDir.listFiles();
        for (int i = 0; i < files.length; i++) {
            // if the file is directory, use recursion
            if (files[i].isDirectory()) {
                addDirToArchive(zos, files[i], dstDir + "/" + files[i].getName());
                continue;
            }
            try {
                //System.out.println("Adding file: " + files[i].getName());
    
                // create byte buffer
                byte[] buffer = new byte[1024];
                FileInputStream fis = new FileInputStream(files[i]);
                zos.putNextEntry(new ZipEntry(dstDir + "/" + files[i].getName()));
                int length;
                while ((length = fis.read(buffer)) > 0) {
                    zos.write(buffer, 0, length);
                }
                zos.closeEntry();
    
                // close the InputStream
                fis.close();
            } catch (IOException ioe) {
                System.out.println("IOException :" + ioe);
            }
        }
    }
    
    void signApkFile(String zipFile) {
        def signApkCmdLine = "java -Xmx512m -jar signapk.jar -w testkey.x509.pem testkey.pk8 "+zipFile+" "+zipFile
        def sout = new StringBuffer(), serr = new StringBuffer()
        def proc = signApkCmdLine.execute()
        proc.consumeProcessOutput(sout, serr)
        proc.waitForOrKill(1000)
        println "sign apk : out> $sout err> $serr"
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-10-24
      • 2012-08-30
      • 2014-08-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-18
      • 2020-06-11
      相关资源
      最近更新 更多