среда, 27 января 2016 г.

[BroadcastReceiver] Автозапуск приложения после перезагрузки ОС

В этой статье, я покажу, как сделать автозапуск приложения в Андроид используя RAD Studio Seattle.
Последний апдейт от 16.04.17.

Начнём с плана:
  1. Нам необходим java-класс, наследник от BroadcastReceiver, который, собственно и будет запускать наше приложение
  2. Файл classes.dex, склеенный с нашим java-классом
  3. Ну и само приложение, которые мы хотим запускать после перезагрузки системы

Пункт 1. Java – класс.
Ничего особо сложного в нём нет. Класс можно написать в Android Studio, в любом блокноте (например: Notepad ++) или вообще просто скопировав код ниже и вставив его опять же через блокнот, этот вопрос уже сами решайте :)
Я опишу пример, где класс создаём через Notepad ++.
Для начала создадим структуру папок:
  • В папке «ReceiverProject» будем хранить наш проект.
  • В папке «ReceiverProject\java\src\com\TestReceiver\» будет наш класс, назовём его «BootCompletedReceiver», т.е. там будет лежать файл «BootCompletedReceiver.java».

Теперь пишем код:
package com.TestReceiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class BootCompletedReceiver extends BroadcastReceiver {

 public void onReceive(Context context, Intent intent) {

  if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
   Intent TestLauncher = new Intent();
            TestLauncher.setClassName(context, "com.embarcadero.firemonkey.FMXNativeActivity");
   TestLauncher.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
   context.startActivity(TestLauncher);
  }

 }
 
}


Описание кода.
Определяем имя пакета (оно совпадает с частью пути, по которому хранится файл), подключаем модули.
Наследуемся от BroadcastReceiver, определяем метод onReceive, в нём проверяем, если пришло сообщение о завершении загрузки системы, то создаём Интент, прописываем имя класса приложения (в FMX – это всегда «com.embarcadero.firemonkey.FMXNativeActivity»), устанавливаем флаг на запуск Активити в новом таске, ну и стартуем активити (метод startActivity), передав Интент.
Как-то так… :)
Важно, также, заметить, что для «ACTION_BOOT_COMPLETED» требуется выдать разрешение «RECEIVE_BOOT_COMPLETED» в манифесте приложения, но об этом позже.

Ну вот, класс у нас готов.

Пункт 2. Файл classes.dex.
Я уже писал о том, как создавать этот файл в статье «Как подключить и использовать свой JAVA-класс».
Поэтому здесь, вкратце опишу действия, нам необходим bat-файл, в котором мы пропишем пути, положим его в папку «ReceiverProject\java\» и запустим. На выходе, у нас появится папка «ReceiverProject\java\output\dex\», которая содержит файл classes.dex.
Готовый bat файл (вам останется прописать пути, при необходимости) можно взять из исходников, которые я выложил ниже.

Update 23.02.17. Действительно для XE7 и выше. BAT - файл для JAVA 1.7 - 1.8
Для тех, кто уже понимает или наоборот не хочет понимать, для чего нужен classes.dex.
Вы можете создать JAR файл с вашим JAVA классом и добавить его через Project Manager (Как добавить jar библиотеку в проект, в данном случае, обёртку делать не нужно).
Для создания JAR файла, вам необходимо использовать bat файл с таким содержимым:
@echo off
setlocal

if x%ANDROID% == x set ANDROID=C:\Android\sdk
set ANDROID_PLATFORM=%ANDROID%\platforms\android-24
set PROJ_DIR=%CD%
set VERBOSE=0

echo.
echo Compiling the Java service activity source files
echo.
mkdir output 2> nul
mkdir output\classes 2> nul
if x%VERBOSE% == x1 SET VERBOSE_FLAG=-verbose
javac -source 1.7 -target 1.7 %VERBOSE_FLAG% -Xlint:deprecation -cp %ANDROID_PLATFORM%\android.jar -d output\classes src\com\TestReceiver\BootCompletedReceiver.java

echo.
echo Creating jar containing the new classes
echo.
mkdir output\jar 2> nul
if x%VERBOSE% == x1 SET VERBOSE_FLAG=v
jar c%VERBOSE_FLAG%f output\jar\test_classes.jar -C output\classes com

echo.
echo Now we have the end result, which is output\jar\test_classes.jar

:Exit

pause

endlocal

После выполнения этого bat файла, у вас появится файл output\jar\test_classes.jar. Его то и добавьте через Project Manager (подробности в статье, указанной чуть выше).

Update 16.04.17.
  • Если вы выбрали вариант с добавлением jar файл, то вам не нужно создавать classes.dex, просто добавляете jar файл в проект и всё.
  • Если вы выбрали вариант с файлом classes.dex, то не нужно добавлять jar файл одновременно с ним.
  • В обоих случаях для данного примера обёртка не нужна!

Пункт 3. Приложение.
Ну, тут всё совсем просто, можно создать пустой проект.
  • В «Uses Prmissions» выдаём разрешение «Receive boot complited».
  • В Deployment Manager снимаем галочку с файла (по умолчанию) «classes.dex», добавляем туда наш файл из папки «ReceiverProject\java\output\dex», прописываем у него путь (Remote Path) «classes\».
  • В Project Manager жмём Build, это необходимо, чтобы среда создала файл «AndroidManifest.template.xml» в корне проекта.
Открываем файл «AndroidManifest.template.xml», находим строчку «<%receivers%>» и после неё пишем


        <receiver android:name="com.TestReceiver.BootCompletedReceiver"

                  android:permission="android.permission.RECEIVE_BOOT_COMPLETED"

                  android:enabled="true">

            <intent-filter>

                <action android:name="android.intent.action.BOOT_COMPLETED" />

                <category android:name="android.intent.category.DEFAULT" />

            </intent-filter>

        </receiver>


В первой строчке мы указываем имя нашего ресейвера, «com.TestReceiver» - имя пакета, «BootCompletedReceiver» - название нашего класса.

Важные замечания.
  • Проверяйте Deployment Manager, среда иногда ставит обратно галочку на стандартном classes.dex.
  • Чтобы приложение подписалось на события системы, его необходимо один раз запустить.
Сохраняем файл и запускаем компиляцию проекта.
На этом всё.

Как всегда, более подробно, читайте официальную справку :)

Видео

Исходники: Скачать с Google Drive

