Перейти к содержанию
Fire Monkey от А до Я
  • 0

Android 10 и муз.плеер


Ingalime

Вопрос

Здравствуйте. Есть приложение музыкального плеера со службой переднего фона, которая позволяет проигрывать музыку даже если приложение свернуто. Без этой службы андроид убивает приложение через пару минут если оно свернуто. Приложение работает на андроид 7.1, 8.1 и 9. Других устройств для тестирования нет. На андроид 10 приложение при старте сразу падает. Возникла мысль, что андроид 10 не может запустить службу переднего плана. Код:

procedure TForm1.FormCreate(Sender: TObject);
Begin
//Библиотека BASS для аудио http://www.un4seen.com/
 if not BASS_Init(-1, 44100, 0, nil, nil) Then Begin
	   ShowMessage('Failed to initialize audio!' + sLineBreak + 'Не удалось инициализировать audio!');
     Exit;
     end;

 try
     if FService = Nil Then Begin
      FService := TLocalServiceConnection.Create;
      FService.StartService('serPublic');
      end;
  except
       Exit;
  end;

Пользователь форума Tumaso, предложил код как отменить запуск службы для андроид 10. Лучше уж пусть приложение играет на переднем плане, чем просто падает при старте.

uses
    ... Androidapi.JNI.Os, Androidapi.JNIBridge ...
//изменения при страте в FormCreate
  if TJBuild_VERSION.JavaClass.SDK_INT <= 28 then
  begin
    try
      if not Assigned(FService) then
      begin
        FService := TLocalServiceConnection.Create;
        FService.StartService('serPublic');
      end;
    except
      // что нибудь делаем
    end;  
  end;

Но возникает еще вопрос, а может для андроид 10 надо запросить какие-то дополнительные разрешения или что-то добавить в манифест? Сейчас из разрешений в опциях проекта стоит Foreground service и Internet. Устройства с андроид 10 у меня нет. Ниже код службы, за который меня не ругайте, это солянка найденная в интернете и этот код прекрасно работает на андроид 7.1, 8.1 и 9.

unit Unit1;

interface

uses
  System.SysUtils,
  System.Classes,
  System.Android.Service,
  AndroidApi.JNI.GraphicsContentViewText,
  Androidapi.JNI.Os,
  Androidapi.JNI.App,
  Androidapi.JNI.Support,
  Androidapi.JNI.JavaTypes,
  Androidapi.Helpers,
  Androidapi.JNIBridge,
  Androidapi.Jni,
  System.Notification;

type
  TDM = class(TAndroidService)
    NotificationCenter1: TNotificationCenter;
    function AndroidServiceStartCommand(const Sender: TObject;
      const Intent: JIntent; Flags, StartId: Integer): Integer;

  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  DM: TDM;

implementation

{%CLASSGROUP 'FMX.Controls.TControl'}

{$R *.dfm}



function TDM.AndroidServiceStartCommand(const Sender: TObject;
  const Intent: JIntent; Flags, StartId: Integer): Integer;

var
  //Android 8.1, 9
  ServiceChannel: JNotificationChannel;
  NotificationManager: JNotificationManager;
  Obj: JObject;
  NewIntent: JIntent;
  ncb: JNotificationCompat_Builder;
  ntf: JNotification;
  PendingIntent: JPendingIntent;
  //Android 7.1
  service             : JService;
  serviceObjectId     : Pointer;
  ntf2                : JNotification;
  intent2             : JIntent;
  PendingIntent2      : JPendingIntent;

