Fix majority of Android Studio warnings (#88)

This commit is contained in:
John Maguire 2022-11-17 16:48:44 -05:00 committed by GitHub
parent a5684e1978
commit e4bbd0a31c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 73 additions and 72 deletions

View File

@ -26,6 +26,8 @@ apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android { android {
namespace "net.defined.mobile_nebula"
compileSdkVersion 33 compileSdkVersion 33
ndkVersion flutter.ndkVersion ndkVersion flutter.ndkVersion
@ -44,8 +46,8 @@ android {
defaultConfig { defaultConfig {
applicationId "net.defined.mobile_nebula" applicationId "net.defined.mobile_nebula"
minSdkVersion 23 //flutter.minSdkVersion minSdkVersion 26 //flutter.minSdkVersion
targetSdkVersion 31 //flutter.targetSdkVersion targetSdkVersion 33 //flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger() versionCode flutterVersionCode.toInteger()
versionName flutterVersionName versionName flutterVersionName
} }
@ -81,7 +83,7 @@ dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion"
implementation "androidx.security:security-crypto:1.0.0" implementation "androidx.security:security-crypto:1.0.0"
implementation "androidx.work:work-runtime-ktx:$workVersion" implementation "androidx.work:work-runtime-ktx:$workVersion"
implementation 'com.google.code.gson:gson:2.8.6' implementation 'com.google.code.gson:gson:2.8.9'
implementation "com.google.guava:guava:31.0.1-android" implementation "com.google.guava:guava:31.0.1-android"
implementation project(':mobileNebula') implementation project(':mobileNebula')

View File

@ -1,5 +1,4 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android">
package="net.defined.mobile_nebula">
<!-- Flutter needs it to communicate with the running application <!-- Flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc. to allow setting breakpoints, to provide hot reload, etc.
--> -->

View File

@ -1,6 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools">
package="net.defined.mobile_nebula">
<!-- io.flutter.app.FlutterApplication is an android.app.Application that <!-- io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method. calls FlutterMain.startInitialization(this); in its onCreate method.
In most cases you can leave this as-is, but you if you want to provide In most cases you can leave this as-is, but you if you want to provide

View File

@ -1,10 +1,9 @@
package net.defined.mobile_nebula package net.defined.mobile_nebula
import android.content.Context import android.content.Context
import android.util.Log
import com.google.gson.Gson import com.google.gson.Gson
class InvalidCredentialsException(): Exception("Invalid credentials") class InvalidCredentialsException: Exception("Invalid credentials")
class APIClient(context: Context) { class APIClient(context: Context) {
private val packageInfo = PackageInfo(context) private val packageInfo = PackageInfo(context)

View File

@ -6,7 +6,6 @@ import android.util.Log
import androidx.work.Worker import androidx.work.Worker
import androidx.work.WorkerParameters import androidx.work.WorkerParameters
import java.io.Closeable import java.io.Closeable
import java.io.IOException
import java.nio.channels.FileChannel import java.nio.channels.FileChannel
import java.nio.file.Paths import java.nio.file.Paths
import java.nio.file.StandardOpenOption import java.nio.file.StandardOpenOption
@ -35,10 +34,10 @@ class DNUpdateWorker(ctx: Context, params: WorkerParameters) : Worker(ctx, param
} }
} }
return if (failed) Result.failure() else Result.success(); return if (failed) Result.failure() else Result.success()
} }
fun updateSite(site: Site) { private fun updateSite(site: Site) {
try { try {
DNUpdateLock(site).use { DNUpdateLock(site).use {
if (updater.updateSite(site)) { if (updater.updateSite(site)) {
@ -60,7 +59,7 @@ class DNUpdateWorker(ctx: Context, params: WorkerParameters) : Worker(ctx, param
} }
} }
class DNUpdateLock(private val site: Site): Closeable { class DNUpdateLock(site: Site): Closeable {
private val fileChannel = FileChannel.open( private val fileChannel = FileChannel.open(
Paths.get(site.path+"/update.lock"), Paths.get(site.path+"/update.lock"),
StandardOpenOption.CREATE, StandardOpenOption.CREATE,

View File

@ -5,7 +5,7 @@ import androidx.security.crypto.EncryptedFile
import androidx.security.crypto.MasterKeys import androidx.security.crypto.MasterKeys
import java.io.* import java.io.*
class EncFile(var context: Context) { class EncFile(private val context: Context) {
private val scheme = EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB private val scheme = EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
private val master: String = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC) private val master: String = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC)

View File

@ -10,11 +10,7 @@ import android.content.ServiceConnection
import android.net.VpnService import android.net.VpnService
import android.os.* import android.os.*
import android.util.Log import android.util.Log
import androidx.annotation.NonNull
import androidx.work.* import androidx.work.*
import com.google.common.base.Throwables
import com.google.common.util.concurrent.Futures
import com.google.common.util.concurrent.FutureCallback
import com.google.gson.Gson import com.google.gson.Gson
import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine import io.flutter.embedding.engine.FlutterEngine
@ -52,12 +48,12 @@ class MainActivity: FlutterActivity() {
fun getContext(): Context? { return appContext } fun getContext(): Context? { return appContext }
} }
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) { override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
appContext = context appContext = context
//TODO: Initializing in the constructor leads to a context lacking info we need, figure out the right way to do this //TODO: Initializing in the constructor leads to a context lacking info we need, figure out the right way to do this
sites = Sites(flutterEngine) sites = Sites(flutterEngine)
GeneratedPluginRegistrant.registerWith(flutterEngine); GeneratedPluginRegistrant.registerWith(flutterEngine)
ui = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL) ui = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL)
ui!!.setMethodCallHandler { call, result -> ui!!.setMethodCallHandler { call, result ->
@ -228,12 +224,12 @@ class MainActivity: FlutterActivity() {
private fun validateOrDeleteSite(siteDir: File): Boolean { private fun validateOrDeleteSite(siteDir: File): Boolean {
try { try {
// Try to render a full site, if this fails the config was bad somehow // Try to render a full site, if this fails the config was bad somehow
val site = Site(context, siteDir) Site(context, siteDir)
} catch(err: java.io.FileNotFoundException) { } catch(err: java.io.FileNotFoundException) {
Log.e(TAG, "Site not found at ${siteDir}") Log.e(TAG, "Site not found at $siteDir")
return false return false
} catch(err: Exception) { } catch(err: Exception) {
Log.e(TAG, "Deleting site at ${siteDir} due to error: ${err}") Log.e(TAG, "Deleting site at $siteDir due to error: $err")
siteDir.deleteRecursively() siteDir.deleteRecursively()
return false return false
} }
@ -268,8 +264,9 @@ class MainActivity: FlutterActivity() {
} }
private fun stopSite() { private fun stopSite() {
val intent = Intent(this, NebulaVpnService::class.java) val intent = Intent(this, NebulaVpnService::class.java).apply {
intent.setAction(NebulaVpnService.ACTION_STOP) action = NebulaVpnService.ACTION_STOP
}
// We can't stopService because we have to close the fd first. The service will call stopSelf when ready. // We can't stopService because we have to close the fd first. The service will call stopSelf when ready.
// See the official example: https://android.googlesource.com/platform/development/+/master/samples/ToyVpn/src/com/example/android/toyvpn/ToyVpnClient.java#116 // See the official example: https://android.googlesource.com/platform/development/+/master/samples/ToyVpn/src/com/example/android/toyvpn/ToyVpnClient.java#116
@ -286,9 +283,9 @@ class MainActivity: FlutterActivity() {
return result.success(null) return result.success(null)
} }
var msg = Message.obtain() val msg = Message.obtain()
msg.what = NebulaVpnService.MSG_LIST_HOSTMAP msg.what = NebulaVpnService.MSG_LIST_HOSTMAP
msg.replyTo = Messenger(object: Handler() { msg.replyTo = Messenger(object: Handler(Looper.getMainLooper()) {
override fun handleMessage(msg: Message) { override fun handleMessage(msg: Message) {
result.success(msg.data.getString("data")) result.success(msg.data.getString("data"))
} }
@ -306,9 +303,9 @@ class MainActivity: FlutterActivity() {
return result.success(null) return result.success(null)
} }
var msg = Message.obtain() val msg = Message.obtain()
msg.what = NebulaVpnService.MSG_LIST_PENDING_HOSTMAP msg.what = NebulaVpnService.MSG_LIST_PENDING_HOSTMAP
msg.replyTo = Messenger(object: Handler() { msg.replyTo = Messenger(object: Handler(Looper.getMainLooper()) {
override fun handleMessage(msg: Message) { override fun handleMessage(msg: Message) {
result.success(msg.data.getString("data")) result.success(msg.data.getString("data"))
} }
@ -333,11 +330,11 @@ class MainActivity: FlutterActivity() {
return result.success(null) return result.success(null)
} }
var msg = Message.obtain() val msg = Message.obtain()
msg.what = NebulaVpnService.MSG_GET_HOSTINFO msg.what = NebulaVpnService.MSG_GET_HOSTINFO
msg.data.putString("vpnIp", vpnIp) msg.data.putString("vpnIp", vpnIp)
msg.data.putBoolean("pending", pending) msg.data.putBoolean("pending", pending)
msg.replyTo = Messenger(object: Handler() { msg.replyTo = Messenger(object: Handler(Looper.getMainLooper()) {
override fun handleMessage(msg: Message) { override fun handleMessage(msg: Message) {
result.success(msg.data.getString("data")) result.success(msg.data.getString("data"))
} }
@ -357,7 +354,7 @@ class MainActivity: FlutterActivity() {
} }
val addr = call.argument<String>("addr") val addr = call.argument<String>("addr")
if (vpnIp == "") { if (addr == "") {
return result.error("required_argument", "addr is a required argument", null) return result.error("required_argument", "addr is a required argument", null)
} }
@ -365,11 +362,11 @@ class MainActivity: FlutterActivity() {
return result.success(null) return result.success(null)
} }
var msg = Message.obtain() val msg = Message.obtain()
msg.what = NebulaVpnService.MSG_SET_REMOTE_FOR_TUNNEL msg.what = NebulaVpnService.MSG_SET_REMOTE_FOR_TUNNEL
msg.data.putString("vpnIp", vpnIp) msg.data.putString("vpnIp", vpnIp)
msg.data.putString("addr", addr) msg.data.putString("addr", addr)
msg.replyTo = Messenger(object: Handler() { msg.replyTo = Messenger(object: Handler(Looper.getMainLooper()) {
override fun handleMessage(msg: Message) { override fun handleMessage(msg: Message) {
result.success(msg.data.getString("data")) result.success(msg.data.getString("data"))
} }
@ -392,10 +389,10 @@ class MainActivity: FlutterActivity() {
return result.success(null) return result.success(null)
} }
var msg = Message.obtain() val msg = Message.obtain()
msg.what = NebulaVpnService.MSG_CLOSE_TUNNEL msg.what = NebulaVpnService.MSG_CLOSE_TUNNEL
msg.data.putString("vpnIp", vpnIp) msg.data.putString("vpnIp", vpnIp)
msg.replyTo = Messenger(object: Handler() { msg.replyTo = Messenger(object: Handler(Looper.getMainLooper()) {
override fun handleMessage(msg: Message) { override fun handleMessage(msg: Message) {
result.success(msg.data.getBoolean("data")) result.success(msg.data.getBoolean("data"))
} }
@ -475,7 +472,7 @@ class MainActivity: FlutterActivity() {
} }
// Handle and route messages coming from the vpn service // Handle and route messages coming from the vpn service
inner class IncomingHandler: Handler() { inner class IncomingHandler: Handler(Looper.getMainLooper()) {
override fun handleMessage(msg: Message) { override fun handleMessage(msg: Message) {
val id = msg.data.getString("id") val id = msg.data.getString("id")
@ -523,7 +520,7 @@ class MainActivity: FlutterActivity() {
inner class RefreshReceiver : BroadcastReceiver() { inner class RefreshReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent?) { override fun onReceive(context: Context, intent: Intent?) {
if (intent?.getAction() != ACTION_REFRESH_SITES) return if (intent?.action != ACTION_REFRESH_SITES) return
if (sites == null) return if (sites == null) return
Log.d(TAG, "Refreshing sites in MainActivity") Log.d(TAG, "Refreshing sites in MainActivity")

View File

@ -1,6 +1,6 @@
package net.defined.mobile_nebula package net.defined.mobile_nebula
import io.flutter.view.FlutterMain import io.flutter.embedding.engine.loader.FlutterLoader
import android.app.Application import android.app.Application
import androidx.work.Configuration import androidx.work.Configuration
import androidx.work.WorkManager import androidx.work.WorkManager
@ -14,6 +14,6 @@ class MyApplication : Application() {
val myConfig = Configuration.Builder().build() val myConfig = Configuration.Builder().build()
WorkManager.initialize(this, myConfig) WorkManager.initialize(this, myConfig)
FlutterMain.startInitialization(applicationContext) FlutterLoader().startInitialization(applicationContext)
} }
} }

View File

@ -9,7 +9,6 @@ import android.net.*
import android.os.* import android.os.*
import android.system.OsConstants import android.system.OsConstants
import android.util.Log import android.util.Log
import androidx.annotation.RequiresApi
import androidx.work.* import androidx.work.*
import mobileNebula.CIDR import mobileNebula.CIDR
import java.io.File import java.io.File
@ -57,7 +56,7 @@ class NebulaVpnService : VpnService() {
} }
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
if (intent?.getAction() == ACTION_STOP) { if (intent?.action == ACTION_STOP) {
stopVpn() stopVpn()
return Service.START_NOT_STICKY return Service.START_NOT_STICKY
} }
@ -75,10 +74,10 @@ class NebulaVpnService : VpnService() {
return super.onStartCommand(intent, flags, startId) return super.onStartCommand(intent, flags, startId)
} }
path = intent?.getStringExtra("path") path = intent!!.getStringExtra("path")!!
//TODO: if we fail to start, android will attempt a restart lacking all the intent data we need. //TODO: if we fail to start, android will attempt a restart lacking all the intent data we need.
// Link active site config in Main to avoid this // Link active site config in Main to avoid this
site = Site(this, File(path)) site = Site(this, File(path!!))
if (site!!.cert == null) { if (site!!.cert == null) {
announceExit(id, "Site is missing a certificate") announceExit(id, "Site is missing a certificate")
@ -96,7 +95,7 @@ class NebulaVpnService : VpnService() {
} }
private fun startVpn() { private fun startVpn() {
var ipNet: CIDR val ipNet: CIDR
try { try {
ipNet = mobileNebula.MobileNebula.parseCIDR(site!!.cert!!.cert.details.ips[0]) ipNet = mobileNebula.MobileNebula.parseCIDR(site!!.cert!!.cert.details.ips[0])
@ -110,16 +109,16 @@ class NebulaVpnService : VpnService() {
.setMtu(site!!.mtu) .setMtu(site!!.mtu)
.setSession(TAG) .setSession(TAG)
.allowFamily(OsConstants.AF_INET) .allowFamily(OsConstants.AF_INET)
.allowFamily(OsConstants.AF_INET6); .allowFamily(OsConstants.AF_INET6)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
builder.setMetered(false); builder.setMetered(false)
} }
// Add our unsafe routes // Add our unsafe routes
site!!.unsafeRoutes.forEach { unsafeRoute -> site!!.unsafeRoutes.forEach { unsafeRoute ->
val ipNet = mobileNebula.MobileNebula.parseCIDR(unsafeRoute.route) val unsafeIPNet = mobileNebula.MobileNebula.parseCIDR(unsafeRoute.route)
builder.addRoute(ipNet.network, ipNet.maskSize.toInt()) builder.addRoute(unsafeIPNet.network, unsafeIPNet.maskSize.toInt())
} }
try { try {
@ -140,7 +139,7 @@ class NebulaVpnService : VpnService() {
nebula!!.start() nebula!!.start()
running = true running = true
sendSimple(MSG_IS_RUNNING, if (running) 1 else 0) sendSimple(MSG_IS_RUNNING, 1)
} }
// Used to detect network changes (wifi -> cell or vice versa) and rebinds the udp socket/updates LH // Used to detect network changes (wifi -> cell or vice versa) and rebinds the udp socket/updates LH
@ -158,7 +157,7 @@ class NebulaVpnService : VpnService() {
connectivityManager.unregisterNetworkCallback(networkCallback) connectivityManager.unregisterNetworkCallback(networkCallback)
} }
inner class NetworkCallback() : ConnectivityManager.NetworkCallback () { inner class NetworkCallback : ConnectivityManager.NetworkCallback () {
override fun onAvailable(network: Network) { override fun onAvailable(network: Network) {
super.onAvailable(network) super.onAvailable(network)
nebula!!.rebind("network change") nebula!!.rebind("network change")
@ -200,7 +199,7 @@ class NebulaVpnService : VpnService() {
} }
private fun reload() { private fun reload() {
site = Site(this, File(path)) site = Site(this, File(path!!))
nebula?.reload(site!!.config, site!!.getKey(this)) nebula?.reload(site!!.config, site!!.getKey(this))
} }
@ -241,9 +240,9 @@ class NebulaVpnService : VpnService() {
inner class ReloadReceiver : BroadcastReceiver() { inner class ReloadReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent?) { override fun onReceive(context: Context, intent: Intent?) {
if (intent?.getAction() != ACTION_RELOAD) return if (intent?.action != ACTION_RELOAD) return
if (!running) return if (!running) return
if (intent?.getStringExtra("id") != site!!.id) return if (intent.getStringExtra("id") != site!!.id) return
Log.d(TAG, "Reloading Nebula") Log.d(TAG, "Reloading Nebula")
@ -254,7 +253,7 @@ class NebulaVpnService : VpnService() {
/** /**
* Handler of incoming messages from clients. * Handler of incoming messages from clients.
*/ */
inner class IncomingHandler(context: Context, private val applicationContext: Context = context.applicationContext) : Handler() { inner class IncomingHandler : Handler(Looper.getMainLooper()) {
override fun handleMessage(msg: Message) { override fun handleMessage(msg: Message) {
//TODO: how do we limit what can talk to us? //TODO: how do we limit what can talk to us?
//TODO: Make sure replyTo is actually a messenger //TODO: Make sure replyTo is actually a messenger
@ -295,7 +294,7 @@ class NebulaVpnService : VpnService() {
if (protect(msg)) { return } if (protect(msg)) { return }
val res = nebula!!.listHostmap(msg.what == MSG_LIST_PENDING_HOSTMAP) val res = nebula!!.listHostmap(msg.what == MSG_LIST_PENDING_HOSTMAP)
var m = Message.obtain(null, msg.what) val m = Message.obtain(null, msg.what)
m.data.putString("data", res) m.data.putString("data", res)
msg.replyTo.send(m) msg.replyTo.send(m)
} }
@ -304,7 +303,7 @@ class NebulaVpnService : VpnService() {
if (protect(msg)) { return } if (protect(msg)) { return }
val res = nebula!!.getHostInfoByVpnIp(msg.data.getString("vpnIp"), msg.data.getBoolean("pending")) val res = nebula!!.getHostInfoByVpnIp(msg.data.getString("vpnIp"), msg.data.getBoolean("pending"))
var m = Message.obtain(null, msg.what) val m = Message.obtain(null, msg.what)
m.data.putString("data", res) m.data.putString("data", res)
msg.replyTo.send(m) msg.replyTo.send(m)
} }
@ -313,7 +312,7 @@ class NebulaVpnService : VpnService() {
if (protect(msg)) { return } if (protect(msg)) { return }
val res = nebula!!.setRemoteForTunnel(msg.data.getString("vpnIp"), msg.data.getString("addr")) val res = nebula!!.setRemoteForTunnel(msg.data.getString("vpnIp"), msg.data.getString("addr"))
var m = Message.obtain(null, msg.what) val m = Message.obtain(null, msg.what)
m.data.putString("data", res) m.data.putString("data", res)
msg.replyTo.send(m) msg.replyTo.send(m)
} }
@ -322,7 +321,7 @@ class NebulaVpnService : VpnService() {
if (protect(msg)) { return } if (protect(msg)) { return }
val res = nebula!!.closeTunnel(msg.data.getString("vpnIp")) val res = nebula!!.closeTunnel(msg.data.getString("vpnIp"))
var m = Message.obtain(null, msg.what) val m = Message.obtain(null, msg.what)
m.data.putBoolean("data", res) m.data.putBoolean("data", res)
msg.replyTo.send(m) msg.replyTo.send(m)
} }
@ -356,7 +355,7 @@ class NebulaVpnService : VpnService() {
return super.onBind(intent) return super.onBind(intent)
} }
messenger = Messenger(IncomingHandler(this)) messenger = Messenger(IncomingHandler())
return messenger.binder return messenger.binder
} }
} }

View File

@ -2,17 +2,27 @@ package net.defined.mobile_nebula
import android.content.Context import android.content.Context
import android.content.pm.ApplicationInfo import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import android.content.pm.PackageInfo import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.os.Build import android.os.Build
class PackageInfo(val context: Context) { class PackageInfo(private val context: Context) {
private val pInfo: PackageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0) private val pInfo: PackageInfo =
private val appInfo: ApplicationInfo = context.getApplicationInfo() if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
context.packageManager.getPackageInfo(context.packageName, PackageManager.PackageInfoFlags.of(0))
else
@Suppress("DEPRECATION")
context.packageManager.getPackageInfo(context.packageName, 0)
private val appInfo: ApplicationInfo = context.applicationInfo
fun getVersion(): String { fun getVersion(): String {
val version: String = pInfo.versionName val version: String = pInfo.versionName
val build: Int = pInfo.versionCode val build: Long = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P)
pInfo.longVersionCode
else
@Suppress("DEPRECATION")
pInfo.versionCode.toLong()
return "%s-%d".format(version, build) return "%s-%d".format(version, build)
} }
@ -22,6 +32,6 @@ class PackageInfo(val context: Context) {
} }
fun getSystemVersion(): String { fun getSystemVersion(): String {
return Build.VERSION.RELEASE; return Build.VERSION.RELEASE
} }
} }

View File

@ -3,12 +3,10 @@ package net.defined.mobile_nebula
import android.content.Context import android.content.Context
import android.util.Log import android.util.Log
import com.google.gson.Gson import com.google.gson.Gson
import com.google.gson.annotations.Expose
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName
import io.flutter.embedding.engine.FlutterEngine import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.EventChannel import io.flutter.plugin.common.EventChannel
import java.io.File import java.io.File
import java.io.FileNotFoundException
import kotlin.collections.HashMap import kotlin.collections.HashMap
data class SiteContainer( data class SiteContainer(

View File

@ -1,5 +1,4 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android">
package="net.defined.mobile_nebula">
<!-- Flutter needs it to communicate with the running application <!-- Flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc. to allow setting breakpoints, to provide hot reload, etc.
--> -->

View File

@ -1,7 +1,7 @@
buildscript { buildscript {
ext { ext {
workVersion = "2.7.1" workVersion = "2.7.1"
kotlinVersion = '1.6.10' kotlinVersion = '1.7.20'
} }
repositories { repositories {
@ -10,7 +10,7 @@ buildscript {
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:7.1.2' classpath 'com.android.tools.build:gradle:7.3.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
} }
} }