From 3d32f391e658bdf9bd8fbbb47a5e81f1046d397e Mon Sep 17 00:00:00 2001 From: Brandon Presley Date: Tue, 5 Jul 2022 12:43:04 +1200 Subject: [PATCH] Convert java to kotlin --- android/app/build.gradle | 170 ++---------------- .../main/java/com/massive/AlarmActivity.java | 33 ---- .../main/java/com/massive/AlarmActivity.kt | 28 +++ .../main/java/com/massive/AlarmModule.java | 73 -------- .../src/main/java/com/massive/AlarmModule.kt | 46 +++++ .../main/java/com/massive/AlarmPackage.java | 32 ---- .../src/main/java/com/massive/AlarmPackage.kt | 22 +++ .../main/java/com/massive/AlarmService.java | 60 ------- .../src/main/java/com/massive/AlarmService.kt | 46 +++++ .../main/java/com/massive/MainActivity.java | 48 ----- .../src/main/java/com/massive/MainActivity.kt | 28 +++ .../java/com/massive/MainApplication.java | 92 ---------- .../main/java/com/massive/MainApplication.kt | 72 ++++++++ .../java/com/massive/MyBroadcastReceiver.java | 56 ------ .../java/com/massive/MyBroadcastReceiver.kt | 51 ++++++ .../res/drawable/ic_baseline_timer_24.xml | 5 + android/build.gradle | 4 +- 17 files changed, 314 insertions(+), 552 deletions(-) delete mode 100644 android/app/src/main/java/com/massive/AlarmActivity.java create mode 100644 android/app/src/main/java/com/massive/AlarmActivity.kt delete mode 100644 android/app/src/main/java/com/massive/AlarmModule.java create mode 100644 android/app/src/main/java/com/massive/AlarmModule.kt delete mode 100644 android/app/src/main/java/com/massive/AlarmPackage.java create mode 100644 android/app/src/main/java/com/massive/AlarmPackage.kt delete mode 100644 android/app/src/main/java/com/massive/AlarmService.java create mode 100644 android/app/src/main/java/com/massive/AlarmService.kt delete mode 100644 android/app/src/main/java/com/massive/MainActivity.java create mode 100644 android/app/src/main/java/com/massive/MainActivity.kt delete mode 100644 android/app/src/main/java/com/massive/MainApplication.java create mode 100644 android/app/src/main/java/com/massive/MainApplication.kt delete mode 100644 android/app/src/main/java/com/massive/MyBroadcastReceiver.java create mode 100644 android/app/src/main/java/com/massive/MyBroadcastReceiver.kt create mode 100644 android/app/src/main/res/drawable/ic_baseline_timer_24.xml diff --git a/android/app/build.gradle b/android/app/build.gradle index 461162d..a401803 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -1,82 +1,8 @@ apply plugin: "com.android.application" +apply plugin: "kotlin-android" import com.android.build.OutputFile -/** - * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets - * and bundleReleaseJsAndAssets). - * These basically call `react-native bundle` with the correct arguments during the Android build - * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the - * bundle directly from the development server. Below you can see all the possible configurations - * and their defaults. If you decide to add a configuration block, make sure to add it before the - * `apply from: "../../node_modules/react-native/react.gradle"` line. - * - * project.ext.react = [ - * // the name of the generated asset file containing your JS bundle - * bundleAssetName: "index.android.bundle", - * - * // the entry file for bundle generation. If none specified and - * // "index.android.js" exists, it will be used. Otherwise "index.js" is - * // default. Can be overridden with ENTRY_FILE environment variable. - * entryFile: "index.android.js", - * - * // https://reactnative.dev/docs/performance#enable-the-ram-format - * bundleCommand: "ram-bundle", - * - * // whether to bundle JS and assets in debug mode - * bundleInDebug: false, - * - * // whether to bundle JS and assets in release mode - * bundleInRelease: true, - * - * // whether to bundle JS and assets in another build variant (if configured). - * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants - * // The configuration property can be in the following formats - * // 'bundleIn${productFlavor}${buildType}' - * // 'bundleIn${buildType}' - * // bundleInFreeDebug: true, - * // bundleInPaidRelease: true, - * // bundleInBeta: true, - * - * // whether to disable dev mode in custom build variants (by default only disabled in release) - * // for example: to disable dev mode in the staging build type (if configured) - * devDisabledInStaging: true, - * // The configuration property can be in the following formats - * // 'devDisabledIn${productFlavor}${buildType}' - * // 'devDisabledIn${buildType}' - * - * // the root of your project, i.e. where "package.json" lives - * root: "../../", - * - * // where to put the JS bundle asset in debug mode - * jsBundleDirDebug: "$buildDir/intermediates/assets/debug", - * - * // where to put the JS bundle asset in release mode - * jsBundleDirRelease: "$buildDir/intermediates/assets/release", - * - * // where to put drawable resources / React Native assets, e.g. the ones you use via - * // require('./image.png')), in debug mode - * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug", - * - * // where to put drawable resources / React Native assets, e.g. the ones you use via - * // require('./image.png')), in release mode - * resourcesDirRelease: "$buildDir/intermediates/res/merged/release", - * - * // by default the gradle tasks are skipped if none of the JS files or assets change; this means - * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to - * // date; if you have any other folders that you want to ignore for performance reasons (gradle - * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/ - * // for example, you might want to remove it from here. - * inputExcludes: ["android/**", "ios/**"], - * - * // override which node gets called and with what additional arguments - * nodeExecutableAndArgs: ["node"], - * - * // supply additional arguments to the packager - * extraPackagerArgs: [] - * ] - */ - project.ext.react = [ enableHermes: false, // clean and rebuild if changing ] @@ -84,60 +10,28 @@ project.ext.react = [ apply from: "../../node_modules/react-native/react.gradle" apply from: "../../node_modules/react-native-vector-icons/fonts.gradle" -/** - * Set this to true to create two separate APKs instead of one: - * - An APK that only works on ARM devices - * - An APK that only works on x86 devices - * The advantage is the size of the APK is reduced by about 4MB. - * Upload all the APKs to the Play Store and people will download - * the correct one based on the CPU architecture of their device. - */ def enableSeparateBuildPerCPUArchitecture = false - -/** - * Run Proguard to shrink the Java bytecode in release builds. - */ def enableProguardInReleaseBuilds = false - -/** - * The preferred build flavor of JavaScriptCore. - * - * For example, to use the international variant, you can use: - * `def jscFlavor = 'org.webkit:android-jsc-intl:+'` - * - * The international variant includes ICU i18n library and necessary data - * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that - * give correct results when using with locales other than en-US. Note that - * this variant is about 6MiB larger per architecture than default. - */ def jscFlavor = 'org.webkit:android-jsc:+' - -/** - * Whether to enable the Hermes VM. - * - * This should be set on project.ext.react and that value will be read here. If it is not set - * on project.ext.react, JavaScript will not be compiled to Hermes Bytecode - * and the benefits of using Hermes will therefore be sharply reduced. - */ def enableHermes = project.ext.react.get("enableHermes", false); -/** - * Architectures to build native code for. - */ def reactNativeArchitectures() { def value = project.getProperties().get("reactNativeArchitectures") return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"] } android { + java { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + packagingOptions { - pickFirst '**/armeabi-v7a/libfolly_runtime.so' - pickFirst '**/x86/libfolly_runtime.so' - pickFirst '**/arm64-v8a/libfolly_runtime.so' - pickFirst '**/x86_64/libfolly_runtime.so' + jniLibs { + pickFirsts += ['**/armeabi-v7a/libfolly_runtime.so', '**/x86/libfolly_runtime.so', '**/arm64-v8a/libfolly_runtime.so', '**/x86_64/libfolly_runtime.so'] + } } ndkVersion rootProject.ext.ndkVersion - compileSdkVersion rootProject.ext.compileSdkVersion defaultConfig { @@ -150,7 +44,6 @@ android { buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() if (isNewArchitectureEnabled()) { - // We configure the NDK build only if you decide to opt-in for the New Architecture. externalNativeBuild { ndkBuild { arguments "APP_PLATFORM=android-21", @@ -163,8 +56,6 @@ android { "NODE_MODULES_DIR=$rootDir/../node_modules" cFlags "-Wall", "-Werror", "-fexceptions", "-frtti", "-DWITH_INSPECTOR=1" cppFlags "-std=c++17" - // Make sure this target name is the same you specify inside the - // src/main/jni/Android.mk file for the `LOCAL_MODULE` variable. targets "massive_appmodules" } } @@ -177,7 +68,6 @@ android { } if (isNewArchitectureEnabled()) { - // We configure the NDK build only if you decide to opt-in for the New Architecture. externalNativeBuild { ndkBuild { path "$projectDir/src/main/jni/Android.mk" @@ -195,15 +85,9 @@ android { into("$buildDir/react-ndk/exported") } afterEvaluate { - // If you wish to add a custom TurboModule or component locally, - // you should uncomment this line. - // preBuild.dependsOn("generateCodegenArtifactsFromSchema") preDebugBuild.dependsOn(packageReactNdkDebugLibs) preReleaseBuild.dependsOn(packageReactNdkReleaseLibs) - // Due to a bug inside AGP, we have to explicitly set a dependency - // between configureNdkBuild* tasks and the preBuild tasks. - // This can be removed once this is solved: https://issuetracker.google.com/issues/207403732 configureNdkBuildRelease.dependsOn(preReleaseBuild) configureNdkBuildDebug.dependsOn(preDebugBuild) reactNativeArchitectures().each { architecture -> @@ -221,7 +105,7 @@ android { abi { reset() enable enableSeparateBuildPerCPUArchitecture - universalApk false // If true, also generate a universal APK + universalApk false include (*reactNativeArchitectures()) } } @@ -238,20 +122,14 @@ android { signingConfig signingConfigs.debug } release { - // Caution! In production, you need to generate your own keystore file. - // see https://reactnative.dev/docs/signed-apk-android. signingConfig signingConfigs.debug minifyEnabled enableProguardInReleaseBuilds proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" } } - // applicationVariants are e.g. debug, release applicationVariants.all { variant -> variant.outputs.each { output -> - // For each separate APK per architecture, set a unique version code as described here: - // https://developer.android.com/studio/build/configure-apk-splits.html - // Example: versionCode 1 will generate 1001 for armeabi-v7a, 1002 for x86, etc. def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4] def abi = output.getFilter(OutputFile.ABI) if (abi != null) { // null for the universal-debug, universal-release variants @@ -265,28 +143,16 @@ android { dependencies { def work_version = "2.7.1" - // (Java only) + implementation "androidx.work:work-runtime:$work_version" - - // Kotlin + coroutines implementation "androidx.work:work-runtime-ktx:$work_version" - - // optional - RxJava2 support implementation "androidx.work:work-rxjava2:$work_version" - - // optional - GCMNetworkManager support implementation "androidx.work:work-gcm:$work_version" - - // optional - Test helpers androidTestImplementation "androidx.work:work-testing:$work_version" - // optional - Multiprocess support implementation "androidx.work:work-multiprocess:$work_version" - implementation fileTree(dir: "libs", include: ["*.jar"]) - - //noinspection GradleDynamicVersion implementation "com.facebook.react:react-native:+" // From node_modules - + implementation "androidx.core:core-ktx:1.8.0" implementation project(':react-native-sqlite-storage') implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0" @@ -304,7 +170,6 @@ dependencies { } if (enableHermes) { - //noinspection GradleDynamicVersion implementation("com.facebook.react:hermes-engine:+") { // From node_modules exclude group:'com.facebook.fbjni' } @@ -314,9 +179,6 @@ dependencies { } if (isNewArchitectureEnabled()) { - // If new architecture is enabled, we let you build RN from source - // Otherwise we fallback to a prebuilt .aar bundled in the NPM package. - // This will be applied to all the imported transtitive dependency. configurations.all { resolutionStrategy.dependencySubstitution { substitute(module("com.facebook.react:react-native")) @@ -329,8 +191,6 @@ if (isNewArchitectureEnabled()) { } } -// Run this once to be able to run the application with BUCK -// puts all compile dependencies into folder libs for BUCK to use task copyDownloadableDepsToLibs(type: Copy) { from configurations.implementation into 'libs' @@ -339,9 +199,5 @@ task copyDownloadableDepsToLibs(type: Copy) { apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) def isNewArchitectureEnabled() { - // To opt-in for the New Architecture, you can either: - // - Set `newArchEnabled` to true inside the `gradle.properties` file - // - Invoke gradle with `-newArchEnabled=true` - // - Set an environment variable `ORG_GRADLE_PROJECT_newArchEnabled=true` return project.hasProperty("newArchEnabled") && project.newArchEnabled == "true" -} +} \ No newline at end of file diff --git a/android/app/src/main/java/com/massive/AlarmActivity.java b/android/app/src/main/java/com/massive/AlarmActivity.java deleted file mode 100644 index d346f60..0000000 --- a/android/app/src/main/java/com/massive/AlarmActivity.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.massive; - -import android.app.Activity; -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.util.AttributeSet; -import android.util.Log; -import android.view.View; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -public class AlarmActivity extends Activity { - @Override - protected void onCreate(@Nullable Bundle savedInstanceState) { - Log.d("AlarmActivity", "Call to AlarmActivity"); - super.onCreate(savedInstanceState); - Context context = getApplicationContext(); - context.stopService(new Intent(context, AlarmService.class)); - Intent intent = new Intent(context, MainActivity.class); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - context.startActivity(intent); - } - - @Nullable - @Override - public View onCreateView(@NonNull String name, @NonNull Context context, @NonNull AttributeSet attrs) { - return super.onCreateView(name, context, attrs); - } -} diff --git a/android/app/src/main/java/com/massive/AlarmActivity.kt b/android/app/src/main/java/com/massive/AlarmActivity.kt new file mode 100644 index 0000000..9a89ec9 --- /dev/null +++ b/android/app/src/main/java/com/massive/AlarmActivity.kt @@ -0,0 +1,28 @@ +package com.massive + +import android.app.Activity +import android.content.Context +import android.content.Intent +import android.os.Build +import android.os.Bundle +import android.util.AttributeSet +import android.util.Log +import android.view.View +import android.view.WindowManager +import androidx.annotation.RequiresApi +import com.massive.AlarmService +import com.massive.MainActivity + +class AlarmActivity : Activity() { + @RequiresApi(Build.VERSION_CODES.O_MR1) + override fun onCreate(savedInstanceState: Bundle?) { + Log.d("AlarmActivity", "Call to AlarmActivity") + super.onCreate(savedInstanceState) + val context = applicationContext + context.stopService(Intent(context, AlarmService::class.java)) + savedInstanceState.apply { setShowWhenLocked(true) } + val intent = Intent(context, MainActivity::class.java) + intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK + context.startActivity(intent) + } +} \ No newline at end of file diff --git a/android/app/src/main/java/com/massive/AlarmModule.java b/android/app/src/main/java/com/massive/AlarmModule.java deleted file mode 100644 index adf0d87..0000000 --- a/android/app/src/main/java/com/massive/AlarmModule.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.massive; // replace com.your-app-name with your app’s name - -import static android.content.Context.ALARM_SERVICE; - -import android.app.AlarmManager; -import android.app.Notification; -import android.app.NotificationChannel; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.content.Context; -import android.content.Intent; -import android.media.MediaPlayer; -import android.os.Build; -import android.os.SystemClock; -import android.util.Log; -import android.widget.Toast; - -import androidx.annotation.NonNull; -import androidx.annotation.RequiresApi; -import androidx.core.app.NotificationCompat; -import androidx.core.app.NotificationManagerCompat; -import androidx.work.OneTimeWorkRequest; -import androidx.work.PeriodicWorkRequest; -import androidx.work.WorkManager; -import androidx.work.WorkRequest; - -import com.facebook.react.bridge.NativeModule; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; - -import java.time.Duration; -import java.util.Calendar; -import java.util.Date; -import java.util.Map; -import java.util.HashMap; -import java.util.concurrent.TimeUnit; - -public class AlarmModule extends ReactContextBaseJavaModule { - AlarmModule(ReactApplicationContext context) { - super(context); - } - - @NonNull - @Override - public String getName() { - return "AlarmModule"; - } - - @RequiresApi(api = Build.VERSION_CODES.O) - @ReactMethod() - public void timer(int milliseconds) { - Log.d("AlarmModule", "Queue alarm for " + milliseconds + " delay"); - Intent intent = new Intent(getReactApplicationContext(), MyBroadcastReceiver.class); - PendingIntent pendingIntent = PendingIntent.getBroadcast( - getReactApplicationContext(), 69, intent, PendingIntent.FLAG_IMMUTABLE); - AlarmManager alarmManager = (AlarmManager) getReactApplicationContext().getSystemService(ALARM_SERVICE); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - Log.d("AlarmModule", "Can schedule: " + alarmManager.canScheduleExactAlarms()); - } - AlarmManager.AlarmClockInfo info = new AlarmManager.AlarmClockInfo(System.currentTimeMillis() + milliseconds, pendingIntent); - alarmManager.setAlarmClock(info, pendingIntent); - } - - @ReactMethod(isBlockingSynchronousMethod = true) - public void stop() { - Log.d("AlarmModule", "Request to stop timer."); - Intent intent = new Intent(getReactApplicationContext(), MyBroadcastReceiver.class); - intent.setAction("stop"); - getReactApplicationContext().startActivity(intent); - } -} diff --git a/android/app/src/main/java/com/massive/AlarmModule.kt b/android/app/src/main/java/com/massive/AlarmModule.kt new file mode 100644 index 0000000..f2e4da2 --- /dev/null +++ b/android/app/src/main/java/com/massive/AlarmModule.kt @@ -0,0 +1,46 @@ +package com.massive + +import com.facebook.react.bridge.ReactApplicationContext +import com.facebook.react.bridge.ReactContextBaseJavaModule +import android.app.PendingIntent +import android.app.AlarmManager +import androidx.annotation.RequiresApi +import com.facebook.react.bridge.ReactMethod +import android.content.Intent +import com.massive.MyBroadcastReceiver +import android.app.AlarmManager.AlarmClockInfo +import android.content.Context +import android.os.Build +import android.util.Log + +// replace com.your-app-name with your app’s name +class AlarmModule internal constructor(context: ReactApplicationContext?) : + ReactContextBaseJavaModule(context) { + private var pendingIntent: PendingIntent? = null + private var alarmManager: AlarmManager? = null + override fun getName(): String { + return "AlarmModule" + } + + @RequiresApi(api = Build.VERSION_CODES.O) + @ReactMethod + fun timer(milliseconds: Int) { + Log.d("AlarmModule", "Queue alarm for $milliseconds delay") + val intent = Intent(reactApplicationContext, MyBroadcastReceiver::class.java) + pendingIntent = PendingIntent.getBroadcast( + reactApplicationContext, 69, intent, PendingIntent.FLAG_IMMUTABLE + ) + alarmManager = + reactApplicationContext.getSystemService(Context.ALARM_SERVICE) as AlarmManager + val info = AlarmClockInfo(System.currentTimeMillis() + milliseconds, pendingIntent) + alarmManager!!.setAlarmClock(info, pendingIntent) + + } + + @ReactMethod + fun stop() { + Log.d("AlarmModule", "Request to stop timer.") + alarmManager?.cancel(pendingIntent) + reactApplicationContext.stopService(Intent(reactApplicationContext, AlarmService::class.java)) + } +} \ No newline at end of file diff --git a/android/app/src/main/java/com/massive/AlarmPackage.java b/android/app/src/main/java/com/massive/AlarmPackage.java deleted file mode 100644 index 94812b4..0000000 --- a/android/app/src/main/java/com/massive/AlarmPackage.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.massive; -import androidx.annotation.NonNull; - -import com.facebook.react.ReactPackage; -import com.facebook.react.bridge.NativeModule; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.uimanager.ViewManager; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -public class AlarmPackage implements ReactPackage { - - @NonNull - @Override - public List createViewManagers(@NonNull ReactApplicationContext reactContext) { - return Collections.emptyList(); - } - - @NonNull - @Override - public List createNativeModules( - @NonNull ReactApplicationContext reactContext) { - List modules = new ArrayList<>(); - - modules.add(new AlarmModule(reactContext)); - - return modules; - } - -} diff --git a/android/app/src/main/java/com/massive/AlarmPackage.kt b/android/app/src/main/java/com/massive/AlarmPackage.kt new file mode 100644 index 0000000..7d526f4 --- /dev/null +++ b/android/app/src/main/java/com/massive/AlarmPackage.kt @@ -0,0 +1,22 @@ +package com.massive + +import com.facebook.react.ReactPackage +import com.facebook.react.bridge.NativeModule +import com.facebook.react.bridge.ReactApplicationContext +import com.facebook.react.uimanager.ViewManager +import com.massive.AlarmModule +import java.util.ArrayList + +class AlarmPackage : ReactPackage { + override fun createViewManagers(reactContext: ReactApplicationContext): List> { + return emptyList() + } + + override fun createNativeModules( + reactContext: ReactApplicationContext + ): List { + val modules: MutableList = ArrayList() + modules.add(AlarmModule(reactContext)) + return modules + } +} \ No newline at end of file diff --git a/android/app/src/main/java/com/massive/AlarmService.java b/android/app/src/main/java/com/massive/AlarmService.java deleted file mode 100644 index 188ec92..0000000 --- a/android/app/src/main/java/com/massive/AlarmService.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.massive; -import android.app.Service; -import android.content.Context; -import android.content.Intent; -import android.media.AudioAttributes; -import android.media.MediaPlayer; -import android.os.Build; -import android.os.IBinder; -import android.os.VibrationEffect; -import android.os.Vibrator; -import android.util.Log; - -import androidx.annotation.Nullable; -import androidx.annotation.RequiresApi; - -public class AlarmService extends Service implements MediaPlayer.OnPreparedListener { - private static final String ACTION_PLAY = "com.example.action.PLAY"; - MediaPlayer mediaPlayer = null; - private Vibrator vibrator; - - @RequiresApi(api = Build.VERSION_CODES.O) - public int onStartCommand(Intent intent, int flags, int startId) { - Log.d("AlarmService", "Starting alarm: " + intent.getAction()); - mediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.argon); - mediaPlayer.start(); - mediaPlayer.setOnCompletionListener(mediaPlayer -> vibrator.cancel()); - long[] pattern = {0, 300, 1300, 300, 1300, 300}; - vibrator = (Vibrator) getApplicationContext().getSystemService(Context.VIBRATOR_SERVICE); - AudioAttributes audioAttributes = new AudioAttributes.Builder() - .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) - .setUsage(AudioAttributes.USAGE_ALARM) - .build(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - vibrator.vibrate(VibrationEffect.createWaveform(pattern, 1), audioAttributes); - } else { - vibrator.vibrate(pattern, 1, audioAttributes); - } - return START_STICKY; - } - - @Nullable - @Override - public IBinder onBind(Intent intent) { - return null; - } - - /** Called when MediaPlayer is ready */ - public void onPrepared(MediaPlayer player) { - player.start(); - } - - - - @Override - public void onDestroy() { - super.onDestroy(); - if (mediaPlayer != null) mediaPlayer.release(); - if (vibrator != null) vibrator.cancel(); - } -} diff --git a/android/app/src/main/java/com/massive/AlarmService.kt b/android/app/src/main/java/com/massive/AlarmService.kt new file mode 100644 index 0000000..602da58 --- /dev/null +++ b/android/app/src/main/java/com/massive/AlarmService.kt @@ -0,0 +1,46 @@ +package com.massive + +import android.app.Service +import android.media.MediaPlayer.OnPreparedListener +import android.media.MediaPlayer +import android.os.Vibrator +import androidx.annotation.RequiresApi +import android.content.Intent +import android.media.AudioAttributes +import android.os.Build +import android.os.VibrationEffect +import android.os.IBinder + +class AlarmService : Service(), OnPreparedListener { + var mediaPlayer: MediaPlayer? = null + private var vibrator: Vibrator? = null + + @RequiresApi(api = Build.VERSION_CODES.O) + override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { + mediaPlayer = MediaPlayer.create(applicationContext, R.raw.argon) + mediaPlayer?.start() + mediaPlayer?.setOnCompletionListener { vibrator?.cancel() } + val pattern = longArrayOf(0, 300, 1300, 300, 1300, 300) + vibrator = applicationContext.getSystemService(VIBRATOR_SERVICE) as Vibrator + val audioAttributes = AudioAttributes.Builder() + .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) + .setUsage(AudioAttributes.USAGE_ALARM) + .build() + vibrator!!.vibrate(VibrationEffect.createWaveform(pattern, 1), audioAttributes) + return START_STICKY + } + + override fun onBind(intent: Intent): IBinder? { + return null + } + + override fun onPrepared(player: MediaPlayer) { + player.start() + } + + override fun onDestroy() { + super.onDestroy() + mediaPlayer?.release() + vibrator?.cancel() + } +} \ No newline at end of file diff --git a/android/app/src/main/java/com/massive/MainActivity.java b/android/app/src/main/java/com/massive/MainActivity.java deleted file mode 100644 index a387dc2..0000000 --- a/android/app/src/main/java/com/massive/MainActivity.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.massive; - -import com.facebook.react.ReactActivity; -import com.facebook.react.ReactActivityDelegate; -import com.facebook.react.ReactRootView; - -public class MainActivity extends ReactActivity { - - /** - * Returns the name of the main component registered from JavaScript. This is used to schedule - * rendering of the component. - */ - @Override - protected String getMainComponentName() { - return "massive"; - } - - /** - * Returns the instance of the {@link ReactActivityDelegate}. There the RootView is created and - * you can specify the renderer you wish to use - the new renderer (Fabric) or the old renderer - * (Paper). - */ - @Override - protected ReactActivityDelegate createReactActivityDelegate() { - return new MainActivityDelegate(this, getMainComponentName()); - } - - public static class MainActivityDelegate extends ReactActivityDelegate { - public MainActivityDelegate(ReactActivity activity, String mainComponentName) { - super(activity, mainComponentName); - } - - @Override - protected ReactRootView createRootView() { - ReactRootView reactRootView = new ReactRootView(getContext()); - // If you opted-in for the New Architecture, we enable the Fabric Renderer. - reactRootView.setIsFabric(BuildConfig.IS_NEW_ARCHITECTURE_ENABLED); - return reactRootView; - } - - @Override - protected boolean isConcurrentRootEnabled() { - // If you opted-in for the New Architecture, we enable Concurrent Root (i.e. React 18). - // More on this on https://reactjs.org/blog/2022/03/29/react-v18.html - return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED; - } - } -} diff --git a/android/app/src/main/java/com/massive/MainActivity.kt b/android/app/src/main/java/com/massive/MainActivity.kt new file mode 100644 index 0000000..2c91165 --- /dev/null +++ b/android/app/src/main/java/com/massive/MainActivity.kt @@ -0,0 +1,28 @@ +package com.massive + +import com.facebook.react.ReactActivity +import com.facebook.react.ReactActivityDelegate +import com.facebook.react.ReactRootView + +class MainActivity : ReactActivity() { + override fun getMainComponentName(): String? { + return "massive" + } + + override fun createReactActivityDelegate(): ReactActivityDelegate { + return MainActivityDelegate(this, mainComponentName) + } + + class MainActivityDelegate(activity: ReactActivity?, mainComponentName: String?) : + ReactActivityDelegate(activity, mainComponentName) { + override fun createRootView(): ReactRootView { + val reactRootView = ReactRootView(context) + reactRootView.setIsFabric(BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) + return reactRootView + } + + override fun isConcurrentRootEnabled(): Boolean { + return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED + } + } +} \ No newline at end of file diff --git a/android/app/src/main/java/com/massive/MainApplication.java b/android/app/src/main/java/com/massive/MainApplication.java deleted file mode 100644 index 3c5816b..0000000 --- a/android/app/src/main/java/com/massive/MainApplication.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.massive; - -import android.app.Application; -import android.content.Context; -import com.facebook.react.PackageList; -import com.facebook.react.ReactApplication; -import com.facebook.react.ReactInstanceManager; -import com.facebook.react.ReactNativeHost; -import com.facebook.react.ReactPackage; -import com.facebook.react.config.ReactFeatureFlags; -import com.facebook.soloader.SoLoader; -import com.massive.newarchitecture.MainApplicationReactNativeHost; -import java.lang.reflect.InvocationTargetException; -import java.util.List; -import org.pgsqlite.SQLitePluginPackage; - -public class MainApplication extends Application implements ReactApplication { - - private final ReactNativeHost mReactNativeHost = - new ReactNativeHost(this) { - @Override - public boolean getUseDeveloperSupport() { - return BuildConfig.DEBUG; - } - - @Override - protected List getPackages() { - @SuppressWarnings("UnnecessaryLocalVariable") - List packages = new PackageList(this).getPackages(); - packages.add(new SQLitePluginPackage()); - packages.add(new AlarmPackage()); - return packages; - } - - @Override - protected String getJSMainModuleName() { - return "index"; - } - }; - - private final ReactNativeHost mNewArchitectureNativeHost = - new MainApplicationReactNativeHost(this); - - @Override - public ReactNativeHost getReactNativeHost() { - if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { - return mNewArchitectureNativeHost; - } else { - return mReactNativeHost; - } - } - - @Override - public void onCreate() { - super.onCreate(); - // If you opted-in for the New Architecture, we enable the TurboModule system - ReactFeatureFlags.useTurboModules = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED; - SoLoader.init(this, /* native exopackage */ false); - initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); - } - - /** - * Loads Flipper in React Native templates. Call this in the onCreate method with something like - * initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); - * - * @param context - * @param reactInstanceManager - */ - private static void initializeFlipper( - Context context, ReactInstanceManager reactInstanceManager) { - if (BuildConfig.DEBUG) { - try { - /* - We use reflection here to pick up the class that initializes Flipper, - since Flipper library is not available in release mode - */ - Class aClass = Class.forName("com.massive.ReactNativeFlipper"); - aClass - .getMethod("initializeFlipper", Context.class, ReactInstanceManager.class) - .invoke(null, context, reactInstanceManager); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } - } - } -} diff --git a/android/app/src/main/java/com/massive/MainApplication.kt b/android/app/src/main/java/com/massive/MainApplication.kt new file mode 100644 index 0000000..9dbfc25 --- /dev/null +++ b/android/app/src/main/java/com/massive/MainApplication.kt @@ -0,0 +1,72 @@ +package com.massive + +import android.app.Application +import android.content.Context +import com.facebook.react.* +import com.facebook.react.config.ReactFeatureFlags +import com.facebook.soloader.SoLoader +import com.massive.newarchitecture.MainApplicationReactNativeHost +import org.pgsqlite.SQLitePluginPackage +import java.lang.reflect.InvocationTargetException + +class MainApplication : Application(), ReactApplication { + private val mReactNativeHost: ReactNativeHost = object : ReactNativeHost(this) { + override fun getUseDeveloperSupport(): Boolean { + return BuildConfig.DEBUG + } + + override fun getPackages(): List { + val packages: MutableList = PackageList(this).packages + packages.add(SQLitePluginPackage()) + packages.add(AlarmPackage()) + return packages + } + + override fun getJSMainModuleName(): String { + return "index" + } + } + + private val mNewArchitectureNativeHost: ReactNativeHost = MainApplicationReactNativeHost(this) + override fun getReactNativeHost(): ReactNativeHost { + return if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { + mNewArchitectureNativeHost + } else { + mReactNativeHost + } + } + + override fun onCreate() { + super.onCreate() + ReactFeatureFlags.useTurboModules = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED + SoLoader.init(this, false) + initializeFlipper(this, reactNativeHost.reactInstanceManager) + } + + companion object { + private fun initializeFlipper( + context: Context, reactInstanceManager: ReactInstanceManager + ) { + if (BuildConfig.DEBUG) { + try { + val aClass = Class.forName("com.massive.ReactNativeFlipper") + aClass + .getMethod( + "initializeFlipper", + Context::class.java, + ReactInstanceManager::class.java + ) + .invoke(null, context, reactInstanceManager) + } catch (e: ClassNotFoundException) { + e.printStackTrace() + } catch (e: NoSuchMethodException) { + e.printStackTrace() + } catch (e: IllegalAccessException) { + e.printStackTrace() + } catch (e: InvocationTargetException) { + e.printStackTrace() + } + } + } + } +} \ No newline at end of file diff --git a/android/app/src/main/java/com/massive/MyBroadcastReceiver.java b/android/app/src/main/java/com/massive/MyBroadcastReceiver.java deleted file mode 100644 index 5fcc544..0000000 --- a/android/app/src/main/java/com/massive/MyBroadcastReceiver.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.massive; - -import android.app.NotificationChannel; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.os.Build; -import android.os.VibrationEffect; -import android.os.Vibrator; -import android.util.Log; - -import androidx.annotation.RequiresApi; -import androidx.core.app.NotificationCompat; -import androidx.core.app.NotificationManagerCompat; - -public class MyBroadcastReceiver extends BroadcastReceiver { - private static final String CHANNEL_ID = "MassiveAlarm"; - private static final int ALARM_ID = 59; - - @RequiresApi(api = Build.VERSION_CODES.M) - @Override - public void onReceive(Context context, Intent intent) { - Log.d("MyBroadcastReceiver", "Received intent for BroadcastReceiver."); - String action = intent.getAction(); - Log.d("MyBroadcastReceiver", "Action: " + action); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - int importance = NotificationManager.IMPORTANCE_HIGH; - NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_ID, importance); - channel.setDescription("Alarms for rest timings."); - NotificationManager notificationManager = context.getSystemService(NotificationManager.class); - notificationManager.createNotificationChannel(channel); - } - context.startService(new Intent(context, AlarmService.class)); - Intent contentIntent = new Intent(context.getApplicationContext(), AlarmActivity.class); - PendingIntent pendingContent = PendingIntent.getActivity(context, 0, contentIntent, PendingIntent.FLAG_IMMUTABLE); - long[] pattern = {0, 100, 1000, 200, 2000}; - NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID) - .setSmallIcon(R.drawable.rn_edit_text_material) - .setContentTitle("Rest") - .setContentText("Break times over!") - .setContentIntent(pendingContent) - .setAutoCancel(true) - .setVibrate(pattern) - .setCategory(NotificationCompat.CATEGORY_ALARM) - .setPriority(NotificationCompat.PRIORITY_HIGH); - NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context); - notificationManager.notify(ALARM_ID, builder.build()); - } - - private void vibrate(Context context) { - } -} - - diff --git a/android/app/src/main/java/com/massive/MyBroadcastReceiver.kt b/android/app/src/main/java/com/massive/MyBroadcastReceiver.kt new file mode 100644 index 0000000..b309d1c --- /dev/null +++ b/android/app/src/main/java/com/massive/MyBroadcastReceiver.kt @@ -0,0 +1,51 @@ +package com.massive + +import androidx.annotation.RequiresApi +import android.content.Intent +import android.app.NotificationManager +import android.app.NotificationChannel +import com.massive.MyBroadcastReceiver +import com.massive.AlarmService +import com.massive.AlarmActivity +import android.app.PendingIntent +import android.content.BroadcastReceiver +import android.content.Context +import android.os.Build +import android.util.Log +import androidx.core.app.NotificationCompat +import androidx.core.app.NotificationManagerCompat + +class MyBroadcastReceiver : BroadcastReceiver() { + @RequiresApi(api = Build.VERSION_CODES.M) + override fun onReceive(context: Context, intent: Intent) { + Log.d("MyBroadcastReceiver", "Received intent for BroadcastReceiver.") + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + val importance = NotificationManager.IMPORTANCE_HIGH + val channel = NotificationChannel(CHANNEL_ID, CHANNEL_ID, importance) + channel.description = "Alarms for rest timings." + val notificationManager = context.getSystemService( + NotificationManager::class.java + ) + notificationManager.createNotificationChannel(channel) + } + context.startService(Intent(context, AlarmService::class.java)) + val contentIntent = Intent(context.applicationContext, AlarmActivity::class.java) + val pendingContent = + PendingIntent.getActivity(context, 0, contentIntent, PendingIntent.FLAG_IMMUTABLE) + val builder = NotificationCompat.Builder(context, CHANNEL_ID) + .setSmallIcon(R.drawable.ic_baseline_timer_24) + .setContentTitle("Rest") + .setContentText("Break times over!") + .setContentIntent(pendingContent) + .setAutoCancel(true) + .setCategory(NotificationCompat.CATEGORY_ALARM) + .setPriority(NotificationCompat.PRIORITY_HIGH) + val notificationManager = NotificationManagerCompat.from(context) + notificationManager.notify(ALARM_ID, builder.build()) + } + + companion object { + private const val CHANNEL_ID = "MassiveAlarm" + private const val ALARM_ID = 1 + } +} \ No newline at end of file diff --git a/android/app/src/main/res/drawable/ic_baseline_timer_24.xml b/android/app/src/main/res/drawable/ic_baseline_timer_24.xml new file mode 100644 index 0000000..239205e --- /dev/null +++ b/android/app/src/main/res/drawable/ic_baseline_timer_24.xml @@ -0,0 +1,5 @@ + + + diff --git a/android/build.gradle b/android/build.gradle index c9bc539..7f82bf0 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -4,6 +4,7 @@ import org.apache.tools.ant.taskdefs.condition.Os buildscript { ext { + kotlin_version = '1.6.10' buildToolsVersion = "31.0.0" minSdkVersion = 21 compileSdkVersion = 31 @@ -22,9 +23,10 @@ buildscript { mavenCentral() } dependencies { - classpath("com.android.tools.build:gradle:7.1.1") + classpath('com.android.tools.build:gradle:7.2.1') classpath("com.facebook.react:react-native-gradle-plugin") classpath("de.undercouch:gradle-download-task:5.0.1") + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files }