编译Android旧项目遇Parcelable接口实现报错,求解决方案
问题描述
重新编译两年前可正常编译的旧Android项目时,出现两个编译错误:
- 类
Device并非抽象类,未实现android.os.Parcelable中定义的抽象方法public abstract fun writeToParcel(p0: Parcel, p1: Int): Unit - 报错
writeToParcel未覆盖任何方法
相关代码
Device.kt
import android.bluetooth.BluetoothDevice import android.os.Parcel import android.os.Parcelable data class Device( val device: BluetoothDevice, val rssi: Int = 0): Parcelable { constructor(parcel: Parcel) : this( parcel.readParcelable(BluetoothDevice::class.java.classLoader)!!, parcel.readInt() ) override fun describeContents() = 0 override fun writeToParcel(dest: Parcel?, flags: Int) { dest?.writeParcelable(device, flags) } companion object CREATOR : Parcelable.Creator<Device> { override fun createFromParcel(parcel: Parcel): Device { return Device(parcel) } override fun newArray(size: Int): Array<Device?> { return arrayOfNulls(size) } } }
模块build.gradle
plugins { id 'com.android.application' id 'kotlin-android' id 'androidx.navigation.safeargs' } android { compileSdkVersion 34 buildToolsVersion "30.0.3" defaultConfig { applicationId "com.astar.osterrig.controlrelay" minSdkVersion 22 targetSdkVersion 34 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } kotlinOptions { jvmTarget = '1.8' } buildFeatures { viewBinding true } namespace 'com.astar.osterrig.controlrelay' } dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation 'androidx.core:core-ktx:1.12.0' implementation 'androidx.appcompat:appcompat:1.6.1' implementation 'com.google.android.material:material:1.11.0' implementation 'androidx.fragment:fragment-ktx:1.6.2' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'androidx.navigation:navigation-fragment-ktx:2.7.6' implementation 'androidx.navigation:navigation-ui-ktx:2.7.6' implementation 'eo.view:signalstrength:2.0.0' implementation 'no.nordicsemi.android:ble:2.3.0' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' }
项目根目录build.gradle
// Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { ext.kotlin_version = '1.9.0' repositories { google() mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:8.2.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath 'androidx.navigation:navigation-safe-args-gradle-plugin:2.7.6' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } } allprojects { repositories { google() mavenCentral() jcenter() // Warning: this repository is going to shut down soon } } task clean(type: Delete) { delete rootProject.buildDir }
解决方案
问题核心是**writeToParcel方法的参数签名与Parcelable接口定义不匹配**:
- 新版Android SDK/Kotlin中,
Parcelable接口要求的writeToParcel方法第一个参数为非空Parcel,但你的代码写成了可空的Parcel?,导致既未正确实现接口方法,又错误标记了override - 另外代码还遗漏了
rssi字段的序列化写入,会导致反序列化后该字段值异常
修改Device.kt中的writeToParcel方法即可解决:
override fun writeToParcel(dest: Parcel, flags: Int) { dest.writeParcelable(device, flags) dest.writeInt(rssi) // 补上rssi字段的序列化 }
补充说明
两年前项目可正常编译,是因为当时的Parcelable接口在Kotlin中的参数空安全规则更宽松,升级Gradle、Kotlin或Android SDK后,接口签名检查严格化,触发了该错误。
内容的提问来源于stack exchange,提问作者Alan Khabitsov
相关产品推荐
相关产品推荐

