Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,5 @@ insert_final_newline = true
indent_size = 2
trim_trailing_whitespace = false

[Makefile]
indent_style = tab
indent_size = 8

[*.{js,json,css,scss,sass,html,handlebars,tpl}]
indent_size = 2
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
name: ${{ matrix.variant }}
runs-on: ubuntu-latest
container:
image: koreader/koandroid:0.9.1-22.04
image: benoitpierre/koandroid:0.10.0-22.04

steps:

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ A good number of Android native API headers are readily presented via FFI alread

Have a look at KOReader's [llapp_main.lua](https://github.com/koreader/koreader/blob/master/platform/android/llapp_main.lua) file. You can use it as a starting point for your own app.

The real starting point, called from JNI/C, is the run() function in android.lua. It sets up a few things, namely FFI definitions for the Android native API (since it uses that itself for a few things) and some wrapper functions for logging. Also, it registers the "android" module in package.loaded, so you can access it in your own code via require("android"). It also registers a new package loader which can load Lua code from the activity's asset store, so you can use require() for Lua code stored there.
The real starting point, called from JNI/C, is the run() function in android.lua. It sets up a few things, namely FFI definitions for the Android native API (since it uses that itself for a few things) and some wrapper functions for logging. Also, it registers the "android" module in `package.loaded`, so you can access it in your own code via require("android"). It also registers a new package loader which can load Lua code from the activity's asset store, so you can use require() for Lua code stored there.

## Disclaimer

Expand Down
57 changes: 31 additions & 26 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'

