• 0
Roman V

ini Программа не запускается под Android

Вопрос

Всем привет. Учусь работать с ini-файлами на Android. И сразу же возникла проблема, которую никак не могу решить. Хотел написать подобие приложение-тест с хранением данных в ini файле. В итоге все отлично работает на windows,а под Андроид при запуске висит только значок firemonkey секунд 10 и приложение вырубается так и не запустившись. В чем может быть проблема? Использую отладку по USB. 

TIniFile *Ini = new TIniFile(System::Ioutils::TPath::GetDocumentsPath() + PathDelim + "options.ini");

Юзаю эти библиотеки 

#include <System.IOUtils.hpp>
#include <System.IniFiles.hpp>

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

25 ответов на этот вопрос

  • 0
#include <System.IniFiles.hpp>
#include <System.IOUtils.hpp>
#include <memory>

//****

   #ifdef __ANDROID__
   String path = System::Ioutils::TPath::Combine(System::Ioutils::TPath::GetSharedDownloadsPath(), L"options.ini");
   #elif _Windows
   String path = System::Ioutils::TPath::Combine(ExtractFilePath(ParamStr(0)), L"options.ini");
   #endif

   if(FileExists(path))
    {
      std::unique_ptr<TIniFile> FileINI(new TIniFile(path));
      String ip = FileINI->ReadString(L"HOST", L"ip", L"127.0.0.1");
//****

1. std::unique_ptr используется чтобы избавиться от delete. std::unique_ptr все делает сам.
2. Файл ini для Андроида надо сохранить в UTF-8.

Rusland, enatechno и Roman V понравилось это

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
2 часа назад, Kitty сказал:

.. ExtractFilePath(ParamStr(0)) ...

Думаю, для Windows предпочтительнее использовать GetDocumentsPath(), т.к.:
1). как правило, exe-файл лежит в папке находящейся в Program Files и для записи ini-файла рядом с exe понадобятся права администратора;
2). если работа ведется с разных рабочих столов, то каждый пользователь сможет иметь индивидуальные настройки, хранящиеся в ini-файле

Kitty понравилось это

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
3 часа назад, Kitty сказал:

if(FileExists(path))

На этой строчке выходит ошибка [bccaarm Error] Unit1.cpp(31): expected unqualified-id

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

Эта строка ни причем. Судя по ошибке, где-то ошибка в коде в синтаксе, например, пропущена где то точка с запятой ;

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
34 минуты назад, Kitty сказал:

Эта строка ни причем. Судя по ошибке, где-то ошибка в коде в синтаксе, например, пропущена где то точка с запятой ;

Не могу ничего найти, скорее всего ошибка в коде, что написал ты. Но блин, 20 раз уже проверил. Видимо я слепой)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

Доброго вечера. Уж не помню в какой версии, но если мне память не изменят я когда то натыкался на аткой косяк.

Ради спортивного интереса, перепишите строку проверку таким макаром

int check = FileExists(path);
if(check == 1)
{
//
}

я ПОНИМАЮ, что это бред, но попробовать то можно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
51 минуту назад, Gingercat сказал:

я ПОНИМАЮ, что это бред, но попробовать то можно.

