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
50 changes: 50 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Devcontainer image for building the Android app.
FROM mcr.microsoft.com/devcontainers/java

USER root

# Android SDK locations
ENV ANDROID_PLATFORM=android-36
ENV ANDROID_BUILD_TOOLS=36.0.0
ENV ANDROID_SDK_ROOT=/opt/android-sdk
ENV ANDROID_HOME=/opt/android-sdk
ENV ANDROID_CMDLINE_TOOLS_ROOT=/opt/android-sdk/cmdline-tools/latest
ENV PATH=${PATH}:${ANDROID_CMDLINE_TOOLS_ROOT}/bin:${ANDROID_HOME}/platform-tools

# Remove broken/optional third-party apt sources that may be present in the base image/features
RUN rm -f /etc/apt/sources.list.d/yarn.list \
/etc/apt/sources.list.d/yarn*.list \
/etc/apt/sources.list.d/archive_uri-https_dl_yarnpkg_com_debian-bookworm.list || true

# Install packages required for Android/Gradle workflows
RUN apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
curl \
unzip \
ca-certificates \
git \
bash \
libc6 \
libstdc++6 \
libgcc1 \
libbz2-1.0 \
libncurses6 \
zlib1g \
# && uv tool install specify-cli --from git+https://github.com/github/spec-kit.git \
&& rm -rf /var/lib/apt/lists/*

# Install Android command line tools
RUN mkdir -p ${ANDROID_HOME}/cmdline-tools \
&& curl -fsSL https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip -o /tmp/cmdline-tools.zip \
&& mkdir -p /tmp/android-cmdline-tools \
&& unzip -q /tmp/cmdline-tools.zip -d /tmp/android-cmdline-tools \
&& mv /tmp/android-cmdline-tools/cmdline-tools ${ANDROID_HOME}/cmdline-tools/latest \
&& rm -rf /tmp/cmdline-tools.zip /tmp/android-cmdline-tools \
&& chown -R vscode:vscode ${ANDROID_HOME}

# Accept licenses and install commonly needed Android SDK components
RUN yes | sdkmanager --sdk_root=${ANDROID_HOME} --licenses > /dev/null || true \
&& sdkmanager --sdk_root=${ANDROID_HOME} \
"platform-tools" \
"build-tools;${ANDROID_BUILD_TOOLS}" \
"platforms;${ANDROID_PLATFORM}"
44 changes: 44 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"name": "Kotlin Multiplatform Development",
"build": {
"dockerfile": "Dockerfile"
},
"features": {
"ghcr.io/devcontainers/features/git:1": {},
"ghcr.io/devcontainers/features/java:1": {
"version": "25",
"installGradle": "true",
"gradleVersion": "9.4"
},
"ghcr.io/devcontainers-extra/features/uv:1": {
"version": "latest"
}
},
"customizations": {
"vscode": {
"settings": {
"java.import.generatesMetadataFilesAtProjectRoot": false,
"java.import.gradle.wrapper.enabled": true,
"kotlin.languageServer.enabled": true,
"editor.formatOnSave": true,
"files.exclude": {
"**/.gradle": true,
"**/build": true
}
},
"extensions": [
"fwcd.kotlin",
"vscjava.vscode-java-pack",
"vscjava.vscode-gradle",
"redhat.vscode-yaml",
"GitHub.copilot"
]
}
},
"containerEnv": {
"ANDROID_HOME": "/opt/android-sdk",
"ANDROID_SDK_ROOT": "/opt/android-sdk"
},
// "postCreateCommand": "bash -lc 'uv tool install specify-cli --from git+https://github.com/github/spec-kit.git && gradle --version'",
"remoteUser": "vscode" // More info: https://aka.ms/dev-containers-non-root.
}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ build
gen
out
.externalNativeBuild
.kotlin