18 комментариев:

  1. Не работает.
    запускаю сервис
    ServiceHandle:=TLocalServiceConnection.Create;
    ServiceHandle.StartService('PanelControlService');
    ServiceHandle.Free;

    в сервисе
    Result := TJService.JavaClass.START_STICKY;

    вижу что сервис дальше работает после закрытия приложения


    в файле прописал
    package com.PanelControlReceiver;

    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;

    public class BootCompletedReceiver extends BroadcastReceiver {

    public void onReceive(Context context, Intent intent) {

    if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
    Intent TestLauncher = new Intent();
    TestLauncher.setClassName(context, "com.embarcadero.services.PanelControlService");
    context.startService(TestLauncher);
    }

    }

    }

    в манифесте







    <%uses-permission%>



    <%application-meta-data%>
    <%services%>









    <%activity%>
    <%receivers%>


















    после перезагрузки сервис не стартует автоматически

    ОтветитьУдалить
  2. Доброе время суток!
    Подскажите если не сложно. Начал кодить на Delphi 10.2, всё делаю как в Вашей статье только не много со своими корректировками и получается всё создаётся как надо, но только сам мой класс dex создаваться не хочет хоть убей.
    Код батника следующий:
    @echo off

    setlocal

    if x%ANDROID% == x set ANDROID=C:\Users\Public\Documents\Embarcadero\Studio\19.0\PlatformSDKs\android-sdk-windows
    set ANDROID_PLATFORM=%ANDROID%\platforms\android-22
    set DX_LIB=%ANDROID%\build-tools\22.0.1\lib
    set EMBO_DEX="C:\Program Files (x86)\Embarcadero\Studio\19.0\lib\android\debug"
    set PROJ_DIR=%CD%
    set VERBOSE=0

    echo.
    echo Compiling the Java service activity source files
    echo.
    mkdir output 2> nul
    mkdir output\classes 2> nul
    if x%VERBOSE% == x1 SET VERBOSE_FLAG=-verbose
    javac %VERBOSE_FLAG% -Xlint:deprecation -cp %ANDROID_PLATFORM%\android.jar -d output\classes src\com\SecurityReceiver\BootCompletedReceiver.java

    echo.
    echo Creating jar containing the new classes
    echo.
    mkdir output\jar 2> nul
    if x%VERBOSE% == x1 SET VERBOSE_FLAG=v
    jar c%VERBOSE_FLAG%f output\jar\security_classes.jar -C output\classes com

    echo.
    echo Converting from jar to dex...
    echo.
    mkdir output\dex 2> nul
    if x%VERBOSE% == x1 SET VERBOSE_FLAG=--verbose
    call %DX_LIB%\dx.jar --dex %VERBOSE_FLAG% --output=%PROJ_DIR%\output\dex\security_classes.dex --positions=lines %PROJ_DIR%\output\jar\security_classes.jar

    echo.
    echo Merging dex files
    echo.com.android.dx.merge.DexMerger
    java -cp %DX_LIB%\dx.jar com.android.dx.merge.DexMerger %PROJ_DIR%\output\dex\classes.dex %PROJ_DIR%\output\dex\security_classes.dex %EMBO_DEX%

    echo Tidying up
    echo.
    ::del output\classes\SecurityReceiver\BootCompletedReceiver.class
    ::rmdir output\classes\SecurityReceiver
    ::rmdir output\classes
    ::del output\dex\security_classes.dex
    ::del output\jar\security_classes.jar
    ::rmdir output\jar

    echo.
    echo Now we have the end result, which is output\dex\classes.dex

    :Exit

    pause

    endlocal

    Ошибка при билде через этот батник, ниже скриншот:
    http://redpro.site/myscr/1111.jpg

    После я меняю строку в батники, ниже её привожу:
    java -cp %DX_LIB%\dx.jar com.android.dx.merge.DexMerger.java %PROJ_DIR%\output\dex\classes.dex %PROJ_DIR%\output\dex\security_classes.dex %EMBO_DEX%
    Как видите я добавил расширение к файлу com.android.dx.merge.DexMerger JAVA, но при билде
    через указанный выше батник так же происходит ошибка, ниже скриншот:
    http://redpro.site/myscr/222.jpg
    Я так понимаю по выше указанной ошибки батник не может найти нужную строку для подгрузки данного класса, а может вообще не может найти данный файл com.android.dx.merge.DexMerger.java. Я уже его качал с интернета и ложил по директории C:\Users\Public\Documents\Embarcadero\Studio\19.0\PlatformSDKs\android-sdk-windows\build-tools\22.0.1\lib и всё равно происходит такая ошибка, уже двое суток над ней бьюсь если не сложно подскажите, что я не так делаю.

    На счёт Вашего исходника:
    В комплекте не ишла обёртка, а точнее преобразованный JavaInterfaces.pas, но это мелочи я его через утилиту Java2OP.exe создал и подрубил к Uses, так же добавил Ваш test_classes.jar и соответственно test_classes.dex в общем приложение скомпилилось удачно, но так же есть маленькая ошибка, а точнее на эмуляторе BlueStacks не показывается сам интерфейс программы чисто запускается и софт сразу сворачивается хотя после перезагрузки происходит это же, а это значит, что приложение село в автозагрузку. Так же тестировал место эмулятора использовал свой мобильник: 1.При запуске на мобильнике стартует приложение и висит, дальше заставки оно не идёт как будто приложению мешает, что то полностью подгрузится и соответственно не какой код если стоять будет к примеру в событии TForm1.FormCreate не выполнится т.к приложение не полностью запускается, хотя при перезагрузки телефона приложение перезапускается, но так же виснет на заставке.
    Пожалуйста помогите разобраться, что я не так делаю?
    P.S: Я так понял если приложение перемещать на флешку то автозапуск работать не будет ((?

    ОтветитьУдалить
    Ответы
    1. Сразу про Delphi 10.2 Tokyo - не тестировал и не собираюсь, на данный момент студия сильно нестабильна, нужно ждать обновления. Рекомендую поставить Delphi 10.1.2 Berlin.
      Вам нужно быть внимательнее и не торопиться. У вас ошибка в пути EMBO_DEX, сравните с тем, что лежит в моём архиве.
      Ошибку поняли в корне неверно. Никакие JAVA добавлять в com.android.dx.merge.DexMerger не нужно!
      Специально для таких случаев я написал Update в статье, создайте себе jar файл и забудьте про склейку classes.dex, вам не придётся его генерировать и клеить.

      Насчёт моих исходников:
      Обёртка не нужна! (Об этом я упоминаю в Updat'e) Какой в ней смысл?!
      Не нужно добавлять jar и dex файлы одновременно, делайте что-то одно, об этом написано в Updat'e.
      Про эмуляторы и т.п., я за них ответственности не несу. На всех устройствах, которые я использовал для тестирования, всё отлично работало. Тесты проводили и некоторые участники форума, всё заводится отлично.

      Удалить
    2. На всякий случай, добавил новый апдейт(Update 16.04.17)

      Удалить
    3. По поводу вашего "p.s.", ответ дан в официальной справке...
      https://developer.android.com/guide/topics/data/install-location.html#ShouldNot

      Конкретно вот эти предложения:
      Broadcast Receivers listening for "boot completed"
      The system delivers the ACTION_BOOT_COMPLETED broadcast before the external storage is mounted to the device. If your application is installed on the external storage, it can never receive this broadcast.

      Удалить
    4. У Вас он расположен по пути C:\Program Files\Embarcadero\Studio\17.0\lib\android\debug\classes.dex у меня в C:\Program Files нет папки Embarcadero только в директории C:\Program Files (x86) т.к у меня установлена Win 10 x64 по этому я и указывал путь C:\Program Files (x86)\Embarcadero\Studio\19.0\lib\android\debug\classes.dex. Добавил к своему пути имя файла classes.dex, но всё равно ошибка((. Подскажите может батник не понимает данный путь?
      Скриншот: http://redpro.site/myscr/555.jpg
      А так я вроде бы правильно понял? Создаём pas файл JavaInterfaces.pas и подрубаем его в Uses и после в проекте либо добавляем в Libraries созданный наш jar файл либо подрубаем наш созданный dex файл в Deployment в общем одно из двух? У меня сам jar создаётся и создавался только после загрузки в Libraries и после когда компилируешь даёт ошибку скриншот: http://redpro.site/myscr/4444.jpg.
      При создании батником тоже ошибка: http://redpro.site/myscr/1111.jpg.
      По этому вроде путь EMBO_DEX указываю верный, тогда в чём ошибка подскажите?
      P.S: Если не сложно дайте ссылку на Delphi XE5-Tokyo с Вашего сайта и так же на Update 16.04.17. Заранее спасибо! Христос Воскрес!

      Удалить
    5. Нет, дело не в пути, проверил у себя (на Berlin и на Tokyo), всё хорошо компилируется.
      Поняли не правильно, ещё раз повторяю, обёртка вам не нужна! (вы читали вообще сообщения/статью выше?!)
      Какую ссылку, я вам варезная/поисковая система что ли? Для этого есть яндекс и гугл.
      Про Update 16.04.17, речь идёт о статье! В статье я добавил доп. информацию от сегодняшнего числа.
      Вот ссылка на новый пример из статьи, в бат файл добавил параметр для совместимости JAVA версий (почему-то в статье старый архив был) В статье, ссылку на пример обновил.
      https://drive.google.com/open?id=0BwEZB8sRo0DScFc4eHQwQnZyaW8

      Удалить
  3. К стати запустил Ваш исходник и только удалил с Deployment classes.dex и test_classes.dex и поразительно всё заработало, появился интерфейс, при перезагрузке приложение висит почему то в фоновом режиме на заставке и когда нажимаешь на кноку домой ты видишь, что приложение запущено, но на заставке и только когда вызываешь его то только тогда оно полноценно запускается, а так к примеру если написать допустим какую то команду в TForm1.FormActivate то она после перезагрузки не сработает как в принципе и в TForm1.FormCreate. Может это правда очень сырая Delphi 10.2 и это в ней проблемы или я что то не то делаю((?

    ОтветитьУдалить
    Ответы
    1. Не знаю, что вы там наделали с исходником...
      В деплой менеджере должен быть только один classes.dex помечен галочкой. Я только что проверял проект, никаких test_classes.dex в деплое нет. Кстати, обновил архив с проектом, добавлена совместимость с JAVA 1.7-1.8.
      Нет, проблема явно не в Токио, а в том, что вы не знаете что делаете...

      Удалить
  4. А Ваш исходник без добавления dex файла на эмуляторе BlueStacks после перезагрузки запускается отлично ... только на мобиле после перезагрузки появляется в фоновом режиме и то на заставке(

    ОтветитьУдалить
  5. Очень интересно ... щас взял старый Samsung GT-S7262 и Ваш исходник заработал, при перезагрузки тоже отлично всё работает и не в фоновом режиме а как надо ..., но почему на моём DNS S5001 не хочет корректно работать (( Android OS стоит версия 4.2.1(((. Теперь я понял, что Ваш исходник работает всё отлично, если можно ответе на выше написанные вопросы где у меня в батники ошибка при создании своих файлов через бат файл?

    ОтветитьУдалить
    Ответы
    1. Читайте ответы выше.
      Если хотите консультацию или помощь, то только на платной основе. Заниматься бесплатно, целый день, вашей проблемой у меня нет желания.
      Ещё повторюсь, из проекта, выложенного в статье не нужно ничего удалять, всё отлично компилируется и запускается, проверил только что на Андроид 4.1.2 и 4.4.2.

      Удалить
    2. Сколько стоит час, оплачу без проблем в разумных приделах?
      Меня очень сильно интересует написание под OS Android и решил под данную OS научится писать да и надо т.к под OS Windows уже под заказ как лет 7 пишу, а с Android-ом не удаётся дружить ((.

      Удалить
    3. Вопрос решён в скайпе.

      Удалить
  6. Этот комментарий был удален администратором блога.

    ОтветитьУдалить