Не прокатило((

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

Компилируется если закомментировать саму проверку. Но далее все равно прога на андроиде не запускается (только значок файерманки висит). А на винде все так же отлично работает. 

Изменено пользователем Roman V

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
15 часов назад, Roman V сказал:

На этой строчке выходит ошибка [bccaarm Error] Unit1.cpp(31): expected unqualified-id

Покажите ваш код

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

Похоже на отсутствие прав чтения /записи в Андроиде.
Проверьте : Project - Options - Uses Permission - Read external storage (Write external storage)

P.S. Когда задаете вопрос, указывайте версию RAD, версию Android и устройство на котором тестируете

Изменено пользователем enatechno
Anatoliy понравилось это

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
26 минут назад, enatechno сказал:

P.S. Когда задаете вопрос, указывайте версию RAD, версию Android и устройство на котором тестируете

Запускаю на Lenovo A806, Android 4.4.2. Кастомная Lewa OS. Пробовал запускать другой код. Все работает. Однако с ini не хочет. Все галочки стоят.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
51 минуту назад, Rusland сказал:

Покажите ваш код

По сути весь основной код уже сверху написан

#ifdef __ANDROID__
String path = System::Ioutils::TPath::Combine
	(System::Ioutils::TPath::GetSharedDownloadsPath(), L"options.ini");
#elif _Windows
String path = System::Ioutils::TPath::Combine(ExtractFilePath(ParamStr(0)),
	L"options.ini");
#endif

if (FileExists(path)) {
	std::unique_ptr <TIniFile> Ini(new TIniFile(path));
	String ip = Ini->ReadString(L"HOST", L"ip", L"127.0.0.1");
}
int butId; // номер вопроса

Далее идет код, который передает данные с ini на кнопки. 

void __fastcall TForm1::FormShow(TObject *Sender) {
	Form1->Updated();
	Form1->Updating();
	Button1->Text = Ini->ReadString(butId, "Ответ1", "Def");
	Button2->Text = Ini->ReadString(butId, "Ответ2", "Def");
	Button3->Text = Ini->ReadString(butId, "Ответ3", "Def");
	Button4->Text = Ini->ReadString(butId, "Ответ4", "Def");
	right = StrToInt(Ini->ReadString(butId, "right", "0"));
	Image1->Bitmap->LoadFromFile("img\\" + IntToStr(butId) + ".jpg");
	Label1->Text = butId;
}

Ну и еще там по мелочи. Все писать не буду. Т.к. в остальном ini не фигурирует.

Anatoliy понравилось это

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
В 26.10.2017 в 15:40, Kitty сказал:

1. std::unique_ptr используется чтобы избавиться от delete. std::unique_ptr все делает сам.
2. Файл ini для Андроида надо сохранить в UTF-8.

Спасибо большое! У тебя все правильно). Сегодня решил еще раз зайти и посмотреть со свежей головой. И вот, оказывается я не туда писал код просто. Приложение теперь запускается на Андроиде, но как мне создать файл ini во внутренней папке андроида? Если поместить файл ini в asset, то при компиляции все из этой папки удаляется, и приложение запускается без необходимых данных. Как решить эту беду. Как сделать так, чтобы файл считывался из папки assets?)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

За это отвечает Deployment.

Добавьте нужные файлы, укажите путь и все.

Подробнее смотрите http://docwiki.embarcadero.com/RADStudio/Berlin/en/Deployment_Manager и http://docwiki.embarcadero.com/RADStudio/Berlin/en/Creating_an_Android_App#Loading_and_Deploying_Files

Так же есть статья в блоге Андрея Ефимова http://delphifmandroid.blogspot.ru/2014/02/deployment-manager.html

Rusland, Anatoliy, Roman V и 1 другому понравилось это

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
6 часов назад, mazayhin сказал:

Добавьте нужные файлы, укажите путь и все.

Не до конца понял как с этим работать. Шаги: пишу код 

#ifdef __ANDROID__
	String path = System::Ioutils::TPath::Combine
		(System::Ioutils::TPath::GetDocumentsPath(), L"options.ini");

->добавляю файл в Deployment Manager ->указываю путь(assets internal), кидая в папку assets файл-ini->нажимаю Deploy. После этого файл-ini из папки удаляется и сама строка становится не активной. И при запуске естественно приложение сразу же вырубается так и не запустившись. Что я делаю не так? И да. Пробовал класть ini файл в другую директорию, и загружать оттуда, но в Remote Path все равно указывал assets\internal. В таком случае строка остается активной, однако приложение не запускается...

Безымянный.png

Изменено пользователем Roman V
Забыл кое-что упомянуть

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 1

Судя по скринам ini-файл берется из папки Android\Debug. Зачем так делать? Эту папку создает сама студия. Возможно что Clean очищает все содержимое в этой папке и строка становится неактивной, потому что файла больше нет.

 

19 часов назад, Roman V сказал:

Пробовал класть ini файл в другую директорию, и загружать оттуда, но в Remote Path все равно указывал assets\internal. В таком случае строка остается активной, однако приложение не запускается...

Какую ошибку при этом выдает?

Andrey Efimov понравилось это

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
1 час назад, Rusland сказал:

