mirror of
https://gitee.com/zhangsken/AndroidIDE.git
synced 2026-10-16 07:49:44 +08:00
refactor: rewrite logsender-api and logsender-sample in Java to avoid Kotlin dependencies
This commit is contained in:
@@ -99,10 +99,10 @@ import com.itsaky.androidide.viewmodel.EditorViewModel
|
||||
import com.itsaky.androidide.xml.resources.ResourceTableRegistry
|
||||
import com.itsaky.androidide.xml.versions.ApiVersionsRegistry
|
||||
import com.itsaky.androidide.xml.widgets.WidgetTableRegistry
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode.MAIN
|
||||
import java.io.File
|
||||
import java.util.Objects
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode.MAIN
|
||||
|
||||
/**
|
||||
* Base class for EditorActivity which handles most of the view related things.
|
||||
|
||||
@@ -34,8 +34,7 @@ class LogReceiverService : Service() {
|
||||
private val binder = LogReceiverImpl()
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
internal val LOOKUP_KEY = Lookup.Key<LogReceiverService>()
|
||||
@JvmStatic internal val LOOKUP_KEY = Lookup.Key<LogReceiverService>()
|
||||
}
|
||||
|
||||
override fun onCreate() {
|
||||
@@ -60,6 +59,6 @@ class LogReceiverService : Service() {
|
||||
}
|
||||
}
|
||||
|
||||
fun lookupLogService() : LogReceiverService? {
|
||||
fun lookupLogService(): LogReceiverService? {
|
||||
return Lookup.DEFAULT.lookup(LogReceiverService.LOOKUP_KEY)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
plugins {
|
||||
id("com.android.library")
|
||||
id("kotlin-android")
|
||||
}
|
||||
|
||||
android {
|
||||
@@ -28,7 +27,6 @@ android {
|
||||
dependencies {
|
||||
implementation(projects.logger)
|
||||
|
||||
implementation(libs.androidx.ktx)
|
||||
implementation(libs.google.material)
|
||||
implementation(libs.androidx.appcompat)
|
||||
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* This file is part of AndroidIDE.
|
||||
*
|
||||
* AndroidIDE is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AndroidIDE is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.logsender;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.IBinder;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteException;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.itsaky.androidide.logsender.utils.LogReader;
|
||||
import com.itsaky.androidide.logsender.utils.Logger;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* Entry point for LogSender.
|
||||
*
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
public class LogSender extends ILogSender.Stub implements ServiceConnection {
|
||||
|
||||
@NonNull
|
||||
private final AtomicBoolean installed = new AtomicBoolean(false);
|
||||
|
||||
@Nullable
|
||||
private LogReader reader;
|
||||
|
||||
@Nullable
|
||||
private ILogReceiver receiver;
|
||||
|
||||
@Nullable
|
||||
private String packageName;
|
||||
|
||||
public static final LogSender INSTANCE = new LogSender();
|
||||
|
||||
/**
|
||||
* Action for the LogSender service.
|
||||
*/
|
||||
public static final String SERVICE_ACTION = "com.itsaky.androidide.LOG_SERVICE_ACTION";
|
||||
|
||||
/**
|
||||
* Constant used to indicate that the package name of the application cannot be determined.
|
||||
*/
|
||||
public static final String PACKAGE_UNKNOWN = "<unknown-package-name>";
|
||||
|
||||
/**
|
||||
* AndroidIDE's package name.
|
||||
*/
|
||||
private static final String PACKAGE_ANDROIDIDE = "com.itsaky.androidide";
|
||||
|
||||
private LogSender() {
|
||||
}
|
||||
|
||||
public static void install(Application app) {
|
||||
INSTANCE.doInstall(app);
|
||||
}
|
||||
|
||||
private void doInstall(Application app) {
|
||||
if (installed.get()) {
|
||||
Logger.warn("LogSender is already installed");
|
||||
return;
|
||||
}
|
||||
|
||||
this.packageName = app.getPackageName();
|
||||
if (PACKAGE_ANDROIDIDE.equals(packageName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final var intent = new Intent(SERVICE_ACTION);
|
||||
intent.setPackage(PACKAGE_ANDROIDIDE);
|
||||
if (app.bindService(intent, this, 0)) {
|
||||
Logger.info("Binding to log receiver");
|
||||
installed.set(true);
|
||||
} else {
|
||||
Logger.error("Failed to bind to log receiver");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
this.receiver = ILogReceiver.Stub.asInterface(service);
|
||||
if (this.receiver == null) {
|
||||
throw new IllegalStateException("Failed to get log receiver instance");
|
||||
}
|
||||
|
||||
try {
|
||||
this.receiver.connect(this);
|
||||
Logger.info("Connecting to log receiver");
|
||||
} catch (RemoteException e) {
|
||||
Logger.error("Failed to connect to log receiver", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
Logger.info("Disconnected from log receiver");
|
||||
if (this.reader != null) {
|
||||
this.reader.interrupt();
|
||||
}
|
||||
this.receiver = null;
|
||||
this.reader = null;
|
||||
this.installed.set(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startReader() {
|
||||
if (reader != null && reader.isAlive()) {
|
||||
Logger.warn("LogReader has already been started");
|
||||
return;
|
||||
}
|
||||
|
||||
reader = new LogReader(this::doLog);
|
||||
reader.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPid() {
|
||||
return Process.myPid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPackageName() {
|
||||
if (this.packageName == null) {
|
||||
return PACKAGE_UNKNOWN;
|
||||
}
|
||||
|
||||
return this.packageName;
|
||||
}
|
||||
|
||||
private void doLog(String line) {
|
||||
try {
|
||||
if (line != null && receiver != null) {
|
||||
receiver.onLog(line);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
/*
|
||||
* This file is part of AndroidIDE.
|
||||
*
|
||||
* AndroidIDE is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AndroidIDE is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.logsender
|
||||
|
||||
import android.app.Application
|
||||
import android.content.ComponentName
|
||||
import android.content.Intent
|
||||
import android.content.ServiceConnection
|
||||
import android.os.IBinder
|
||||
import android.os.Process
|
||||
import com.itsaky.androidide.logsender.utils.LogReader
|
||||
import com.itsaky.androidide.logsender.utils.error
|
||||
import com.itsaky.androidide.logsender.utils.info
|
||||
import com.itsaky.androidide.logsender.utils.warn
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
/**
|
||||
* Entry point for LogSender.
|
||||
*
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
object LogSender : ILogSender.Stub(), ServiceConnection {
|
||||
|
||||
private var installed = AtomicBoolean(false)
|
||||
private var reader: LogReader? = null
|
||||
private var receiver: ILogReceiver? = null
|
||||
private var packageName: String? = null
|
||||
|
||||
/** Action for the LogSender service. */
|
||||
const val SERVICE_ACTION = "com.itsaky.androidide.LOG_SERVICE_ACTION"
|
||||
|
||||
/** Constant used to indicate that the package name of the application cannot be determined. */
|
||||
const val PACKAGE_UNKNOWN = "<unknown-package-name>"
|
||||
|
||||
/** AndroidIDE's package name. */
|
||||
private const val PACKAGE_ANDROIDIDE = "com.itsaky.androidide"
|
||||
|
||||
fun install(app: Application) {
|
||||
check(!installed.getAndSet(true)) { "LogSender has already been installed" }
|
||||
this.packageName = app.packageName
|
||||
|
||||
if (PACKAGE_ANDROIDIDE == this.packageName) {
|
||||
return
|
||||
}
|
||||
|
||||
Intent(SERVICE_ACTION).setPackage(PACKAGE_ANDROIDIDE).let {
|
||||
if (app.bindService(it, this, 0)) {
|
||||
info("Binding to AndroidIDE's LogReceiver service")
|
||||
} else {
|
||||
error("Failed to bind to log receiver service")
|
||||
}
|
||||
}
|
||||
|
||||
installed.set(true)
|
||||
}
|
||||
|
||||
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
|
||||
this.receiver = ILogReceiver.Stub.asInterface(service)
|
||||
checkNotNull(this.receiver) { "Failed to get receiver instance" }
|
||||
|
||||
this.receiver!!.connect(this)
|
||||
info("Connected to AndroidIDE's LogRecevier")
|
||||
}
|
||||
|
||||
override fun onServiceDisconnected(name: ComponentName?) {
|
||||
info("Disconnected from AndroidIDE's LogRecevier")
|
||||
this.installed.set(false)
|
||||
this.reader?.interrupt()
|
||||
this.receiver = null
|
||||
this.reader = null
|
||||
}
|
||||
|
||||
override fun startReader() {
|
||||
if (reader?.isAlive == true) {
|
||||
warn("LogReader has already been started")
|
||||
return
|
||||
}
|
||||
|
||||
reader = LogReader { receiver?.onLog(it) }
|
||||
reader?.start()
|
||||
}
|
||||
|
||||
override fun getPid(): Int {
|
||||
return Process.myPid()
|
||||
}
|
||||
|
||||
override fun getPackageName(): String {
|
||||
return packageName ?: PACKAGE_UNKNOWN
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* This file is part of AndroidIDE.
|
||||
*
|
||||
* AndroidIDE is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AndroidIDE is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.logsender.utils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.Buffer;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Reads application logs with `logcat`.
|
||||
*
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
public class LogReader extends Thread {
|
||||
|
||||
private final ProcessBuilder processBuilder;
|
||||
private final Consumer<String> logConsumer;
|
||||
|
||||
public LogReader(Consumer<String> logConsumer) {
|
||||
this(defaultCmd(), logConsumer);
|
||||
}
|
||||
|
||||
public LogReader(String[] cmd, Consumer<String> logConsumer) {
|
||||
super("AndroidIDE-LogReader");
|
||||
this.logConsumer = logConsumer;
|
||||
|
||||
this.processBuilder = new ProcessBuilder(cmd);
|
||||
this.processBuilder.redirectErrorStream(true);
|
||||
|
||||
}
|
||||
|
||||
public static String[] defaultCmd() {
|
||||
return new String[] { "logcat", "-v", "threadtime" };
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Logger.info("Starting to read logs...");
|
||||
try {
|
||||
final var process = processBuilder.start();
|
||||
try (final var reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
if (logConsumer != null) {
|
||||
logConsumer.accept(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Throwable err) {
|
||||
Logger.error("An error occured while reading logs", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* This file is part of AndroidIDE.
|
||||
*
|
||||
* AndroidIDE is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AndroidIDE is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.logsender.utils
|
||||
|
||||
/**
|
||||
* Reads application logs with `logcat`.
|
||||
*
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
class LogReader(command: Array<String> = defaultCmd(), private val consume: (String) -> Unit) : Thread("AndroidIDE-LogReader") {
|
||||
|
||||
private val process = buildProcess(command)
|
||||
|
||||
override fun run() {
|
||||
info("Starting to read logs...")
|
||||
try {
|
||||
val process = process.start()
|
||||
process.inputStream.bufferedReader().forEachLine(consume)
|
||||
} catch (err: Throwable) {
|
||||
error("Failed to start logcat process", err)
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildProcess(command: Array<String>): ProcessBuilder {
|
||||
return ProcessBuilder(*command).apply {
|
||||
this.redirectErrorStream(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun defaultCmd(): Array<String> {
|
||||
return arrayOf("logcat", "-v", "threadtime")
|
||||
}
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* This file is part of AndroidIDE.
|
||||
*
|
||||
* AndroidIDE is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AndroidIDE is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.logsender.utils;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.ContentProvider;
|
||||
import android.content.ContentValues;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.itsaky.androidide.logsender.LogSender;
|
||||
|
||||
/**
|
||||
* Content providers are loaded before the application class is created. {@link LogSenderInstaller}
|
||||
* is used to install {@link LogSender} on application start.
|
||||
* <p>
|
||||
* {@link LogSenderInstaller} automatically sets up the LogSender code that runs in the main app
|
||||
* process.
|
||||
*
|
||||
* @author Akash Yadav
|
||||
* @see <a
|
||||
* href="https://github.com/square/leakcanary/blob/main/leakcanary-object-watcher-android/src/main/java/leakcanary/internal/MainProcessAppWatcherInstaller.kt">MainProcessAppWatcherInstaller</a>
|
||||
*/
|
||||
public class LogSenderInstaller extends ContentProvider {
|
||||
|
||||
@Override
|
||||
public boolean onCreate() {
|
||||
final var application = ((Application) getContext());
|
||||
LogSender.install(application);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection,
|
||||
@Nullable String[] selectionArgs, @Nullable String sortOrder
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getType(@NonNull Uri uri) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs
|
||||
) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection,
|
||||
@Nullable String[] selectionArgs
|
||||
) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
-75
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* This file is part of AndroidIDE.
|
||||
*
|
||||
* AndroidIDE is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AndroidIDE is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.logsender.utils
|
||||
|
||||
import android.app.Application
|
||||
import android.content.ContentProvider
|
||||
import android.content.ContentValues
|
||||
import android.database.Cursor
|
||||
import android.net.Uri
|
||||
import com.itsaky.androidide.logsender.LogSender
|
||||
|
||||
/**
|
||||
* Content providers are loaded before the application class is created. [LogSenderInstaller] is
|
||||
* used to install [LogSender] on application start.
|
||||
*
|
||||
* [LogSenderInstaller] automatically sets up the LogSender code that runs in the main app process.
|
||||
*
|
||||
* @author Akash Yadav
|
||||
* @see <a
|
||||
* href="https://github.com/square/leakcanary/blob/main/leakcanary-object-watcher-android/src/main/java/leakcanary/internal/MainProcessAppWatcherInstaller.kt">MainProcessAppWatcherInstaller</a>
|
||||
*/
|
||||
internal class LogSenderInstaller : ContentProvider() {
|
||||
|
||||
override fun onCreate(): Boolean {
|
||||
val app = context!!.applicationContext as Application
|
||||
LogSender.install(app)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun query(
|
||||
uri: Uri,
|
||||
projection: Array<out String>?,
|
||||
selection: String?,
|
||||
selectionArgs: Array<out String>?,
|
||||
sortOrder: String?
|
||||
): Cursor? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun getType(uri: Uri): String? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun insert(uri: Uri, values: ContentValues?): Uri? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun delete(uri: Uri, selection: String?, selectionArgs: Array<out String>?): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
override fun update(
|
||||
uri: Uri,
|
||||
values: ContentValues?,
|
||||
selection: String?,
|
||||
selectionArgs: Array<out String>?
|
||||
): Int {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
+25
-8
@@ -15,14 +15,31 @@
|
||||
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.logsender.utils
|
||||
package com.itsaky.androidide.logsender.utils;
|
||||
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
import com.itsaky.androidide.utils.ILogger;
|
||||
|
||||
private val log = ILogger.newInstance("LogSender")
|
||||
/**
|
||||
* Static methods for logging messages.
|
||||
*
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
public class Logger {
|
||||
private static final ILogger LOG = ILogger.newInstance("LogSender");
|
||||
|
||||
fun error(vararg messages: Any?) = log.error(*messages)
|
||||
fun warn(vararg messages: Any?) = log.warn(*messages)
|
||||
fun info(vararg messages: Any?) = log.info(*messages)
|
||||
fun debug(vararg messages: Any?) = log.debug(*messages)
|
||||
fun verbose(vararg messages: Any?) = log.verbose(*messages)
|
||||
public static void error(Object... messages) {
|
||||
LOG.error(messages);
|
||||
}
|
||||
|
||||
public static void warn(Object... messages) {
|
||||
LOG.warn(messages);
|
||||
}
|
||||
|
||||
public static void info(Object... messages) {
|
||||
LOG.info(messages);
|
||||
}
|
||||
|
||||
public static void debug(Object... messages) {
|
||||
LOG.debug(messages);
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
plugins {
|
||||
id("com.android.application")
|
||||
id("kotlin-android")
|
||||
}
|
||||
|
||||
android {
|
||||
@@ -34,7 +33,6 @@ dependencies {
|
||||
|
||||
implementation(projects.logsenderApi)
|
||||
|
||||
implementation(libs.androidx.ktx)
|
||||
implementation(libs.androidx.appcompat)
|
||||
implementation(libs.androidx.constraintlayout)
|
||||
implementation(libs.google.material)
|
||||
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* This file is part of AndroidIDE.
|
||||
*
|
||||
* AndroidIDE is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AndroidIDE is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.logsender.sample;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.PersistableBundle;
|
||||
import android.util.Log;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
|
||||
private final AtomicInteger count = new AtomicInteger(0);
|
||||
private final Handler handler = new Handler(Looper.getMainLooper());
|
||||
private final Runnable logger = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Log.d("LogSenderSample", "Log #" + count.getAndAdd(1));
|
||||
|
||||
if (count.get() == 20) {
|
||||
return;
|
||||
}
|
||||
|
||||
handler.postDelayed(this, 1000);
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState
|
||||
) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
handler.postDelayed(logger, 1000);
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* This file is part of AndroidIDE.
|
||||
*
|
||||
* AndroidIDE is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AndroidIDE is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.logsender.sample
|
||||
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.util.Log
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.WindowCompat
|
||||
import com.itsaky.androidide.logsender.sample.databinding.ActivityMainBinding
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var binding: ActivityMainBinding
|
||||
|
||||
private val count = AtomicInteger(0)
|
||||
private val handler = Handler(Looper.getMainLooper())
|
||||
private val logger =
|
||||
object : Runnable {
|
||||
override fun run() {
|
||||
Log.d("LogSenderSample", "Log #${count.getAndAdd(1)}")
|
||||
if (count.get() == 20) {
|
||||
return
|
||||
}
|
||||
handler.postDelayed(this, 1000)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
binding = ActivityMainBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
handler.postDelayed(logger, 1000)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user