Room数据库Schema export Error

在使用Android Room数据库的时候报错了:

Schema export directory is not provided to the annotation processor so we cannot export the schema. You can either provide `room.schemaLocation` annotation processor argument OR set exportSchema to false.

如果您不需要检查架构并且想要摆脱警告,只需将exportSchema = false添加到RoomDatabase中,如下所示:

@Database(entities = { YourEntity.class }, version = 1, exportSchema = false)
public abstract class AppDatabase extends RoomDatabase {
   //...
}

另一种方法是在应用模块的build.gradle文件中,将此文件添加到defaultConfig部分(在android部分下面)。这会将架构写到项目文件夹的schemas子文件夹中。

android {

    // ... (compileSdkVersion, buildToolsVersion, etc)

    defaultConfig {

     // ... (applicationId, miSdkVersion, etc)

        kapt {
            arguments {
                arg("room.schemaLocation","$projectDir/schemas".toString())
            }
        }
    }

    buildTypes {
        // ... (buildTypes, compileOptions, etc)
    }
}

//...

以上是Kotlin,如果是Java:

android {

    // ... (compileSdkVersion, buildToolsVersion, etc)

    defaultConfig {

        // ... (applicationId, miSdkVersion, etc)

        javaCompileOptions {
            annotationProcessorOptions {
                arguments = ["room.schemaLocation":"$projectDir/schemas".toString()]
            }
        }
    }

    // ... (buildTypes, compileOptions, etc)

}

当执行项目后,在Android Studio 的Project视图下,查看项目,会发现Module生成了一个schemas的文件夹,打开.json文件看起来像这样:

{
 "formatVersion": 1,
 "database": {
   "version": 1,
   "identityHash":"6240057b6178b803a0bf9915edf969e3",
   "entities": [
      {
       "tableName":"sms_table",
       "createSql":"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `message` TEXT, `date` INTEGER, `client_id` INTEGER)",
       "fields": [
          {
           "fieldPath":"id",
           "columnName":"id",
           "affinity":"INTEGER"
          },
          {
           "fieldPath":"message",
           "columnName":"message",
           "affinity":"TEXT"
          },
          {
           "fieldPath":"date",
           "columnName":"date",
           "affinity":"INTEGER"
          },
          {
           "fieldPath":"clientId",
           "columnName":"client_id",
           "affinity":"INTEGER"
          }
        ],
       "primaryKey": {
         "columnNames": [
           "id"
          ],
         "autoGenerate": true
        },
       "indices": [],
       "foreignKeys": []
      }
    ],
   "setupQueries": [
     "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
     "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, "6240057b6178b803a0bf9915edf969e3")"
    ]
  }
}

改变状态栏文本颜色(WHITE/BLACK)

API> = 23

从API v23及更高版本开始,可以将以下内容添加到AppTheme styles.xml中:

  • 解决方案1
// View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR: 将状态栏的文字设置为黑色
window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
  • 解决方案1
<item name="android:statusBarColor">@color/colorPrimaryDark</item>
<item name="android:windowLightStatusBar">true</item>

当android:windowLightStatusBar设置为true,状态栏文字颜色将能够可以看出,当状态栏的颜色是白色的,而当android:windowLightStatusBar设置为false,状态栏文字颜色将被设计在状态栏的颜色是可以看到暗。

API <23

在Android中无法更改状态栏的颜色。可以在应用程序中设置状态栏的背景色

val window: Window = activity.getWindow()
// clear FLAG_TRANSLUCENT_STATUS flag:
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
// add FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS flag to the window
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
// finally change the color
window.setStatusBarColor(ContextCompat.getColor(activity,R.color.my_statusbar_color))

https://developer.android.google.cn/reference/android/view/Window.html#setStatusBarColor(int)

onActivityResult过时了,registerForActivityResult使用方法

最常用的写法

registerForActivityResult(
            ActivityResultContracts.StartActivityForResult()
        ) { result ->
            val data = result.data
            val resultCode= result.resultCode
            val extra = data?.getStringExtra("extra")
        }.launch(Intent(this, MainActivity::class.java))

除了基本用法,ActivityResultContracts还提供了一些ActivityResultContract的实现类,以便进行其他的操作:

  • RequestMultiplePermissions : 多个权限请求
  • RequestPermission : 单个权限请求
  • TakePicturePreview : 拍照预览
  • TakePicture : 拍照
  • TakeVideo : 摄像
  • PickContact : 选择联系人
  • GetContent : 获取各种文件的Uri
  • GetMultipleContents : 获取多个各种文件的Uri
  • OpenDocument : 打开文件
  • OpenMultipleDocuments : 打开多个文件
  • OpenDocumentTree : 打开文件夹
  • CreateDocument : 创建文件

打开相机拍照:

registerForActivityResult(ActivityResultContracts.TakePicturePreview()){
           // 返回bitmap
        }.launch(null)