begin

   Result := TJService.JavaClass.START_NOT_STICKY;

   // can't ref .O on earlier phones, must hardcode
  if TJBuild_VERSION.JavaClass.SDK_INT > 26 then // JBuild_VERSION_CODES.JavaClass.O
  begin
     //Android 8.1
     //new ways for SDK > 26 (won't be called when API < 26 anyways)
     try

      ServiceChannel := TJNotificationChannel.JavaClass.init(
      StringtoJString('com.radio.one'), //CHANNEL_ID
      StrToJCharSequence('Public radio Channel'),
      TJNotificationManager.JavaClass.IMPORTANCE_DEFAULT
    );

    Obj := TAndroidHelper.Context.getSystemService(
    TJContext.JavaClass.NOTIFICATION_SERVICE);
    NotificationManager := TJNotificationManager.Wrap(Obj);
    NotificationManager.createNotificationChannel(ServiceChannel);

    NewIntent:= TAndroidHelper.Context.getPackageManager().getLaunchIntentForPackage(
      TAndroidHelper.Context.getPackageName());
    NewIntent.setAction(TJIntent.JavaClass.ACTION_MAIN);
    NewIntent.addCategory(TJIntent.JavaClass.CATEGORY_LAUNCHER);
    NewIntent.addFlags(TJIntent.JavaClass.FLAG_ACTIVITY_NEW_TASK);

    PendingIntent := TJPendingIntent.JavaClass.getActivity(
      TAndroidHelper.Context, 0, NewIntent,
      TJIntent.JavaClass.FLAG_ACTIVITY_NEW_TASK
    );

    ncb := TJNotificationCompat_Builder.JavaClass.init(
      TAndroidHelper.Context,
      StringToJString('com.radio.one')
    );

   ncb.setContentTitle(StrToJCharSequence('PublicRadio Service'));
   // ncb.setTicker(StrToJCharSequence('MyCommsService')); // can't remember why this is commented out to be honest
   ncb.setSmallIcon(JavaService.getApplicationInfo.icon);
   ncb.setContentIntent(PendingIntent);
   ncb.setOngoing(True);
   ntf := ncb.build;
   JavaService.startForeground(StartId, ntf);
   except
       exit;
   end;

 end
 else
 begin
      //Android 7.1
     try
      serviceObjectId  := (JavaService as ILocalObject).GetObjectID;
      service          := TJService.Wrap(serviceObjectId);
      /////ntf2             := TJNotification.Create;
      ////ntf2.icon        := service.getApplicationInfo.icon;

    NewIntent:= TAndroidHelper.Context.getPackageManager().getLaunchIntentForPackage(
      TAndroidHelper.Context.getPackageName());
    NewIntent.setAction(TJIntent.JavaClass.ACTION_MAIN);
    NewIntent.addCategory(TJIntent.JavaClass.CATEGORY_LAUNCHER);
    NewIntent.addFlags(TJIntent.JavaClass.FLAG_ACTIVITY_NEW_TASK);

    PendingIntent2 := TJPendingIntent.JavaClass.getActivity(
      TAndroidHelper.Context, 0, NewIntent,
      TJIntent.JavaClass.FLAG_ACTIVITY_NEW_TASK
    );

      ncb := TJNotificationCompat_Builder.JavaClass.init(
      TAndroidHelper.Context,
      StringToJString('com.radio.one')
    );

      //intent2  := TJIntent.Create;
      //PendingIntent2 := TJPendingIntent.JavaClass.getActivity(service.getApplicationContext, 0, intent2, 0);

      ncb.setContentTitle(StrToJCharSequence('PublicRadio'));
      // ncb.setTicker(StrToJCharSequence('MyCommsService'));
      ncb.setSmallIcon(JavaService.getApplicationInfo.icon);
      ncb.setContentIntent(PendingIntent2);
      ncb.setOngoing(True);
      ntf2 := ncb.build;

      ntf2.setLatestEventInfo(service.getApplicationContext, StrToJCharSequence('PublicRadio'), StrToJCharSequence('PublicRadio Service'), PendingIntent2);
      service.startForeground(StartId, ntf2);
   except
       exit;
   end;

  end;

end;

end.

 

Ссылка на комментарий
  • Ответы 60
  • Создана
  • Последний ответ

Лучшие авторы в вопросе

Рекомендуемые сообщения

  • 0
2 часа назад, Ingalime сказал:

Не могу я собрать 32 бит падает.

Если падает, значит скорее всего какие-то файлы не задеплоились.

 