android {
namespace 'org.koreader.launcher'
ndkVersion '23.2.8568313'
ndkPath System.getenv('ANDROID_NDK_HOME')
compileSdk rootProject.ext.compileSdk
namespace = 'org.koreader.launcher'
ndkVersion = '23.2.8568313'
ndkPath = System.getenv('ANDROID_NDK_HOME')
compileSdk = rootProject.ext.compileSdk
def baseVersionCode = versCode as Integer

aaptOptions {
noCompress '7z'
}

defaultConfig {
applicationId "org.koreader.launcher"
versionName versName
applicationId = "org.koreader.launcher"
versionName = versName
minSdkVersion rootProject.ext.minSdk
targetSdkVersion rootProject.ext.targetSdk

Expand Down Expand Up @@ -45,25 +43,27 @@ android {

buildTypes {
release {
minifyEnabled true
shrinkResources true
minifyEnabled = true
shrinkResources = true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}

debug {
applicationIdSuffix ".debug"
minifyEnabled false
debuggable true
applicationIdSuffix = ".debug"
minifyEnabled = false
debuggable = true
}
}

compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}

kotlinOptions {
jvmTarget = '17'
kotlin {
compilerOptions {
jvmTarget = JvmTarget.JVM_17
}
}

flavorDimensions = [ 'ABI', 'CHANNEL' ]
Expand Down Expand Up @@ -102,7 +102,7 @@ android {

packagingOptions {
jniLibs {
useLegacyPackaging true
useLegacyPackaging = true
}
resources {
excludes += '/kotlin/**.kotlin_builtins'
Expand All @@ -117,14 +117,19 @@ android {
disable 'GradleDependency'
disable 'QueryAllPackagesPermission'
disable 'SameParameterValue'
htmlReport false
xmlReport false
htmlReport = false
xmlReport = false
}
androidResources {
noCompress '7z'
}
}

applicationVariants.configureEach { variant ->
variant.outputs.configureEach {
outputFileName = "NativeActivity.apk"
}
androidComponents {
onVariants(selector().all()) {
outputs.forEach {
it.outputFileName.set("NativeActivity.apk")
}
}
}

Expand Down
4 changes: 3 additions & 1 deletion app/src/debug/res/mipmap-anydpi-v26/icon.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<adaptive-icon xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
tools:ignore="MonochromeLauncherIcon">
<background android:drawable="@color/icon_debug"/>
<foreground android:drawable="@mipmap/icon_foreground"/>
</adaptive-icon>
15 changes: 9 additions & 6 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,23 @@
<!-- common android permissions -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS"
tools:ignore="ProtectedPermissions" />

<!-- legacy storage permissions -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="29" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" android:maxSdkVersion="29" />
<uses-permission android:name="android.permission.WRITE_SETTINGS"
tools:ignore="ProtectedPermissions" />

<!-- These are used on API30+ -->
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
tools:ignore="AllFilesAccessPolicy,ScopedStorage" />
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"
tools:ignore="PackageVisibilityPolicy" />

<application
tools:ignore="DataExtractionRules,DiscouragedApi,NonResizeableActivity"
android:name=".MainApp"
android:icon="@mipmap/icon"
android:banner="@mipmap/banner"
Expand All @@ -41,8 +45,7 @@
android:resizeableActivity="false"
android:screenOrientation="nosensor"
android:launchMode="singleInstance"
android:configChanges="colorMode|density|fontScale|keyboard|keyboardHidden|layoutDirection|locale|mcc|mnc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|touchscreen|uiMode"
tools:ignore="NonResizeableActivity">
android:configChanges="colorMode|density|fontScale|keyboard|keyboardHidden|layoutDirection|locale|mcc|mnc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|touchscreen|uiMode">
<meta-data android:name="android.app.lib_name" android:value="luajit-launcher" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
Expand Down
5 changes: 4 additions & 1 deletion app/src/main/java/org/koreader/launcher/ApkUpdater.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.koreader.launcher

import android.annotation.SuppressLint
import android.app.DownloadManager
import android.content.Context
import android.content.Intent
Expand All @@ -8,6 +9,7 @@ import android.os.Build
import android.util.Log
import androidx.core.content.FileProvider
import java.io.File
import androidx.core.net.toUri

class ApkUpdater {

Expand All @@ -27,7 +29,7 @@ class ApkUpdater {
if (file.exists()) {
DOWNLOAD_EXISTS
} else {
val request = DownloadManager.Request(Uri.parse(url))
val request = DownloadManager.Request(url.toUri())
request.setMimeType("application/vnd.android.package-archive")
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN)
request.setDestinationInExternalFilesDir(context, null, name)
Expand Down Expand Up @@ -56,6 +58,7 @@ class ApkUpdater {
}
}

@SuppressLint("RequestInstallPackagesPolicy")
fun install(context: Context) {
if (MainApp.OTA_UPDATES) {
downloadPath?.let { apk ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ class CrashReportActivity : AppCompatActivity() {
intent?.extras?.let { bundle ->
binding = CrashReportBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.title.text = bundle.get("title").toString()
binding.reason.text = bundle.get("reason").toString()
binding.title.text = bundle.getString("title")
binding.reason.text = bundle.getString("reason")
if (binding.reason.text.equals("")) {
binding.reason.visibility = View.GONE
}
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/java/org/koreader/launcher/LuaInterface.kt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
@file:Suppress("SameReturnValue")

package org.koreader.launcher

import androidx.annotation.WorkerThread
Expand Down
19 changes: 9 additions & 10 deletions app/src/main/java/org/koreader/launcher/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ package org.koreader.launcher

import android.Manifest
import android.annotation.SuppressLint
import android.annotation.TargetApi
import android.app.Activity
import android.app.NativeActivity
import android.content.ClipboardManager
import android.content.ClipData
Expand All @@ -24,9 +22,9 @@ import androidx.core.content.ContextCompat
import org.koreader.launcher.device.Device
import org.koreader.launcher.dialog.LightDialog
import org.koreader.launcher.extensions.*
import java.io.File
import java.util.Locale
import java.util.concurrent.CountDownLatch
import androidx.core.net.toUri

class MainActivity : NativeActivity(), LuaInterface,
ActivityCompat.OnRequestPermissionsResultCallback {
Expand Down Expand Up @@ -178,6 +176,7 @@ class MainActivity : NativeActivity(), LuaInterface,
drawSplashScreen(holder)
}

@SuppressLint("ObsoleteSdkInt")
@RequiresApi(Build.VERSION_CODES.P)
override fun onAttachedToWindow() {
Log.d(TAG_SURFACE, "onAttachedToWindow()")
Expand Down Expand Up @@ -226,9 +225,9 @@ class MainActivity : NativeActivity(), LuaInterface,
}

/* Called on activity result, available from KitKat onwards */
@TargetApi(19)
@RequiresApi(19)
override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
if (requestCode == ACTION_SAF_FILEPICKER_ID && resultCode == Activity.RESULT_OK) {
if (requestCode == ACTION_SAF_FILEPICKER_ID && resultCode == RESULT_OK) {
val importPath = lastImportedPath ?: return
resultData?.let {
val clipData = it.clipData
Expand Down Expand Up @@ -277,7 +276,7 @@ class MainActivity : NativeActivity(), LuaInterface,
@Suppress("NewApi")
override fun canIgnoreBatteryOptimizations(): Boolean {
return if (MainApp.isAtLeastApi(Build.VERSION_CODES.M)) {
val pm = applicationContext.getSystemService(Context.POWER_SERVICE) as PowerManager
val pm = applicationContext.getSystemService(POWER_SERVICE) as PowerManager
pm.isIgnoringBatteryOptimizations(packageName)
} else false
}
Expand Down Expand Up @@ -359,7 +358,7 @@ class MainActivity : NativeActivity(), LuaInterface,
val result = Box<String>()
runOnUiThread {
result.value = try {
val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
val clipboard = getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
val clipData: ClipData? = clipboard.primaryClip
clipData?.getItemAt(0)?.text?.toString()?.trim() ?: ""
} catch (e: Exception) {
Expand Down Expand Up @@ -521,7 +520,7 @@ class MainActivity : NativeActivity(), LuaInterface,
}

override fun hasClipboardText(): Boolean {
val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
val clipboard = getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
return clipboard.primaryClip?.let {
(it.itemCount > 0)
}?: false
Expand Down Expand Up @@ -629,7 +628,7 @@ class MainActivity : NativeActivity(), LuaInterface,
}

override fun openLink(url: String): Boolean {
val webpage = Uri.parse(url)
val webpage = url.toUri()
val intent = Intent(Intent.ACTION_VIEW, webpage)
return try {
startActivity(intent)
Expand Down Expand Up @@ -692,7 +691,7 @@ class MainActivity : NativeActivity(), LuaInterface,

override fun setClipboardText(text: String) {
runOnUiThread {
val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
val clipboard = getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
clipboard.setPrimaryClip(ClipData.newPlainText("KOReader_clipboard", text))
}
}
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/java/org/koreader/launcher/MainApp.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.koreader.launcher

import android.annotation.SuppressLint
import android.app.Application
import android.content.Context
import android.content.Intent
Expand All @@ -10,6 +11,7 @@ import java.io.BufferedReader
import java.io.File
import java.io.InputStreamReader

@Suppress("HasPlatformType")
class MainApp : Application() {
companion object {
const val NAME = BuildConfig.APP_NAME
Expand Down Expand Up @@ -89,6 +91,7 @@ class MainApp : Application() {
}
}

@SuppressLint("DefaultUncaughtExceptionDelegation")
@Suppress("DEPRECATION")
override fun onCreate() {
super.onCreate()
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/java/org/koreader/launcher/TestActivity.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.koreader.launcher

import android.annotation.SuppressLint
import android.graphics.Point
import android.text.method.LinkMovementMethod
import android.util.Log
Expand Down Expand Up @@ -151,6 +152,7 @@ class TestActivity: AppCompatActivity() {
Log.i(tag, MARKER_END)
}

@SuppressLint("DefaultLocale")
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
val msg = String.format("Pressed: %d", keyCode)
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/java/org/koreader/launcher/device/DeviceInfo.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import android.os.Build
import android.util.Log
import java.util.Locale

@Suppress("detekt:all")
@Suppress("detekt:all", "LocalVariableName")
object DeviceInfo {
private const val TAG = "DeviceInfo"

Expand Down Expand Up @@ -509,7 +509,7 @@ object DeviceInfo {
// Onyx Note Air 4C
BRAND == "onyx" && MODEL == "noteair4c"
-> Id.ONYX_NOTE_AIR_4C

// Onyx Note Air 5C
BRAND == "onyx" && MODEL == "noteair5c"
-> Id.ONYX_NOTE_AIR_5C
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/java/org/koreader/launcher/device/EPDFactory.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/* generic EPD Controller for Android devices,
* based on https://github.com/unwmun/refreshU */

@file:Suppress("EmptyMethod")

package org.koreader.launcher.device

import android.util.Log
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/* generic EPD Controller for Android devices,
* based on https://github.com/unwmun/refreshU */

@file:Suppress("EmptyMethod")

package org.koreader.launcher.device

interface EPDInterface {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ abstract class RK30xxEPDController {
init {
try {
@Suppress("UNCHECKED_CAST")
eInkEnum = Class.forName("android.view.View\$EINK_MODE") as Class<Enum<*>>
eInkEnum = Class.forName($$"android.view.View$EINK_MODE") as Class<Enum<*>>
updateEpdMethod = View::class.java.getMethod("requestEpdMode",
eInkEnum, Boolean::class.javaPrimitiveType)
} catch (e: ClassNotFoundException) {
Expand Down
Loading