convert more to kotlin

Signed-off-by: androidacy-user <opensource@androidacy.com>
pull/27/head
androidacy-user 2 years ago
parent 3cf96fef71
commit b20a9fcced

@ -1,115 +1,123 @@
package com.fox2code.mmm.utils; package com.fox2code.mmm.utils
import android.app.Dialog; import android.app.Dialog
import android.content.ActivityNotFoundException; import android.content.ActivityNotFoundException
import android.content.ComponentName; import android.content.ComponentName
import android.content.Context; import android.content.Context
import android.content.Intent; import android.content.DialogInterface
import android.content.pm.PackageManager; import android.content.Intent
import android.content.pm.ResolveInfo; import android.content.pm.PackageManager
import android.net.Uri; import android.net.Uri
import android.os.Bundle; import android.widget.Toast
import android.widget.Toast; import androidx.appcompat.app.AlertDialog
import androidx.core.app.ActivityOptionsCompat
import androidx.core.util.Supplier
import com.fox2code.mmm.Constants
import com.topjohnwu.superuser.internal.UiThreadHandler
import timber.log.Timber
import androidx.appcompat.app.AlertDialog; class ExternalHelper private constructor() {
import androidx.core.app.ActivityOptionsCompat; private var fallback: ComponentName? = null
import androidx.core.util.Supplier; private var label: CharSequence? = null
private var multi = false
import com.fox2code.mmm.Constants; fun refreshHelper(context: Context) {
import com.topjohnwu.superuser.internal.UiThreadHandler; val intent = Intent(
FOX_MMM_OPEN_EXTERNAL,
import java.util.List; Uri.parse("https://very-invalid-prefix-for-testing.androidacy.com")
)
import timber.log.Timber; @Suppress("DEPRECATION") val resolveInfos =
context.packageManager.queryIntentActivities(intent, PackageManager.GET_RESOLVED_FILTER)
public final class ExternalHelper {
public static final ExternalHelper INSTANCE = new ExternalHelper();
private static final boolean TEST_MODE = false;
private static final String FOX_MMM_OPEN_EXTERNAL = "com.fox2code.mmm.utils.intent.action.OPEN_EXTERNAL";
private static final String FOX_MMM_EXTRA_REPO_ID = "extra_repo_id";
private ComponentName fallback;
private CharSequence label;
private boolean multi;
private ExternalHelper() {
}
public void refreshHelper(Context context) {
Intent intent = new Intent(FOX_MMM_OPEN_EXTERNAL, Uri.parse("https://fox2code.com/module.zip"));
List<ResolveInfo> resolveInfos = context.getPackageManager().queryIntentActivities(intent, PackageManager.GET_RESOLVED_FILTER);
if (resolveInfos.isEmpty()) { if (resolveInfos.isEmpty()) {
Timber.i("No external provider installed!"); Timber.i("No external provider installed!")
label = TEST_MODE ? "External" : null; label = if (TEST_MODE) "External" else null
multi = TEST_MODE; multi = TEST_MODE
fallback = null; fallback = null
} else { } else {
ResolveInfo resolveInfo = resolveInfos.get(0); val resolveInfo = resolveInfos[0]
Timber.i("Found external provider: %s", resolveInfo.activityInfo.packageName); Timber.i("Found external provider: %s", resolveInfo.activityInfo.packageName)
fallback = new ComponentName(resolveInfo.activityInfo.packageName, resolveInfo.activityInfo.name); fallback =
label = resolveInfo.loadLabel(context.getPackageManager()); ComponentName(resolveInfo.activityInfo.packageName, resolveInfo.activityInfo.name)
multi = resolveInfos.size() >= 2; label = resolveInfo.loadLabel(context.packageManager)
multi = resolveInfos.size >= 2
} }
} }
public boolean openExternal(Context context, Uri uri, String repoId) { fun openExternal(context: Context, uri: Uri?, repoId: String?): Boolean {
if (label == null) if (label == null) return false
return false; val param =
Bundle param = ActivityOptionsCompat.makeCustomAnimation(context, android.R.anim.fade_in, android.R.anim.fade_out).toBundle(); ActivityOptionsCompat.makeCustomAnimation(context, com.google.android.material.R.anim.abc_fade_in, com.google.android.material.R.anim.abc_fade_out).toBundle()
Intent intent = new Intent(FOX_MMM_OPEN_EXTERNAL, uri); var intent = Intent(FOX_MMM_OPEN_EXTERNAL, uri)
intent.setFlags(IntentHelper.FLAG_GRANT_URI_PERMISSION); intent.flags = IntentHelper.FLAG_GRANT_URI_PERMISSION
intent.putExtra(FOX_MMM_EXTRA_REPO_ID, repoId); intent.putExtra(FOX_MMM_EXTRA_REPO_ID, repoId)
if (multi) { if (multi) {
intent = Intent.createChooser(intent, label); intent = Intent.createChooser(intent, label)
} else { } else {
intent.putExtra(Constants.EXTRA_FADE_OUT, true); intent.putExtra(Constants.EXTRA_FADE_OUT, true)
} }
try { try {
if (multi) { if (multi) {
context.startActivity(intent); context.startActivity(intent)
} else { } else {
context.startActivity(intent, param); context.startActivity(intent, param)
} }
return true; return true
} catch ( } catch (e: ActivityNotFoundException) {
ActivityNotFoundException e) { Timber.e(e)
Timber.e(e);
} }
if (fallback != null) { if (fallback != null) {
if (multi) { if (multi) {
intent = new Intent(FOX_MMM_OPEN_EXTERNAL, uri); intent = Intent(FOX_MMM_OPEN_EXTERNAL, uri)
intent.putExtra(FOX_MMM_EXTRA_REPO_ID, repoId); intent.putExtra(FOX_MMM_EXTRA_REPO_ID, repoId)
intent.putExtra(Constants.EXTRA_FADE_OUT, true); intent.putExtra(Constants.EXTRA_FADE_OUT, true)
} }
intent.setComponent(fallback); intent.component = fallback
try { try {
context.startActivity(intent, param); context.startActivity(intent, param)
return true; return true
} catch ( } catch (e: ActivityNotFoundException) {
ActivityNotFoundException e) { Timber.e(e)
Timber.e(e);
} }
} }
return false; return false
} }
public void injectButton(AlertDialog.Builder builder, Supplier<Uri> uriSupplier, String repoId) { fun injectButton(builder: AlertDialog.Builder, uriSupplier: Supplier<Uri?>, repoId: String?) {
if (label == null) if (label == null) return
return; builder.setNeutralButton(label) { dialog: DialogInterface, _: Int ->
builder.setNeutralButton(label, (dialog, button) -> { val context = (dialog as Dialog).context
Context context = ((Dialog) dialog).getContext(); object : Thread("Async downloader") {
new Thread("Async downloader") { override fun run() {
@Override val uri = uriSupplier.get()
public void run() { if (uri == null) {
final Uri uri = uriSupplier.get(); UiThreadHandler.run {
if (uri == null) Toast.makeText(
return; context,
UiThreadHandler.run(() -> { "Failed to get uri",
Toast.LENGTH_SHORT
).show()
}
return
}
UiThreadHandler.run {
if (!openExternal(context, uri, repoId)) { if (!openExternal(context, uri, repoId)) {
Toast.makeText(context, "Failed to launch external activity", Toast.LENGTH_SHORT).show(); Toast.makeText(
context,
"Failed to launch external activity",
Toast.LENGTH_SHORT
).show()
}
} }
});
} }
}.start(); }.start()
}); }
}
companion object {
@JvmField
val INSTANCE = ExternalHelper()
private const val TEST_MODE = false
private const val FOX_MMM_OPEN_EXTERNAL =
"com.fox2code.mmm.utils.intent.action.OPEN_EXTERNAL"
private const val FOX_MMM_EXTRA_REPO_ID = "extra_repo_id"
} }
} }