6 часов назад, Andrey Efimov сказал:

Перед тем как вы соберётесь выложить сюда собранный 32-битный apk, проверьте его, открыв например в винраре. Зайдите в папку "lib" и проверьте каждую папку. Выше я уже написал, что будет внутри каждой папки для 32-битного apk и для 64-битного apk (https://fire-monkey.ru/topic/7447-android-10-и-музплеер/?do=findComment&comment=43249). Т.о. в 32-битном apk должна получиться примерно такая структура (на примере Project1):

  • armeabi - заглушка libProject1.so.
  • armeabi-v7a - ваш проект libProject1.so, сервис, библиотека bass и т.д.
  • mips - заглушка libProject1.so.

По всей видимости вы напрочь проигнорировали совет Андрея Ефимова, или же просто даже не читали, что он написал. Откройте полученный apk через любой архиватор и проверьте, чтобы в каталогах были все необходимые файлы.

 

2 часа назад, Ingalime сказал:

Обнаружилось что папки armeabi вообще нет.

Если нет, значит разработчики библиотеки BASS посчитали, что платформа armeabi больше не является актуальной. В каталоге armeabi должна быть заглушка libProject1.so

Ссылка на комментарий
  • 0
11 часов назад, PowerOwl сказал:

По всей видимости вы напрочь проигнорировали совет Андрея Ефимова,

Я в предыдущем посте через символ -> указала содержимое lib пакета 32, как сказал Андрей.

Вот содержимое всех папок APK 32 бит.

 

32bit.jpg

Изменено пользователем Ingalime
Ссылка на комментарий
  • 0

Сейчас так:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.embarcadero.PublicRadio/com.embarcadero.firemonkey.FMXNativeActivity}: java.lang.IllegalArgumentException: Unable to find native library PublicRadio using classloader: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.embarcadero.PublicRadio-yXTvrVLFqprwZS5V63BhCQ==/base.apk"],nativeLibraryDirectories=[/data/app/com.embarcadero.PublicRadio-yXTvrVLFqprwZS5V63BhCQ==/lib/arm64, /data/app/com.embarcadero.PublicRadio-yXTvrVLFqprwZS5V63BhCQ==/base.apk!/lib/arm64-v8a, /system/lib64, /system/vendor/lib64]]]

at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2817)

at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2895)

at android.app.ActivityThread.-wrap11(Unknown Source:0)

at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1616)

at android.os.Handler.dispatchMessage(Handler.java:106)

at android.os.Looper.loop(Looper.java:176)

at android.app.ActivityThread.main(ActivityThread.java:6651)

at java.lang.reflect.Method.invoke(Native Method)

at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)

at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:824)

Caused by: java.lang.IllegalArgumentException: Unable to find native library PublicRadio using classloader: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.embarcadero.PublicRadio-yXTvrVLFqprwZS5V63BhCQ==/base.apk"],nativeLibraryDirectories=[/data/app/com.embarcadero.PublicRadio-yXTvrVLFqprwZS5V63BhCQ==/lib/arm64, /data/app/com.embarcadero.PublicRadio-yXTvrVLFqprwZS5V63BhCQ==/base.apk!/lib/arm64-v8a, /system/lib64, /system/vendor/lib64]]]

at android.app.NativeActivity.onCreate(NativeActivity.java:160)

at com.embarcadero.firemonkey.FMXNativeActivity.onCreate(FMXNativeActivity.java:135)

at android.app.Activity.performCreate(Activity.java:7088)

at android.app.Activity.performCreate(Activity.java:7079)

at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1215)

at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2770)

... 9 more

dep1.jpg

dep2.jpg

Изменено пользователем Ingalime
Ссылка на комментарий
  • 0
2 часа назад, Ingalime сказал:

nativeLibraryDirectories=[/data/app/com.embarcadero.PublicRadio-yXTvrVLFqprwZS5V63BhCQ==/lib/arm64

Давайте apk. По вот этой строчке видно, что файлы он ищёт в каталоге для 64-битных устройств. На 32-битных всё должно работать.

Ссылка на комментарий
  • 0

Мои дополнительные шаги. Надо было подправить манифест для 32 бит. Там по дефолту добавлялись 5 опасных разрешений. Теперь манифест для 32 бит нормальный:

<uses-sdk android:minSdkVersion="23" android:targetSdkVersion="29" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <uses-permission android:name="android.permission.INTERNET" />
//********************
 <service android:exported="false" android:foregroundServiceType="mediaPlayback" android:name="com.embarcadero.services.serPublic" />

Откомпилировала службу в режиме 32 бит и в деплоймент для 32 бит добавила пути как выше на рисунке. Вот такой теперь арк, но падает.

 

PublicRadio.apk

Ссылка на комментарий
  • 0

Логи:

FATAL EXCEPTION: main
Process: com.embarcadero.PublicRadio, PID: 9717
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.embarcadero.PublicRadio/com.embarcadero.firemonkey.FMXNativeActivity}: java.lang.IllegalArgumentException: Unable to load native library: /data/app/com.embarcadero.PublicRadio-1/lib/arm/libPublicRadio.so
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java)
    at android.app.ActivityThread.access$1100(ActivityThread.java)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java)
    at android.os.Handler.dispatchMessage(Handler.java)
    at android.os.Looper.loop(Looper.java)
    at android.app.ActivityThread.main(ActivityThread.java)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java)
Caused by: java.lang.IllegalArgumentException: Unable to load native library: /data/app/com.embarcadero.PublicRadio-1/lib/arm/libPublicRadio.so
    at android.app.NativeActivity.onCreate(NativeActivity.java)
    at com.embarcadero.firemonkey.FMXNativeActivity.onCreate(FMXNativeActivity.java:135)
    at android.app.Activity.performCreate(Activity.java)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java)
    ... 10 more

Библиотека libPublicRadio.so по пути /data/app/com.embarcadero.PublicRadio-1/lib/arm присутствует, значит что-то не так с самой библиотекой. Тут уже можно только гадать. Я бы на вашем месте попробовал создать новый проект, перенести в него код и компоненты со старого и попробовать скомпилировать сразу под Андроид-32.

Ссылка на комментарий
  • 0
1 час назад, Ingalime сказал:

Мои дополнительные шаги. Надо было подправить манифест для 32 бит. Там по дефолту добавлялись 5 опасных разрешений. Теперь манифест для 32 бит нормальный:

<uses-sdk android:minSdkVersion="23" android:targetSdkVersion="29" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <uses-permission android:name="android.permission.INTERNET" />
//********************
 <service android:exported="false" android:foregroundServiceType="mediaPlayback" android:name="com.embarcadero.services.serPublic" />

Откомпилировала службу в режиме 32 бит и в деплоймент для 32 бит добавила пути как выше на рисунке. Вот такой теперь арк, но падает.

 

PublicRadio.apk 14 \u041c\u0411 · 1 загрузка

Да и у меня "падает".

С Уважением. Олег Киреев.

Ссылка на комментарий
  • 0

Большое спасибо!

Подскажите, пожалуйста, мои шаги следующие правильные?

У меня в дереве проектов две версии приложения. Запускаю 32 бит версию. На телефоне появляется приложение и оно работает. Запускаю версию 64 бит на телефоне и рядом с приложением 32 бит появляется 64 битное и тоже работает.

Далее создаю aab и отправляю в магазин.

http://docwiki.embarcadero.com/RADStudio/Sydney/en/Submitting_Your_Android_App_to_Google_Play#Android_App_Bundle_Support

Однако если aab содержит сервис то могут быть проблемы, информация отсюда, правда это было год назад:

https://fire-monkey.ru/topic/2040-проблема-с-android-service/#comment-10875

Как все таки правильно? Пробовать создать гибридный apk?

Изменено пользователем Ingalime
Ссылка на комментарий

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

  • Последние посетители   0 пользователей онлайн

    Ни одного зарегистрированного пользователя не просматривает данную страницу


×
×
  • Создать...