获取单个/多个权限请求:


// 单个权限获取
registerForActivityResult(ActivityResultContracts.RequestPermission()) {
            if (it) {//同意权限
            } else {//拒绝权限
            }
        }.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
// 多个权限获取
var permissions: Array<String> = arrayOf(
            Manifest.permission.WRITE_EXTERNAL_STORAGE,
            Manifest.permission.CAMERA
        )
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) {
            if (it[Manifest.permission.WRITE_EXTERNAL_STORAGE]!!) {// 同意
            } else {// 拒绝
            }
            if (it[Manifest.permission.CAMERA]!!) {// 同意
            } else {// 拒绝
            }
        }.launch(permissions)

查询联系人信息:

registerForActivityResult(ActivityResultContracts.PickContact()){
            if(it != null){
                val cursor = contentResolver.query(it, null, null, null, null)
                cursor?.run {
                    if(cursor.moveToFirst()){
                        val name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME))
                    }
                }
            }
        }.launch(null)

选取文件:

registerForActivityResult(ActivityResultContracts.OpenDocument()){
            // 获取的文件uri
        }.launch(arrayOf("image/*","text/plain"))

Caused by: java.lang.IllegalStateException: Only fullscreen opaque activities can request orientation

android 8.0 (API=26) 出现的问题

解决方法:

  1. 去掉android:screenOrientation;
  2. android:windowIsTranslucent 改为false; 如果需要透明的设置加上android:windowDisablePreview =true;
    在项目res目录下创建values-v26/styles.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="AppTheme.Start" parent="AppTheme">
        <item name="android:windowActionBar">false</item>
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowFullscreen">true</item>
      
        <!-- 适配android手机系统8.0(api26),Only fullscreen opaque activities can request orientation -->
        <!--用背景图消除启动白屏-->
        <item name="android:windowBackground">@mipmap/background</item>
        <item name="android:windowIsTranslucent">false</item>
        <item name="android:windowDisablePreview">true</item>
    </style>
</resources>

Retrofit传参Map<String,Any>报错

在使用retrofit请求接口时报错了,参数:Map<String,Any>

Parameter type must not include a type variable or wildcard: java.util.Map<java.lang.String, ?>

问题是在值类型为Any,在JAVA里这个值就Object,查在kotlin里就变成*号了,Retrofit不能识别。
只需要添加@JvmSuppressWildcards接口即可

@JvmSuppressWildcards
internal interface WebService {
    ...
}

android5遇到INSTALL_FAILED_DEXOPT 解决办法

最近写个项目,在用一台android5.0.2的旧手机测试时出现INSTALL_FAILED_DEXOPT,看图:

20201216171437.png20201216171437.png

点击ok后可以看到报错:

20201216171740.png20201216171740.png

起初以为是手机内存不足,卸载了多个app后无效,恢复出厂设置也一样无效。在网上找了好几天都无头绪,直到我看到这样一片文章:

20201216172427.png20201216172427.png

但我这里并没有用到kotlin协程,于是我移除了kotlin-android-extensions,最还是一样无效,为了方便,重新新建了一个项目。然后一个一个加进去试,最后发现"androidx.room:room-ktx"加入后就出现以上错误,既然找到了错误来源,后面的问题就好解决了。

Android唤起微信扫一扫

fun scanQR() {
        try {
            val intent = context.packageManager.getLaunchIntentForPackage("com.tencent.mm")
            intent!!.putExtra("LauncherUI.From.Scaner.Shortcut", true)
            context.startActivity(intent)
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

反编译微信小程序

一、环境准备

  1. node.js
  2. 有root权限的android手机
  3. 反编译脚本:wxappUnpacker(github上作者已移除,可搜索其它版本)

二、获取小程序包

  1. 在手机文件夹里找到以下路径(需要root权限):/data/data/com.tencent.mm/MicroMsg/xxxxx(这里是微信用户的某种id)/appbrand/pkg/
  2. 这里通过查看文件更新时间(在这之前,为了方便寻找对应文件,我先将其它所有微信小程序都移除了)找到你要反编译的小程序,以wxapkg后缀名结尾。
  3. 通过adb将文件传到电脑上。

三、安装反编译依赖

  1. 先安装nodejs
  2. clone wxappUnpacker后,通过命令行进入到该文件夹。
  3. 安装依赖包
npm install esprima
npm install css-tree
npm install cssbeautify
npm install vm2
npm install uglify-es
npm install js-beautify
npm install escodegen

四、开始反编译

  1. 执行以下命令:
node ./wuWxapkg.js ../_xxxxxx_16.wxapkg
  1. 完成了编译后,提示:
    20201129204449.png20201129204449.png
  2. 最后开发者工具打开项目:
    20201129204815.png20201129204815.png

注意:该方法仅为学习参考,切勿滥用。