@ -1,15 +1,13 @@
package com.fox2code.mmm.utils; package com.fox2code.mmm.utils
import androidx.annotation.NonNull; class FastException private constructor() : RuntimeException() {
@Synchronized
public final class FastException extends RuntimeException { override fun fillInStackTrace(): Throwable {
public static final FastException INSTANCE = new FastException(); return this
}
private FastException() {}
@NonNull companion object {
@Override @JvmField
public synchronized Throwable fillInStackTrace() { val INSTANCE = FastException()
return this;
} }
} }

@ -1,25 +1,29 @@
package com.fox2code.mmm.utils; package com.fox2code.mmm.utils
import android.app.AlarmManager; import android.app.AlarmManager
import android.app.PendingIntent; import android.app.PendingIntent
import android.content.Context; import android.content.Context
import android.content.Intent; import android.content.Intent
import com.fox2code.mmm.MainActivity
import java.util.concurrent.ThreadLocalRandom
import kotlin.system.exitProcess
import com.fox2code.mmm.MainActivity; enum class ProcessHelper {
import java.util.concurrent.ThreadLocalRandom;
public enum ProcessHelper {
; ;
private static final int sPendingIntentId = ThreadLocalRandom.current().nextInt(100, 1000000 + 1);
public static void restartApplicationProcess(Context context) { companion object {
Intent mStartActivity = new Intent(context, MainActivity.class); private val sPendingIntentId = ThreadLocalRandom.current().nextInt(100, 1000000 + 1)
mStartActivity.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); @JvmStatic
PendingIntent mPendingIntent = PendingIntent.getActivity(context, sPendingIntentId, fun restartApplicationProcess(context: Context) {
mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE); val mStartActivity = Intent(context, MainActivity::class.java)
AlarmManager mgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); mStartActivity.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent); val mPendingIntent = PendingIntent.getActivity(
System.exit(0); // Exit app process context, sPendingIntentId,
mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
val mgr = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
mgr[AlarmManager.RTC, System.currentTimeMillis() + 100] = mPendingIntent
exitProcess(0) // Exit app process
}
} }
} }

