Служба переднего плана Kivy для Android – невозможно открыть приложение после перезапуска службы (приложение удалено из Android

Форум для тех, кто программирует под Android
Ответить
Anonymous
 Служба переднего плана Kivy для Android – невозможно открыть приложение после перезапуска службы (приложение удалено из

Сообщение Anonymous »

Когда основное приложение запущено, но не активно, щелчок по уведомлению о службе выводит его на передний план, это нормально.
Другой случай, когда я закрываю приложение, вытаскивая его из списка последних приложений, служба перезапускается, и когда я нажимаю на уведомление, отображается просто черный экран и все.
Одна интересная вещь, которую я заметил: через некоторое время (час или два) оно начинает работать — основное приложение запускается при нажатии на уведомление о службе!
Как я могу добиться этого после перезапуска службы?
Приложение создано с помощью Python+Kivy и построено с помощью Buildozer, и я запускаю его на Android 10.
Я пробовал setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) для Intent, но это не помогло.
Вот код.
PythonService.java:

Код: Выделить всё

package org.kivy.android;

import android.os.Build;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import android.app.Service;
import android.os.IBinder;
import android.os.Bundle;
import android.content.Intent;
import android.content.Context;
import android.util.Log;
import android.app.Notification;
import android.app.PendingIntent;
import android.os.Process;
import java.io.File;

//imports for channel definition
import android.app.NotificationManager;
import android.app.NotificationChannel;
import android.graphics.Color;

public class PythonService extends Service implements Runnable {

// Thread for Python code
private Thread pythonThread = null;

// Python environment variables
private String androidPrivate;
private String androidArgument;
private String pythonName;
private String pythonHome;
private String pythonPath;
private String serviceEntrypoint;
// Argument to pass to Python code,
private String pythonServiceArgument;

public static PythonService mService = null;
private Intent startIntent = null;

private boolean autoRestartService = false;

public void setAutoRestartService(boolean restart) {
autoRestartService = restart;
}

public int startType() {
return START_NOT_STICKY;
}

@Override
public IBinder onBind(Intent arg0) {
return null;
}

@Override
public void onCreate() {
super.onCreate();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (pythonThread != null) {
Log.v("python service", "service exists, do not start again");
return START_NOT_STICKY;
}

startIntent = intent;
Bundle extras = intent.getExtras();
androidPrivate = extras.getString("androidPrivate");
androidArgument = extras.getString("androidArgument");
serviceEntrypoint = extras.getString("serviceEntrypoint");
pythonName = extras.getString("pythonName");
pythonHome = extras.getString("pythonHome");
pythonPath = extras.getString("pythonPath");
boolean serviceStartAsForeground = (
extras.getString("serviceStartAsForeground").equals("true")
);
pythonServiceArgument = extras.getString("pythonServiceArgument");
pythonThread = new Thread(this);
pythonThread.start();

if (serviceStartAsForeground) {
doStartForeground(extras);
}

return startType();
}

protected int getServiceId() {
return 1;
}

protected void doStartForeground(Bundle extras) {
String serviceTitle = extras.getString("serviceTitle");
String serviceDescription = extras.getString("serviceDescription");
Notification notification;
Context context = getApplicationContext();
Intent contextIntent = new Intent(context, PythonActivity.class);
contextIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // my attempt but it didn't helped
PendingIntent pIntent = PendingIntent.getActivity(context, 0, contextIntent, PendingIntent.FLAG_UPDATE_CURRENT);

if (Build.VERSION.SDK_INT <  Build.VERSION_CODES.O) {
notification = new Notification(
context.getApplicationInfo().icon, serviceTitle, System.currentTimeMillis());
try {
// prevent using NotificationCompat, this saves 100kb on apk
Method func = notification.getClass().getMethod(
"setLatestEventInfo", Context.class, CharSequence.class,
CharSequence.class, PendingIntent.class);
func.invoke(notification, context, serviceTitle, serviceDescription, pIntent);
} catch (NoSuchMethodException | IllegalAccessException |
IllegalArgumentException | InvocationTargetException e) {
}
} else {
// for android 8+ we need to create our own channel
// https://stackoverflow.com/questions/47531742/startforeground-fail-after-upgrade-to-android-8-1
String NOTIFICATION_CHANNEL_ID = "org.kivy.p4a";    //TODO: make this configurable
String channelName = "Background Service";                //TODO: make this configurable
NotificationChannel chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName,
NotificationManager.IMPORTANCE_NONE);

chan.setLightColor(Color.BLUE);
chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
manager.createNotificationChannel(chan);

Notification.Builder builder = new Notification.Builder(context, NOTIFICATION_CHANNEL_ID);
builder.setContentTitle(serviceTitle);
builder.setContentText(serviceDescription);
builder.setContentIntent(pIntent);
builder.setSmallIcon(context.getApplicationInfo().icon);
notification = builder.build();
}
startForeground(getServiceId(), notification);
}

@Override
public void onDestroy() {
super.onDestroy();
pythonThread = null;
if (autoRestartService &&  startIntent != null) {
Log.v("python service", "service restart requested");
startService(startIntent);
}
Process.killProcess(Process.myPid());
}

/**
* Stops the task gracefully when killed.
* Calling stopSelf() will trigger a onDestroy() call from the system.
*/
@Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
stopSelf();
}

