在Android Studio中公开隐藏的API android L(SDK 21)

时间:2015-02-02 21:58:17

标签: android android-studio

我已经成功从android模拟器中提取了类文件,并将它们替换为我的android.jar文件,该文件驻留在我的\ platforms \ android-21 \ android.jar中,我仍然无法访问隐藏的方法。我以前使用过android 19,但要保持我的版本更新。我知道我可以使用反射,但在Android Studio中原生支持它会更容易。

使用JD-GUI我可以确认类和方法在android.jar文件中,但Android Studio“无法解析符号”。我在这里很重要。谢谢大家。

编辑:我确实有repo设置,所以如果从源代码编译android.jar文件是可能的,我不介意这样做。

5 个答案:

答案 0 :(得分:1)

档案>使高速缓存无效并重新启动>无效并重新启动

我知道一些奇怪的事情。我知道罐子里有方法,我知道它与Studio有关。在这里它缓存方法:)

我在第一行发布的内容修复了它!很高兴!希望别人受益!

答案 1 :(得分:1)

  1. 在../app下创建文件夹,命名为' systemlibs'
  2. 将您的图书馆复制到' systemlibs'
  3. 在app / build.gradle依赖项中添加提供的文件(' systemlibs / android.jar')
  4. 同步gradle并构建
  5. 
    
        dependencies {
            provided files('systemlibs/android.jar')
            compile fileTree(dir: 'libs', include: ['*.jar'])
            testCompile 'junit:junit:4.12'
            compile 'com.android.support:appcompat-v7:23.4.0'
            compile 'com.android.support:design:23.4.0'
        }
    
    

答案 2 :(得分:0)

你不必替换\ platforms \ android-21 \ android.jar 它会破坏SDK,你可能不会将这些更改提交给git。

以下方式可能更容易:

  1. 请参阅How do I build the Android SDK with hidden and internal APIs available?并获取framework_all.jar

  2. 将framework_all.jar放在除项目中app之外的system_libraries中。

  3. 更改app / build.gradle,如

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

  4. AS会提供“Gradle文件自......立即同步后更改”等提示,点击立即同步。

  5. 转到项目视图,您将在外部库中看到platform_all.jar。

  6. 每次更改system_libraries下的任何.jar时,您需要在app / build.gradle中进行一些更改并重新同步它。

答案 3 :(得分:0)

这里有一个替代方案,它不需要构建整个android SDK JAR或修改你的android SDK。如果你有一个JAR包含一些@hide android SDK类和/或方法,你可以将这个hunk添加到你的标准android项目build.gradle文件中:

allprojects {
  gradle.projectsEvaluated {
    tasks.withType(JavaCompile) {
      options.compilerArgs << "-Xbootclasspath/p:<FULL_PATH_TO_CUSTOM_ANDROID_API>.jar"
    }
  }
}

这会将您的JAR添加到bootclasspath,其中包含所选SDK中的android.jar。编译时,java编译器更喜欢使用前置bootclasspath中的类,从而覆盖SDK中的android.jar。

请参阅http://docs.oracle.com/javase/7/docs/technotes/tools/windows/javac.html

缺点是IntelliJ / Android Studio似乎并没有在更高级别理解这一点,因此方法在编辑器中显示为红色,但构建工作正常。实际上,您可以将其与provided解决方案结合起来,至少可以获得在编辑器中显示为有效的其他类,但IDE仍然不知道公开的@hide方法。

dependencies {
  compile fileTree(dir: 'libs', include: ['*.jar'], 'exclude': ['<PATH_TO_CUSTOM_ANDROID_API>.jar'])
  provided files('libs/<PATH_TO_CUSTOM_ANDROID_API>.jar')
}

我还没玩过足够长的时间来找到如何在compilerArgs中引用相对路径,但它应该很容易。

答案 4 :(得分:0)

有一阵子,我使用了Xbootclasspath技巧,但是Android Studio并不喜欢它(突出显示被破坏了),如果您尝试访问在SDK中已更改的隐藏API,则根本无法使用级别(这些API是隐藏的,因此不稳定)。

最终,我找到了一个解决方案,其中涉及创建用于我的Android项目的纯Java库。我称这个技巧为“无平台隐藏”(又名P-U)。主要的烦恼是存在更多样板代码,并且库结构很复杂。

如果您需要支持两个级别(假设API级别为25和更低,API级别为26和更高),那么您将需要5个Java库。 “存根”库包含从AOSP复制的Android平台代码,但像SDK中的android.jar这样,存根都被隐藏了,但是带有要公开的隐藏方法。 “包装”库使用存根库并公开具有唯一名称的方法/类。 P-U库根据检测到的Build.SDK_INT的SDK级别选择适当的包装库。

外观上看起来像这样:

                     +---------+                 +----------+
            +--api-->+ wrap-25 +--compile-only-->+ stubs-25 +--+
+-------+   |        +---------+                 +----------+  |   +---------+
|       +---+                                                  +-->+         |
|  P-U  |                                                          | android |
|       +---+                                                  +-->+         |
+-------+   |        +---------+                 +----------+  |   +---------+
            +--api-->+ wrap-26 +--compile-only-->+ stubs-26 +--+
                     +---------+                 +----------+

设置Java库需要创建一个共享的gradle文件,如下所示:

platform-shared.gradle:

// All the platform-* projects apply this gradle file
apply plugin: 'java'
apply plugin: 'java-library'

sourceCompatibility = 1.8

apply from: file("${androidBuild}/versions.gradle")

// ANDROID_HOME can override ANDROID_SDK_ROOT
// see https://developer.android.com/studio/command-line/variables

def androidHome = System.getenv('ANDROID_HOME')
def androidSdkRoot = System.getenv('ANDROID_SDK_ROOT')

if (androidHome?.trim() && new File(androidHome).canRead()) {
  androidSdkRoot = androidHome
}

if (!androidSdkRoot?.trim() || !new File(androidSdkRoot).canRead()) {
  def props = new Properties()
  def file = new File("${rootDir}/local.properties")
  if (file.exists()) {
    file.withInputStream { props.load(it) }
    if (props.getProperty("sdk.dir")) {
      androidSdkRoot = props.getProperty("sdk.dir")
    }
  }
  else {
    throw new GradleException('Android SDK root not usable')
  }
}

repositories {
  // Need an Android SDK jar to compile against even though this is a pure java project
  repositories {
    flatDir {
      dirs "${androidSdkRoot}/platforms/android-${COMPILE_SDK_VERSION}"
    }
  }

  mavenCentral()
}

// Make CI happy by implementing these tasks

task assembleRelease {
  dependsOn 'jar'
}

task assembleDebug {
  dependsOn 'jar'
}

task assembleAndroidTest {
  // Ignored
}

task lintRelease {
  // Ignored
}

task lintDebug {
  // Ignored
}

task testReleaseUnitTest {
  // Ignored
}

task testDebugUnitTest {
  // Ignored
}

然后,您将需要为每个库添加gradle文件(不显示26,它看起来与25相同)。根据需要添加更多级别。

存根25.gradle:

apply from: file("../platform-shared.gradle")

dependencies {
    api name: "android"
}

包装25.gradle:

apply from: file("../platform-shared.gradle")

dependencies {
    compileOnly project(':platform-stubs-25')
}

platform-unhidden.gradle:

apply from: file("../platform-shared.gradle")

dependencies {
    compileOnly project(':platform-stubs-25')
    compileOnly name: "android"
    api project(':platform-wrap-25')
    api project(':platform-wrap-26')
}