@ -1,79 +1,76 @@
package com.fox2code.mmm.utils; package com.fox2code.mmm.utils
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
/** /**
* Manager that want both to be thread safe and not to worry about thread safety * Manager that want both to be thread safe and not to worry about thread safety
* {@link #scan()} and {@link #update(UpdateListener)} can be called from multiple * [.scan] and [.update] can be called from multiple
* thread at the same time, {@link #scanInternal(UpdateListener)} will only be * thread at the same time, [.scanInternal] will only be
* called from one thread at a time only. * called from one thread at a time only.
*/ */
public abstract class SyncManager { abstract class SyncManager {
private static final UpdateListener NO_OP = value -> {}; @JvmField
protected final Object syncLock = new Object(); protected val syncLock = Any()
private boolean syncing; private var syncing = false
private long lastSync; private var lastSync: Long = 0
fun scanAsync() {
public final void scanAsync() { if (!syncing) {
if (!this.syncing) { Thread({ this.scan() }, "Scan Thread").start()
new Thread(this::scan, "Scan Thread").start();
} }
} }
public final void scan() { fun scan() {
this.update(null); update(null)
} }
// MultiThread friendly method // MultiThread friendly method
public final void update(@Nullable UpdateListener updateListener) { fun update(updateListener: UpdateListener?) {
if (updateListener == null) updateListener = NO_OP; @Suppress("NAME_SHADOWING") var updateListener = updateListener
if (!this.syncing) { if (updateListener == null) updateListener = NO_OP
if (!syncing) {
// Do scan // Do scan
synchronized (this.syncLock) { synchronized(syncLock) {
if (System.currentTimeMillis() < this.lastSync + 50L) if (System.currentTimeMillis() < lastSync + 50L) return // Skip sync if it was synced too recently
return; // Skip sync if it was synced too recently syncing = true
this.syncing = true;
try { try {
this.scanInternal(updateListener); scanInternal(updateListener)
} finally { } finally {
this.lastSync = System.currentTimeMillis(); lastSync = System.currentTimeMillis()
this.syncing = false; syncing = false
} }
} }
} else { } else {
// Wait for current scan // Wait for current scan
synchronized (this.syncLock) { synchronized(syncLock) { Thread.yield() }
Thread.yield();
}
} }
} }
// Pause execution until the scan is completed if one is currently running // Pause execution until the scan is completed if one is currently running
public final void afterScan() { fun afterScan() {
if (this.syncing) synchronized (this.syncLock) { Thread.yield(); } if (syncing) synchronized(syncLock) { Thread.yield() }
} }
public final void runAfterScan(Runnable runnable) { fun runAfterScan(runnable: Runnable) {
synchronized (this.syncLock) { synchronized(syncLock) { runnable.run() }
runnable.run();
}
} }
public final void afterUpdate() { fun afterUpdate() {
if (this.syncing) synchronized (this.syncLock) { Thread.yield(); } if (syncing) synchronized(syncLock) { Thread.yield() }
} }
public final void runAfterUpdate(Runnable runnable) { fun runAfterUpdate(runnable: Runnable) {
synchronized (this.syncLock) { synchronized(syncLock) { runnable.run() }
runnable.run();
}
} }
// This method can't be called twice at the same time. // This method can't be called twice at the same time.
protected abstract void scanInternal(@NonNull UpdateListener updateListener); protected abstract fun scanInternal(updateListener: UpdateListener)
interface UpdateListener {
fun update(value: Double)
}
companion object {
private val NO_OP: UpdateListener = object : UpdateListener {
override fun update(value: Double) {
public interface UpdateListener { }
void update(double value); }
} }
} }
Loading…
Cancel
Save