@Override
public void run(){
String app_root =  getFilesDir().getAbsolutePath() + "/app";
File app_root_file = new File(app_root);
PythonUtil.loadLibraries(app_root_file,
new File(getApplicationInfo().nativeLibraryDir));
this.mService = this;
nativeStart(
androidPrivate, androidArgument,
serviceEntrypoint, pythonName,
pythonHome, pythonPath,
pythonServiceArgument);
stopSelf();
}

// Native part
public static native void nativeStart(
String androidPrivate, String androidArgument,
String serviceEntrypoint, String pythonName,
String pythonHome, String pythonPath,
String pythonServiceArgument);
}
и класс, расширяющий PythonService:

Код: Выделить всё

package org.test.schedules;

import android.content.Intent;
import android.content.Context;
import org.kivy.android.PythonService;

public class ServiceService extends PythonService {

@Override
protected int getServiceId() {
return 1;
}

static public void start(Context ctx, String pythonServiceArgument) {
Intent intent = new Intent(ctx, ServiceService.class);
String argument = ctx.getFilesDir().getAbsolutePath() + "/app";
intent.putExtra("androidPrivate", ctx.getFilesDir().getAbsolutePath());
intent.putExtra("androidArgument", argument);
intent.putExtra("serviceTitle", "Schedules1106fgs_sdk28");
intent.putExtra("serviceDescription", "Service");
intent.putExtra("serviceEntrypoint", "service/main.py");
intent.putExtra("pythonName", "service");
intent.putExtra("serviceStartAsForeground", "true");
intent.putExtra("pythonHome", argument);
intent.putExtra("pythonPath", argument + ":" + argument + "/lib");
intent.putExtra("pythonServiceArgument", pythonServiceArgument);
ctx.startService(intent);
}

static public void stop(Context ctx) {
Intent intent = new Intent(ctx, ServiceService.class);
ctx.stopService(intent);
}
}
Также вот фрагмент AndroidManifest.xml Будем очень признательны за вашу помощь.
Обновление
Я еще не нашел решения, но заметил, но, похоже, проблема связана с процессом фонового кэширования. Поэтому, если я перейду в «Параметры разработчика» -> «Запуск служб» -> «Показать кешированные процессы» и остановить процесс там вручную, приложение перезапустится нормально.
Я думаю, решение может заключаться в том, чтобы каким-то образом предотвратить создание кешированного процесса в фоновом режиме или убить этот процесс в какой-то конкретный момент, при выходе из приложения или перезапуске службы. Я не эксперт в Android, может ли кто-нибудь помочь с этим?

Подробнее здесь: https://stackoverflow.com/questions/647 ... -restarted
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Android»