Какую ошибку при этом выдает?

Вот щас попробовал вообще попробовал в левую папку кинуть ini файл и задеплоудить. Строка остается активной, однако на андроиде проект не запускается, хоть и компиляция проходит успешно...

Изменено пользователем Roman V

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

Что значит не запускается? В режиме дебаг что-то выдает наверное...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
6 минут назад, Rusland сказал:

Что значит не запускается? В режиме дебаг что-то выдает наверное...

Компиляция проходит успешно. Но итоге все отлично работает на windows,а под Андроид при запуске висит только значок firemonkey пару секунд и приложение вырубается так и не запустившись. Debug чист.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

Вообще никаких сообщений не показывается?

Debug.png.76c072d8cefeabbfddf8405f302d1d6b.png

Тогда только смотреть через monitor.bat, что там происходит с приложением.

Anatoliy понравилось это

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
1 час назад, Rusland сказал:

Вообще никаких сообщений не показывается?

Блин. Я вообще не понимаю что с этим андроидом. Оказывается он ругался на загрузку картинки. Так вот я закомментировал строку загрузки картинки щас. Теперь прога запускается, однако почему то не считывает данные с ini файла((((. Юзаю этот код. Однако в конченом результате на экране выводится только Def, Def, Def, Def. А то что под ключем "Ответ1" вообще игнорится...(( 

void __fastcall TForm1::FormShow(TObject *Sender) {
	Form1->Updated();
	Form1->Updating();
	Button1->Text = Ini->ReadString(butId, "Ответ1", "Def");
	Button2->Text = Ini->ReadString(butId, "Ответ2", "Def");
	Button3->Text = Ini->ReadString(butId, "Ответ3", "Def");
	Button4->Text = Ini->ReadString(butId, "Ответ4", "Def");
	right = StrToInt(Ini->ReadString(butId, "right", "0"));
	//Image1->Bitmap->LoadFromFile("img\\" + IntToStr(butId) + ".jpg");
	Label1->Text = butId;
}

 

Безымянный.png

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

во-первых, \ это только у windows разделитель
во-вторых, вы просите прочитать файл 1.jpg из папки /img в корне файловой системы ?

нет у вас никаких прав на это.

прочтите документацию по модулю ioutils

Anatoliy понравилось это

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
4 часа назад, krapotkin сказал:

прочтите документацию по модулю ioutils

Спасибо за информацию (приму к сведению), но щас я хочу разобраться именно с ini. А именоо почему у меня не считываются данные с ini файла. )

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

Скорее всего проблема в том, что вы используете русские буквы: 

Ответ1

Ответ2

Ответ3

...

Возможно проблема в кодировке файла. Она должна быть utf8.

Лучше замените буквы на латинские:

Otvet1

Otvet2

Otvet3

...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
13 часа назад, Roman V сказал:

Спасибо за информацию (приму к сведению), но щас я хочу разобраться именно с ini. А именоо почему у меня не считываются данные с ini файла. )

Вы уверены что загружаете файл по правильному пути? Он точно там существует? При отсутствии файла, будет выдаваться значение по-умолчанию.

В какой он кодировке? Если кодировка не UTF-8, попробуйте указать в конструкторе верную (ту, в которой на самом деле файл).

Проверьте банально (на С++ перепишите):

if TFile.Exists(TPath.Combine(TPath.GetDocumentsPath,'inifile.ini')) then
  showmessage('file found') else
  showmessage('file not found');

Были ли значения в файле, когда у вас первый раз получилось его задеплоить? При обновлении приложения, если файл есть на устройстве, он не обновляется сам, надо или очистить в настройках, или сделать это все руками.

Проверьте что вообще в нем записано, да тем же TFile.ReadAllText('путь к файлу', 'кодировка'). Ну и если его "там" не будет, то как раз словите исключение...

P.S.: специально сейчас проверил, с русскими ключами проблемы нет, все читается. С кодировкой тоже, читает и ANSI и UTF-8 и Win-1251, в конструкторе даже не указывал кодировку.

 

Изменено пользователем mazayhin

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте аккаунт или войдите для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!


Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.


Войти сейчас

  • Похожие публикации

    • Автор: om.pranayama
      Здравствуйте форумчане и профессионалы разработчики.
      Компилирую проект через C++Builder 10.2  под Android
      Появилась следующая проблема при использовании компонента TBitmapListAnimation
      Если приложение свернуть, а затем развернуть - то появляются жуткие глитчи в ввиде чёрных фонов вокруг компонентов, типа TImage, TButton.
      В Windows такая проблема - не наблюдается.
      Попытки вызвать Repaint или даже Invalidate для всей формы - положительного результата не дают.
      Пожалуйста, помогите решить эту проблему.
      //--------------------------------------------------------------------------------------------------------------------------------------------
      ТЕМУ МОЖНО УДАЛЯТЬ
      Причина не в TBitmapListAnimation а в TAniIndicator, который работал совместно с TBitmapListAnimation.
      Приношу извинения за беспокойство. Проблема была в TAniIndicator. Буду разбираться почему он так себя безобразно ведёт.
      Тему можно удалять.
    • Автор: Aptyp
      В приложении:
          procedure TForm7.Button1Click(Sender: TObject);     var AIntent: JIntent;         AServiceName: string;     begin       AIntent := TJIntent.Create;       AServiceName := 'com.embarcadero.services.Service';       AIntent.setClassName( TAndroidHelper.Context.getPackageName(), TAndroidHelper.StringToJString( AServiceName ) );       AIntent.putExtra( TAndroidHelper.StringToJString( 'Code' ), 0 );       AIntent.putExtra( TAndroidHelper.StringToJString( 'Data' ), TAndroidHelper.StringToJString( 'DataString' ) );       TAndroidHelper.Activity.startService( AIntent );     end;
      В сервисе:
          procedure TDM.AndroidIntentServiceCreate(Sender: TObject);     begin       Toast( 'Create' );     end;          procedure TDM.AndroidIntentServiceHandleIntent(const Sender: TObject;       const AnIntent: JIntent);     begin       Toast( 'HandleIntent' );     end; Сообщение 'Create' показывается, а 'HandleIntent' нет. OnCreate срабатывает, но onHandleIntent не вызывается что бы я не делал. Может я что-то не так делаю?
    • Автор: gonzales
      Доброго времени суток!
      Решаю следующую задачу, в приложении динамически формируются разные объекты, наследники от одного класса. При формировании объектов заполняется динамический массив этих элементов. Далее я хочу в отдельном потоке для каждого из элементов массива получить его состояние, то есть делаю запрос к серверу. Все это повешено на таймер, каждую секунду должен отрабатываться запрос. Все более менее работает в Windows, а на Андроиде со временем приложение валится. Вот код таймера, для читаемости я удалил куски с различными вариантами E. RootElements - это массив TEssense от которого есть наследники. Функции GetBoardCurrentValue, GetBoardMaxValue - по сути запросы к серверу. 
      Подскажите, правильно ли я оформляю работу с потоками для работы на Андроиде?
      procedure TForm1.MasterTimerTimer(Sender: TObject); begin TTask.Run( procedure var l, d, a: byte; i,j:integer; E: TEssence; p: Pointer; VirtualNode: IXMLNode; VirtualElementNode: IXMLNode; id: byte; begin l := Length(Form1.RoomElements); for j := 0 to l - 1 do begin E := Form1.RoomElements[j]; // Реле if E is TRele then begin d := (E as TRele).Device_ID; a := (E as TRele).Device_Adress; if Form1.GetBoardCurrentValue(d, a) = true then begin TThread.Synchronize(nil, procedure begin (E as TRele).ReleSwitch.IsChecked := Form1.device[d].Board[a].CurrentValue.ToBoolean; end); end; // (E as TRele).ReleOnTimer(E) end // Диммер else if E is TDimmer then begin d := (E as TDimmer).Device_ID; a := (E as TDimmer).Device_Adress; if Form1.GetBoardMaxValue(d, a) = true then begin TThread.Synchronize(nil, procedure begin if (Form1.device[d].Board[a].Type_ID = TType.Светодиод) or (Form1.device[d].Board[a].Type_ID = TType.Диммер220) then begin (E as TDimmer).DimmerValue.Text := (Form1.device[d].Board[a].MaxValue).ToString; end; end); end; // (E as TDimmer).DimmerOnTimer(E) end // Таймер else if E is TSTimer then begin id := (E as TSTimer).STimerIndex; Form1.FillHTTPRequest(0, 0, HTTP_GET_TIMER_INFO, id); if Form1.AnswerIsComming = HTTP_GET_TIMER_INFO then begin TThread.Synchronize(nil, procedure begin if Form1.HTTPAnswer.Data1 = 0 then (E as TSTimer).Interval.Text := 'OFF' else (E as TSTimer).Interval.Text := 'ON' end); end; // (E as TSTimer).STimerOnTimer(E); end; end; end); end;   
    • Автор: andahay
      Доброго времени суток. Есть android приложение, в нем есть диалоговое окно, которое предлагает перейти в google play и скачать другое приложение (pro версию), с 2 кнопками (да/нет). Как реализовать этот переход в Google play, чтобы в нем сразу было загружено нужное приложение. Использую Delphi XE7
    • Автор: zekelive
      Добрый день, друзья. Начал заниматься вопросом описанным в шапке и столкнулся со множеством непонятных для меня проблем. Как примерно должно выглядеть на Рис. ниже. Знаю, что сам список барабан выполнен в TlistBox. Есть хорошая ссылка на блог Ярослава тут. Пошерстил файлы в FMX, и не нашел ключа для своего дела. Может кто занимался этим? Я изначально брал TScrollBox, кидал на него Tlayout и в него TLabel. Но думаю, видимо не то совсем.

    • Автор: zekelive
      Добрый день. Кто знает, подскажите, можно ли средствами firemonkey менять иконку приложения в рантайм либо после закрытия и повторного открытия приложения? На win вроде бы можно, статьи на форуме находил, а для Андроида найти не удалось.
    • Автор: bossalex
      Недавно компилил приложение на Delphi  FMX Android  при обращении  к серверу https при выполнении Get запроса от компонента TIdHttp запросил библиотеку "Could not load SSL library" используется протокол sslvTLSv1_2 в windows все пашет в андроид нет , накопал что можно подключить библиотеки  libssl.so и  libcrypto.so через  deployment .assets\internal , А вот как в коде дальше их использовать никто примерчик не выложил, хоть и обсуждали на интернет просторах 100 раз, те как прикрутить  к IdSSLIOHandlerSocketOpenSSL1.SSLOptions.CertFile. Если есть у кого код выложите пожалуйста? или скинте по email bossalex@ya.ru
      IdSSLIOHandlerSocketOpenSSL1.SSLOptions.Method.sslvTLSv1_2;
      IdSSLIOHandlerSocketOpenSSL1.SSLOptions.Mode.sslmUnassigned;
       
    • Автор: zekelive
      Добрый день, друзья. Подскажите, есть ли возможность в firemonkey открыть форму как представлено на картинке ниже? Если да, то подскажите в какую сторону копать. Спасибо.

    • Автор: Rustam Bikeev
      Суть проблемы следующая: после перехода с одной вкладки на другую в tabcontrol страница не отображается, фактически она переключается но на экране отображается предыдущая вкладка с которой был переход, ровно до той поры пока на что нибудь не клацнешь, нужно либо нажать на кнопку в тулбаре либо открыть multiview. После того как я первый раз с этим столкнулся я так и делал программно открывал и закрывал multiview, но не могу же я так делать постоянно, нужно решить проблему. Для подробности напишу, что есть основной tabcontrol в котором вкладки открываются из multiview, во вкладках есть вложенные tabcontrol-ы, со своими страницами в основном по 2 страницы. 
      Зря я начал делать приложения в делфи... чем дальше в лес тем больше дров.
    • Автор: Alex7wrt
      Добрый день
      Как заставить TMediaPlayer воспроизводить MPG файлы под Windows? MP4 воспроизводит, а mpg не хочет. Установлены кодеки KLite.
      Добавление строки 
      TMediaCodecManager.RegisterMediaCodecClass('.mpg', 'MPEG Video', TMediaType.Video, TWindowsMediaCodec); не помогает. 
  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу