标签 Android 下的文章

旧版本 Android 的模拟器可能出现调用 Canvas.clipPath() 导致 app 崩溃的现象。这是因为模拟器在过低的 API 级别下启用了 Canvas 的硬件加速1,在对应 API 级别下强制关闭硬件加速就好了。

E/AndroidRuntime: FATAL EXCEPTION: main
    java.lang.UnsupportedOperationException
        at android.view.GLES20Canvas.clipPath(GLES20Canvas.java:408)
If your application is affected by any of these missing features or limitations, you can turn off hardware acceleration for just the affected portion of your application by calling setLayerType(View.LAYER_TYPE_SOFTWARE, null). This way, you can still take advantage of hardware acceleration everywhere else. See Control hardware acceleration for more information on how to enable and disable hardware acceleration at different levels in your application.

参考资料

菜单中选择 ... -> Phone -> SMS message,发送短信后进入模拟器的短信应用就可以将文本复制到模拟器内的剪贴板了。

Android Emulator Copy & Paste: Back by popular demand, we added back the Copy & Paste feature to the latest Emulator (v25.3.1). We have a shared clipboard between the Android Emulator and host operating system, which will allow you to copy text between both environments. Copy & Paste works with x86 Google API Emulator system images API Level 19 (Android 4.4 - Kitkat) and higher.

如果镜像 API Level 高于 18,直接复制粘贴就好,和系统剪贴板互通。

如果 Android 模拟器无法上网,测试 adb shell 里 ping 域名解析不出 IP,可以试试用 ./emulator/emulator -avd <name> -dns-server 1.1.1.1 启动。

When starting the emulator at the command line, you can also use the -dns-server <serverList> option to manually specify the addresses of DNS servers to use, where <serverList> is a comma-separated list of server names or IP addresses. You might find this option useful if you encounter DNS resolution problems in the emulated network (for example, an "Unknown Host error" message that appears when using the web browser).

https://developer.android.com/studio/run/emulator-networking#dns

给旧设备写 app 时遇到一个问题,在重写的 Application 类里使用 Java 8 特性会在运行时报错找不到类,而在其他地方使用都没问题。

E/AndroidRuntime: FATAL EXCEPTION: main
    java.lang.NoClassDefFoundError: $r8$backportedMethods$utility$Objects$2$equals
        at MyApplication.onCreate(MyApplication.java:xx)

排查了一圈才发现是 multidex 惹的祸,由于执行 attachBaseContext() 需要先加载 MyApplication 类,此时 multidex 还没来得及安装,所以 MyApplication 里不能调用主 DEX 文件中不存在的类。

public class MyApplication extends SomeOtherApplication {
  @Override
  protected void attachBaseContext(Context base) {
     super.attachBaseContext(base);
     MultiDex.install(this);
  }
}

参考资料

https://developer.android.com/studio/write/java8-support#library-desugaring
https://developer.android.com/studio/build/multidex

# In `adb shell`
$ settings get global captive_portal_http_url
null
$ settings get global captive_portal_https_url
null

$ settings put global captive_portal_http_url https://204.vercel.app/generate_204
$ settings put global captive_portal_https_url https://204.vercel.app/generate_204

$ settings
Settings provider (settings) commands:
  help
      Print this help text.
  get [--user <USER_ID> | current] [--lineage] NAMESPACE KEY
      Retrieve the current value of KEY.
  put [--user <USER_ID> | current] [--lineage] NAMESPACE KEY VALUE [TAG] [default]
      Change the contents of KEY to VALUE.
      TAG to associate with the setting.
      {default} to set as the default, case-insensitive only for global/secure namespace
  delete [--lineage] NAMESPACE KEY
      Delete the entry for KEY.
  reset [--user <USER_ID> | current] NAMESPACE {PACKAGE_NAME | RESET_MODE}
      Reset the global/secure table for a package with mode.
      RESET_MODE is one of {untrusted_defaults, untrusted_clear, trusted_defaults}, case-insensitive
  list [--lineage] NAMESPACE
      Print all defined keys.
      NAMESPACE is one of {system, secure, global}, case-insensitive
# In `adb shell`
$ settings get global captive_portal_http_url
http://google.cn/generate_204
$ settings get global captive_portal_https_url
https://google.cn/generate_204

$ settings put global captive_portal_http_url https://204.vercel.app/generate_204
$ settings put global captive_portal_https_url https://204.vercel.app/generate_204

$ settings
usage:  settings [--user <USER_ID> | current] [--cm] get namespace key
        settings [--user <USER_ID> | current] [--cm] put namespace key value
        settings [--user <USER_ID> | current] [--cm] delete namespace key
        settings [--user <USER_ID> | current] [--cm] list namespace

'namespace' is one of {system, secure, global}, case-insensitive
If '--user <USER_ID> | current' is not given, the operations are performed on the system user.
If '--cm' is given, the operations are performed on the CMSettings provider.

Source: android-9.0.0\_r8, android-7.1.2\_r36