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

ENERGY

Пользователи
  • Постов

    568
  • Зарегистрирован

  • Посещение

  • Победитель дней

    57

Весь контент ENERGY

  1. Project > View Source - и там можете менять очередность запуска форм, или вообще создать одну, а затем подгружать нужные, если их много. Так даже экономней. Установите форме Visible false. А затем когда нужно меняйте на true из формы загрузки.
  2. Как создать простейший Android Broadcast Receiver. Создайте класс, для приема Intent уведомлений: uses Androidapi.JNIBridge, Androidapi.JNI.Embarcadero, Androidapi.JNI.GraphicsContentViewText; type TMyReceiver = class(TJavaLocal, JFMXBroadcastReceiverListener) public constructor Create; procedure onReceive(context: JContext; intent: JIntent); cdecl; end; uses Androidapi.Helpers, Androidapi.JNI.JavaTypes; { TMyReceiver } constructor TMyReceiver.Create; begin inherited; end; procedure TMyReceiver.onReceive(context: JContext; intent: JIntent); begin Log.d('Broadcast Received = ' + JStringToString(intent.getAction)); end; Регистрируем тип уведомлений и приемник в событиях формы: type TForm1 = class(TForm) procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); private { private } FMyListener: TMyReceiver; FBroadcastReceiver: JFMXBroadcastReceiver; public { public } end; procedure TForm1.FormCreate(Sender: TObject); var Filter: JIntentFilter; begin FMyListener := TMyReceiver.Create; FBroadcastReceiver := TJFMXBroadcastReceiver.JavaClass.init(FMyListener); Filter := TJIntentFilter.JavaClass.init; Filter.addAction(TJIntent.JavaClass.ACTION_SCREEN_OFF); Filter.addAction(TJIntent.JavaClass.ACTION_SCREEN_ON); TAndroidHelper.context.getApplicationContext.registerReceiver (FBroadcastReceiver, Filter); end; procedure TForm1.FormDestroy(Sender: TObject); begin TAndroidHelper.context.getApplicationContext.unregisterReceiver (FBroadcastReceiver); end; Все. Теперь когда вы запустите программу и выключите\включите экран, лог покажет : FMX: BroadcastSample: Broadcast Received = android.intent.action.SCREEN_OFF FMX: BroadcastSample: Broadcast Received = android.intent.action.SCREEN_ON Takashi Yamamoto
  3. Ссылка на barisatalay указан битая. Не открывает. Вот правильная: https://github.com/barisatalay/delphi-android-broadcast-receiver-component Кстати после компиляции под Berlin и запуском на 4 Android телефон у меня перезагрузился. Между прочим начиная с Berlin - появился пример Samples\Object Pascal\Mobile Snippets\AndroidIntents\
  4. Фух. Наконец то проспался и понял как сделать. Нужно просто поставить Alarm еще раз, напр. чтобы выполнился через 3 секунды. (неудобный, есть вероятность попасть на ошибку) просто вызвать его в Broadcast после Activity . (не всегда работает) Запустить Activity и в BroadcastReceiver подождать 8 секунд, а затем там же снять WakeLock. Это вариант работает прекрасно. Также с этим кодом Alarm срабатывает если Activity уже запущено либо в фоне. Нужно перехватывать WillBecomeForeground, BecameActive и там включать экран. Процессор включается в WakeLock, но не на долго, вам нужно включить экран при помощи функции ниже, сделать работу затем отключить экран). В моем случае, в отдельном потоке крутиться самописный планировщик, для других задач, который возбуждает события, по нему я и включаю\отключаю экран. Итак выстраданный бесcонными ночами Java код, обратите внимание на TestLauncher.putExtra("StartedFromAM", true), это чтобы знать из Activity что запустились из Broadcast (предложенный Blong'гом EXTRA_ALARM_COUNT с BroadcastReceiver всегда вернет ноль, он работает только если запускать напрямую Activity!) : package com.TestReceiver; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.PowerManager; import android.os.Handler; public class AlarmReceiver extends BroadcastReceiver { private static PowerManager.WakeLock mWakeLock; @Override public void onReceive(Context context, Intent intent) { if (mWakeLock == null) { PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Delphi"); mWakeLock.acquire(); } Intent TestLauncher = new Intent(); TestLauncher.setClassName(context, "com.embarcadero.firemonkey.FMXNativeActivity"); TestLauncher.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); // I TestLauncher.putExtra("StartedFromAM", true); context.startActivity(TestLauncher); // Handler h = new Handler(); h.postDelayed(new Runnable(){ public void run(){ mWakeLock.release(); mWakeLock = null; } }, 8000); //Toast.makeText(context, "Reelase! ("+mcounter.toString()+")", Toast.LENGTH_SHORT).show(); // For example } } PARTIAL_WAKE_LOCK означает что процессор во время выполнения этого кода, не будет уходить в спящий режим. Теперь в OnCreate нашей формы добавляем флаги чтобы включить экран, но при условии что запустились мы из AlarmManager : function StartedFromAlarmManager: boolean; begin {$IFDEF ANDROID} Result := TAndroidHelper.Activity.getIntent.getBooleanExtra(StringToJString('StartedFromAM'), false); // this will work only if using Activity instead of Broadcast - TJPendingIntent.JavaClass.getActivity: // Result := TAndroidHelper.Activity.getIntent.getIntExtra(TJIntent.JavaClass.EXTRA_ALARM_COUNT, 0); {$ELSE} Result := false; {$ENDIF} end; {$IFDEF ANDROID} procedure TurnOnAndKeepScreenAndroid(aEnable: boolean); var vFlags: integer; begin vFlags := TJWindowManager_LayoutParams.JavaClass.FLAG_TURN_SCREEN_ON or TJWindowManager_LayoutParams.JavaClass.FLAG_DISMISS_KEYGUARD or TJWindowManager_LayoutParams.JavaClass.FLAG_SHOW_WHEN_LOCKED or TJWindowManager_LayoutParams.JavaClass.FLAG_KEEP_SCREEN_ON; if aEnable then begin CallInUIThread ( // uses FMX.Helpers.Android procedure begin TAndroidHelper.Activity.getWindow.setFlags (vFlags, vFlags); end ); end else CallInUIThread ( procedure begin TAndroidHelper.Activity.getWindow.clearFlags (vFlags); end ); end; {$ENDIF} И сразу же отключаем наш WakeLock устанавливая второй раз Alarmmanager на срабатывание через 3 сек (соответственно запуститься BroadcastReceiver и освободит WakeLock). (уже отключается сам в Broadcast сразу после старта Activity)- т.к. во флагах окна, уже указан FLAG_KEEP_SCREEN - это будет держать экран и систему включенной. Не забудьте поставить разрешение WAKE LOCK = true!
  5. Ребят, а можете отозваться у кого работает без Wake Lock? Возможно у автора статьи, ведь Андрей даже никаких намеков не давал. Я просто удивлен что никто с этим не сталкивался.
  6. Блин, проблема. Уже сутки не могу решить. Если телефон подключен к USB - то Alarm запускает активити. Если он на батареях, то он спит себе дальше и ничего не происходит. Ну понятно почему, - на батареях он уходит в sleep режим. Я уже пробовал и WakeLock и флаги FLAG_TURN_SCREEN_ON or FLAG_DISMISS_KEYGUARD or FLAG_SHOW_WHEN_LOCKED.- все в OnCreate (даже до и после Application.Initialize пробовал), пробовал и первый и второй метод со статьи (Activity и BroadcastReceiver) Проблема в том, что когда срабатывает RTC - система просыпается, но просыпается ненадолго. Где то на 2-3 секунды. Т,е. фактически не доходит до кода с WakeLock или кода с флагами (я уже пробовал его и до и после инициализации). Есть один рабочий вариант - ставить WakeLock в java коде с BroadcastReceiver (это кстати рекомендованный способ для запуска сервисов) - это работает, я пробовал, но я пока не знаю как отключить его. Пример Возможно у кого то есть рабочий вариант? Был бы очень благодарен. Странно что никто об этом не говорил..
  7. Можно его и напрямую получить, через пайпы (Pipe StdOut) - т.е. консоль будет перенаправлять вывод в вашу программу, только особого смысла нет, больше кода, на производительность это вообще не повлияет. Такие мелкие файлы будут висеть в кэше они не сбрасываются на диск сразу.
  8. SerhioUser Через cmd.exe запускайте. Т.е. пишите строку в ShellExecute : cmd.exe aapt dump badging myapp.apk > mytextfile.txt . Если не получится, сделайте bat файл, и запускайте его.
  9. Используйте NOX - самый быстрый эмулятор. На нем также будут работать Delphi программы (проверял). BlueStacks медленнее. На нем тоже будут работать Delphi программы. Минус эмуляторов - вы не сможете делать отладку. Плюс на телефоне все равно быстрее будет, наверное
  10. aapt dump badging myapp.apk > mytextfile.txt Вот эта команда "> mytextfile.txt" 100% сохранит весь вывод консоли в файл. Сначала протестируйте свою command line cтрочку в cmd.exe, потом вставьте ее в ShellExecute
  11. Ну какие под Windows могут быть стандартные средства для чтения файла из другой ОС? Конечно их нету. Делается элементарно. 1. apk - это обычный zip файл. Распаковываете его (в Delphi встроенная поддержка zip - uses System.Zip > TZipFile ), и читаете все что надо. В Total Commander в такие архивы проще заходить без переименования расширения - нажав Ctrl + PgDown 2. Еще проще aapt dump badging myapp.apk Выведет детальную информацию об apk. aapt лежит где то в c:\Users\<user>\Documents\Embarcadero\Studio\18.0\PlatformSDKs\android-sdk-windows\build-tools\25.0.0\aapt.exe Например чтобы сохранил результат в файл: aapt dump badging myapp.apk > mytextfile.txt В первой строчке и будет искомое: package: name='com.embarcadero.MyApp' versionCode='1' versionName='1.0.0' platformBuildVersionName=''
  12. Чтобы картинка была на всю кнопку - вообще картинки должны быть фиксированного размера, когда одна больше, другая меньше - это смотрится криво. Но если очень нужно тогда так (это для Firemonkey, не для VCL): Бросайте рядом TGlyph - затем в инспекторе объектов мышкой перемещаете его на кнопку. В результате TGlyph должен быть внутри кнопки (TSpeedButton или TButton). Далее настраиваете TGlyph - указываете там ImageList, ImageIndex (можно картинку и без ImageList указать отдельно, там есть соответствующее поле), далее свойство Stretch и Align = Client.
  13. Major Под Android, iOS, MacOS - TIniFile это все тот же TMemIniFile: {$IFDEF MSWINDOWS} { TIniFile - Encapsulates the Windows INI file interface (Get/SetPrivateProfileXXX functions) } TIniFile = class(TCustomIniFile) public [...] end; {$ELSE} TIniFile = class(TMemIniFile) public [...] end; {$ENDIF}
  14. Спасибо Ярослав! Есть еще одна статья от GunSmoker на эту тему. Там есть ряд интересных ньюансов, которые не описаны у Ярослава и о которых многие не знают. К примеру то, что DisposeOf хотя и вызывает деструктор, но не освобождает память выделенную под объект..
  15. Это спорный момент. При написании мултиплатформенной программы, в Windows - GetDocumentsPath вернет c:\Users\<username>\Documents\ . Пользователь может удалить оттуда данные случайно - т.к. это папка "Мои документы". Лучше TPath.GetHomePath\имя программы - напр. для Adobe в Windows это c:\Users\<username>\AppData\Roaming\Adobe\ Для андроида GetHomePath и GetDocumentsPath вернут одинаковый путь. В MacOS, iOS и Windows - это разные пути. Здесь описание всех путей. + Для андроида GetDocumentsPath; - /data/data/com.myapp.app1/files GetDownloadsPath; - /storage/emulated/0/Android/data/com.myapp.app1/files/Download GetHomePath; - /data/data/com.myapp.app1/files GetSharedDocumentsPath; - /storage/emulated/0/Android/data/com.myapp.app1/files GetLibraryPath; - /data/data/com.myapp.app1/files GetPublicPath; - /storage/emulated/0/Android/data/com.myapp.app1/files GetPicturesPath; - /storage/emulated/0/Android/data/com.myapp.app1/files/Pictures Ну и кто еще не в курсе - сохранять удобней всего в TMemIniFile из юнита IniFiles. Реестра в Unix системах нет (а это MacOS, iOS и Android), там все на файлах.
  16. Кривая реализация TSwitch, тоже столкнулся с этим. Тут проблема в том, что компонент после вызова своих событий (OnSwitch напр) продолжает анимацию, и даже если поменять в OnSwitch на Switch1.IsChecked := false; ничего не измениться, т.к. еще не закончилась анимация на предыдущий статус True. Чтобы изменить значение в OnSwitch или в OnClick - на нужное: TThread.CreateAnonymousThread ( procedure begin TThread.Queue( nil , procedure begin Switch1.IsChecked := false; end ); end ).Start; Админ почему то закрыл такую же тему, хотя вопрос не был решен.
  17. Установите - Stylelookup у каждого Item'a - listboxitemnodetail или listboxitembottomdetail Detail - обозначает что появляется еще одна дополнителная текстовая строка, bottom detail переводится как "детали внизу". Добавить текст в нее можно через инспектор - кликните на нужный listitem > ItemData > Detail listboxitemleftdetail - содержит еще одну текстовую панельку справа, которая перекрывает основной текст. Вы можете сделать эти пункты в своем стиле - добавить туда визуальные компоненты, такие как Tswitch, кнопки итд. Для этого, - Нажмите правой кнопкой мыши (ПКМ) по листбоксу - Add ListBoxitem, выберите для этого Item'a нужный стиль, в Stylelookup, на основе которого хотите сделать свой. Далее, ПКМ по Item - Edit Custom Style. Выделите в инспекторе ListBoxItem1Style1 - это ваш новый стиль, можете переименовать его в StyleName на нужное вам имя. Это имя потом указывайте в StyleLookup каждого item'a. Теперь можно переносить мышкой компоненты на этот шаблон. Имена меняйте в StyleName. По этим именам потом можно обращаться к ним таким образом: vItem.StylesData['descript'] := 'text'; vItem.StylesData['details'] := 'Text'; vItem.ImageIndex := 5; Чтобы отображался картинка при помощи ImageIndex в таком собственном Item е - нужно кинуть TGlyph и назвать Stylename как 'glyphstyle'. TListBox довольно медленный компонент, и нужен в основном для небольших списков (напр. настройки) или там, где используются Items с контролами. Для динамических списков используйте TListView.
  18. Ни мануала, ни строчки описания.. 1. А можно посмотреть на Java код? 2. Как получить в таком коде getResultCode (Activiy Result) - например в Java это пишется так (код отсюда): private BroadcastReceiver receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (SENT.equals(intent.getAction())) { String name = intent.getStringExtra("name"); String number = intent.getStringExtra("number"); switch (getResultCode()) { case Activity.RESULT_OK: toastShort("SMS sent to " + name + " & " + number); break; case SmsManager.RESULT_ERROR_GENERIC_FAILURE: toastShort("Generic failure"); break; детали для Delphi в этом вопросе. Спасибо.
  19. А можно как то вызвать getResultCode из Delphi? Чтобы не отправлять результаты из Java кода в Delphi при помощи PutExtra Код Java: private BroadcastReceiver receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (SENT.equals(intent.getAction())) { String name = intent.getStringExtra("name"); String number = intent.getStringExtra("number"); switch (getResultCode()) { case Activity.RESULT_OK: toastShort("SMS sent to " + name + " & " + number); break; case SmsManager.RESULT_ERROR_GENERIC_FAILURE: toastShort("Generic failure"); break; case SmsManager.RESULT_ERROR_NO_SERVICE: toastShort("No service"); break; case SmsManager.RESULT_ERROR_NULL_PDU: toastShort("Null PDU"); break; case SmsManager.RESULT_ERROR_RADIO_OFF: toastShort("Radio off"); break; } } else if (DELIVERED.equals(intent.getAction())) { switch (getResultCode()) { case Activity.RESULT_OK: toastShort("SMS delivered"); break; case Activity.RESULT_CANCELED: toastShort("SMS not delivered"); break; } } } };
  20. А если поставить гестуру на ListBox, который на MultiView и закрывать его по гестуре. Тут даже подойдет обычный OnTap\OnClick по идее - если нажали не по Item - то закрываем..
  21. Надо было назвать тему TListView OnItemClick и Long Tap, т.к. для остальных гестур все работает. А что если использовать OnTap и определять по координатам текущий Item?
  22. Зачем придумывать сложности на ровном месте. MultiView закрывается если тапнуть на правую панель, также можно сделать чтобы она закрывалась по тапу по незаполненному участку TListBox (который представляет меню TMultiView ). Хотя можно сделать чтобы MV закрывался проведя по нему пальцем, просто никогда такой задачи не стояло - почему вам тапа не достаточно.
  23. Нашел код на Java, вроде более менее понятно. http://stackoverflow.com/questions/24673595/how-to-get-sms-sent-confirmation-for-each-contact-person-in-android буду разбираться.. Видимо забирать значения нужно вызывая getResultCode в java коде, и придется забрасывать значения через PutExtra в моё Activity и там их обрабатывать (по таймеру проверять пришли новые значения или нет в случае если прога уже запущена?). Может у кого то есть другое решение? К примеру проверять этот Activity Result из Delphi ? К примеру вот эта статья http://blong.com/Articles/DelphiXE6AndroidActivityResult/ActivityResult.htm (глава Communication from the launched activity) случайно не про извлечение Activity Result из Delphi ?
  24. Привет. Для отправки смс используется SMSManager и его функция. smsManager.sendTextMessage(smsTo, nil, StringToJString('Test SMS'), nil, nil); Описание ее на сайте developer.android.com . Для того чтобы узнать статус отправлена смс или нет, нужно указать предпоследний параметр sentIntent PendingIntent: if not NULL this PendingIntent is broadcast when the message is successfully sent, or failed. The result code will be Activity.RESULT_OK for success, or one of these errors: RESULT_ERROR_GENERIC_FAILURE RESULT_ERROR_RADIO_OFF RESULT_ERROR_NULL_PDU. Я также нашел описание как добавить этот параметр на StackOverflow, но там не указаны детали. Вот что пишет этот человек: You have to createIntent objects first, THEN create PendingIntent objects to wrap those Intent objects, THEN pass the PendingIntent objects to sendTextMessage() and use a broadcastReceiver to receive the Intent objects. Итак я создаю интент, и оборачиваю его в PendingIntent по аналогии со статьей Андрея Ефимова: // Создаём Интент Intent := TJIntent.Create; Intent.setClassName(TAndroidHelper.Context, StringToJString('com.TestReceiver.AlarmReceiver')); // Оборачиваем Интент в PendingIntent PendingIntent := TJPendingIntent.JavaClass.getBroadcast(TAndroidHelper.Context, 1, Intent, 0); И вставляю это PendingIntent в код sendTextMessage Когда вернутся код ошибки SMS, то насколько я понял сработает ява код, на который зарегистрирован прием: package com.TestReceiver; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; public class AlarmReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { Intent TestLauncher = new Intent(); TestLauncher.setClassName(context, "com.embarcadero.firemonkey.FMXNativeActivity"); TestLauncher.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(TestLauncher); } } Вопрос в следующем: Как мне эту цифру с ошибкой Activity.RESULT_OK (или RESULT_ERROR_GENERIC_FAILURE или любой другой) вытащить оттуда и передать в программу? Upd1: Это результат вызова из Java кода метода getResultCode(). Можно ли getResultCode вызвать из Delphi, а не из Java кода?
  25. Ребят вы меня удивляете. Зачем перезапускать или искать в меню итп, если можно выбрать рабочий стол по умолчанию (Default Layout). Все эти панельки, их расположение\размеры - все можно сохранить-загрузить оттуда (подсказка при наведении курсора: Desktop Speedsetting).
×
×
  • Создать...