# Mac
.DS_Store
Expand Down
14 changes: 14 additions & 0 deletions .vscode/Joshua.code-workspace
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"folders": [
{
"path": ".."
}
],
"settings": {
"chat.tools.terminal.autoApprove": {
"gradle": true,
"./gradlew": true,
".\\gradlew.bat": true
}
}
}
20 changes: 14 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,20 @@
[![API](https://img.shields.io/badge/API-19%2B-blue.svg?style=flat)](https://www.android.com/versions/kit-kat-4-4/)
[![Apache License](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg?style=flat)](https://www.apache.org/licenses/LICENSE-2.0)

This project was forked [here](https://github.com/danzuep/Joshua) after the [original](https://github.com/xizzhu/Joshua) appears to have been abandoned. My goal was to work with the [WEB](https://ebible.org/engwebu/MRK01.htm) translator to create a [FOSS](https://f-droid.org/) app for the many public domain licenced works he has, but as this is my first time using Kotlin that may be unrealistic. So far I've updated the project from JDK 11 to build in a JDK 25 devcontainer, and gotten all the unit tests to pass again.

Joshua
======

A simple and easy-to-use Bible reader for your Android device, with minimalist design. It supports offline reading, multi-versions, full-text search, and many other features, while maintaining a small download and install size.
A simple and easy-to-use Bible reader for your Android device, with minimalist design. It supports offline reading, multi-versions, full-text search, and many other features, while maintaining a small download and install size.

You can download the APK from [Play Store](https://play.google.com/store/apps/details?id=me.xizzhu.android.joshua) or [here](https://github.com/xizzhu/Joshua/releases). Recent changes are listed [here](docs/CHANGELOG.md). Feel free to request new features or report bugs [here](https://github.com/xizzhu/Joshua/issues).
You can download the APK from [GitHub](https://github.com/danzuep/Joshua/releases). Recent changes are listed [here](docs/CHANGELOG.md). Feel free to request new features or report bugs [here](https://github.com/danzuep/Joshua/issues).


A simple and easy-to-use Bible reader for your Android device, with minimalist design. It supports offline reading, multi-versions, full-text search, and many other features, while maintaining a small download and install size.

~~You can download the APK from [Play Store](https://play.google.com/store/apps/details?id=me.xizzhu.android.joshua) or [here](https://github.com/xizzhu/Joshua/releases). Recent changes are listed [here](docs/CHANGELOG.md). Feel free to request new features or report bugs [here](https://github.com/xizzhu/Joshua/issues).~~

Main Features
-------------
Expand All @@ -27,11 +35,11 @@ Main Features

We currently support tens of different translations, with more added regularly. A full list of available translations can be found [here](docs/TRANSLATIONS.md).

Donations
---------
If you would like to support this project, feel free to donate. Your support is highly appreciated. Thank you!
* [PayPal](https://paypal.me/xizzhu)
* [Venmo](https://www.venmo.com/u/xizzhu)
~~Donations~~
~~---------~~
~~If you would like to support this project, feel free to donate. Your support is highly appreciated. Thank you!~~
~~* [PayPal](https://paypal.me/xizzhu)~~
~~* [Venmo](https://www.venmo.com/u/xizzhu)~~

License
-------
Expand Down
72 changes: 26 additions & 46 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,10 @@ import java.util.Properties

plugins {
id("com.android.application")
id("com.google.firebase.crashlytics")
id("com.google.gms.google-services")
//id("com.google.firebase.crashlytics")
//id("com.google.gms.google-services")
id(Dependencies.Kotlin.Ksp.plugin)
id(Dependencies.Hilt.plugin)
kotlin("android")
kotlin("kapt")
}

android {
Expand All @@ -32,8 +31,10 @@ android {
sourceCompatibility = Versions.java
targetCompatibility = Versions.java
}
kotlinOptions {
jvmTarget = Versions.Kotlin.jvmTarget
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
compilerOptions {
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.fromTarget(Versions.Kotlin.jvmTarget))
}
}

buildToolsVersion = Versions.Sdk.buildTools
Expand All @@ -48,21 +49,19 @@ android {
versionCode = Versions.App.code
versionName = Versions.App.name

multiDexEnabled = true

resourceConfigurations.addAll(Configurations.supportedLocales)
androidResources.localeFilters.addAll(Configurations.supportedLocales)
}

buildFeatures {
viewBinding = true
buildConfig = true
}

sourceSets {
getByName("main").java.srcDirs("src/main/kotlin")
getByName("debug").java.srcDirs("src/debug/kotlin")
getByName("release").java.srcDirs("src/release/kotlin")

getByName("test").java.srcDirs("src/test/kotlin")
getByName("main") { java.setSrcDirs(setOf("src/main/kotlin")) }
getByName("debug") { java.setSrcDirs(setOf("src/debug/kotlin")) }
getByName("release") { java.setSrcDirs(setOf("src/release/kotlin")) }
getByName("test") { java.setSrcDirs(setOf("src/test/kotlin")) }
}

signingConfigs {
Expand All @@ -81,18 +80,23 @@ android {
}

buildTypes {
getByName("release") {
release {
isMinifyEnabled = true
isShrinkResources = true
signingConfig = signingConfigs.getByName("release")
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
}
getByName("debug") {
debug {
applicationIdSuffix = ".debug"
versionNameSuffix = " debug"
}
}

compileOptions {
sourceCompatibility = Versions.java
targetCompatibility = Versions.java
}

testOptions {
unitTests.isIncludeAndroidResources = true
unitTests.isReturnDefaultValues = true
Expand All @@ -102,31 +106,14 @@ android {
}
}

packagingOptions {
resources.excludes.addAll(listOf(
"META-INF/atomicfu.kotlin_module", "META-INF/AL2.0", "META-INF/LGPL2.1", "META-INF/licenses/*",

// https://github.com/Kotlin/kotlinx.coroutines/tree/master/kotlinx-coroutines-debug#debug-agent-and-android
"win32-x86/attach_hotspot_windows.dll", "win32-x86-64/attach_hotspot_windows.dll"
))
}
}

// allow references to generated code
kapt {
correctErrorTypes = true
}

tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
kotlinOptions {
jvmTarget = Versions.Kotlin.jvmTarget
packaging {
resources.excludes.add("**/NOTNOTICE")
jniLibs.excludes.add("**/libshared.so")
}
}

dependencies {
implementation(Dependencies.Kotlin.coroutines)

debugImplementation(Dependencies.AndroidX.multidex)
implementation(Dependencies.AndroidX.activity)
implementation(Dependencies.AndroidX.annotation)
implementation(Dependencies.AndroidX.appCompat)
Expand All @@ -147,26 +134,19 @@ dependencies {
releaseImplementation(Dependencies.Firebase.Crashlytics.crashlytics)

implementation(Dependencies.Hilt.android)
kapt(Dependencies.Hilt.compiler)
ksp(Dependencies.Hilt.compiler)

implementation(Dependencies.ask)
implementation(Dependencies.logger)
implementation(Dependencies.kermit)
implementation(Dependencies.materialComponent)

testImplementation(Dependencies.Kotlin.test)
testImplementation(Dependencies.Kotlin.coroutinesTest)
testImplementation(Dependencies.Kotlin.reflect)
debugImplementation(Dependencies.AndroidX.Fragment.test)
testImplementation(Dependencies.AndroidX.Test.core)
testImplementation("androidx.test.ext:junit:1.1.4")
kaptTest(Dependencies.Hilt.compiler)
testImplementation(Dependencies.AndroidX.Test.junit)
testImplementation(Dependencies.Hilt.test)
testImplementation(Dependencies.mockk)
testImplementation(Dependencies.robolectric)
}

kover {
instrumentation {
excludeTasks.add("testDebugUnitTest")
}
}
12 changes: 8 additions & 4 deletions app/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
# Crashlytics
# https://firebase.google.com/docs/crashlytics/get-deobfuscated-reports?platform=android
-keepattributes SourceFile,LineNumberTable
-keep public class * extends java.lang.Exception

# Add project-specific ProGuard rules here.
# By default, the flags are kept minimal.

## Crashlytics
## https://firebase.google.com/docs/crashlytics/get-deobfuscated-reports?platform=android
#-keepattributes SourceFile,LineNumberTable
#-keep public class * extends java.lang.Exception
19 changes: 12 additions & 7 deletions app/src/debug/kotlin/me/xizzhu/android/joshua/App.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,24 @@

package me.xizzhu.android.joshua

import android.app.Application
import android.os.StrictMode
import androidx.annotation.CallSuper
import androidx.multidex.MultiDexApplication
import me.xizzhu.android.logger.Log
import me.xizzhu.android.logger.LogcatLogger
import co.touchlab.kermit.Logger

abstract class BaseApp : MultiDexApplication() {
abstract class BaseApp : Application() {
@CallSuper
override fun onCreate() {
super.onCreate()

StrictMode.enableDefaults()

Log.addLogger(LogcatLogger())
setupGlobalLogger()
}
}

fun setupGlobalLogger() {
// Configure the global logger instance
Logger.setLogWriters(co.touchlab.kermit.platformLogWriter())

// Set an optional default tag for the global logger
Logger.withTag("Joshua")
}
7 changes: 6 additions & 1 deletion app/src/main/kotlin/me/xizzhu/android/joshua/Navigator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import android.app.Activity
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.annotation.IntDef
import me.xizzhu.android.joshua.annotated.bookmarks.BookmarksActivity
import me.xizzhu.android.joshua.annotated.highlights.HighlightsActivity
Expand Down Expand Up @@ -74,6 +75,10 @@ class Navigator {
}

fun goBack(activity: Activity) {
activity.finish()
if (activity is ComponentActivity) {
activity.onBackPressedDispatcher.onBackPressed()
} else {
activity.finish()
}
}
}
Loading