feat(logsender): run LogSender as a service to avoid termination

This commit is contained in:
Akash Yadav
2023-05-25 19:56:27 +05:30
parent e53a873339
commit 4346c6a572
8 changed files with 92 additions and 21 deletions
@@ -20,7 +20,6 @@ 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;
@@ -51,12 +50,14 @@ public class MainActivity extends AppCompatActivity {
handler.postDelayed(logger, 1000);
new Thread(() -> {
findViewById(R.id.exception).setOnClickListener(v -> {
throw new RuntimeException("Oops!");
});
// Test with 100K lines at once
findViewById(R.id.log_overflow).setOnClickListener(v -> new Thread(() -> {
for (int i = 0; i < 100000; i++) {
Log.d("SomeLogs", "Log #" + i);
Log.d("ShouldNotBreak", "Log #" + i);
}
}).start();
}).start());
}
}
@@ -21,11 +21,32 @@
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:gravity="center"
android:orientation="vertical"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />
android:text="Click the buttons below to test different cases." />
<Button
android:id="@+id/log_overflow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="8dp"
android:text="Log 100K lines" />
<Button
android:id="@+id/exception"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="8dp"
android:text="throw RuntimeException" />
</androidx.appcompat.widget.LinearLayoutCompat>
@@ -17,7 +17,7 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Base.Theme.AndroidIDE" parent="Theme.Material3.DayNight.NoActionBar">
<style name="Base.Theme.AndroidIDE" parent="Theme.Material3.DayNight">
<!-- Customize your dark theme here. -->
<!-- <item name="colorPrimary">@color/my_dark_primary</item> -->
</style>
@@ -17,7 +17,7 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Base.Theme.AndroidIDE" parent="Theme.Material3.DayNight.NoActionBar">
<style name="Base.Theme.AndroidIDE" parent="Theme.Material3.DayNight">
<!-- Customize your light theme here. -->
<!-- <item name="colorPrimary">@color/my_light_primary</item> -->
</style>
+9 -3
View File
@@ -16,16 +16,22 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<queries>
<package android:name="com.itsaky.androidide"/>
<package android:name="com.itsaky.androidide" />
</queries>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="com.itsaky.androidide.permission.BIND_LOG_SERVICE"/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="com.itsaky.androidide.permission.BIND_LOG_SERVICE" />
<application>
<provider
android:name=".utils.LogSenderInstaller"
android:authorities="${applicationId}.logsender-installer"
android:enabled="@bool/logsender_enabled"
android:exported="false" />
<service
android:name=".LogSenderService"
android:exported="false" />
</application>
</manifest>
@@ -17,8 +17,8 @@
package com.itsaky.androidide.logsender;
import android.app.Application;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
@@ -33,7 +33,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
*
* @author Akash Yadav
*/
public class LogSender extends ILogSender.Stub implements ServiceConnection {
public final class LogSender extends ILogSender.Stub implements ServiceConnection {
private final AtomicBoolean installed = new AtomicBoolean(false);
@@ -63,24 +63,20 @@ public class LogSender extends ILogSender.Stub implements ServiceConnection {
private LogSender() {
}
public static void install(Application app) {
INSTANCE.doInstall(app);
}
private void doInstall(Application app) {
void doInstall(Context context) {
if (installed.get()) {
Logger.warn("LogSender is already installed");
return;
}
this.packageName = app.getPackageName();
this.packageName = context.getPackageName();
if (PACKAGE_ANDROIDIDE.equals(packageName)) {
return;
}
final Intent intent = new Intent(SERVICE_ACTION);
intent.setPackage(PACKAGE_ANDROIDIDE);
if (app.bindService(intent, this, 0)) {
if (context.bindService(intent, this, 0)) {
Logger.info("Binding to log receiver");
installed.set(true);
} else {
@@ -0,0 +1,45 @@
/*
* 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.Service;
import android.content.Intent;
import android.os.IBinder;
import androidx.annotation.Nullable;
/**
* A {@link Service} which runs in the background and sends logs to AndroidIDE.
*
* @author Akash Yadav
*/
public class LogSenderService extends Service {
private final LogSender logSender = LogSender.INSTANCE;
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
logSender.doInstall(getApplicationContext());
return START_NOT_STICKY;
}
}
@@ -20,9 +20,11 @@ package com.itsaky.androidide.logsender.utils;
import android.app.Application;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import com.itsaky.androidide.logsender.LogSender;
import com.itsaky.androidide.logsender.LogSenderService;
/**
* Content providers are loaded before the application class is created. {@link LogSenderInstaller}
@@ -40,7 +42,7 @@ public class LogSenderInstaller extends ContentProvider {
@Override
public boolean onCreate() {
final Application application = ((Application) getContext());
LogSender.install(application);
application.startService(new Intent(application, LogSenderService.class));
return true;
}