-
Постов
75 -
Зарегистрирован
-
Посещение
-
Победитель дней
1
Сообщения, опубликованные Андрей Рулин
-
-
В ходи анализа обнаружилось, что первый раз приложение открывается в любом положении экрана. Потом , если нажать кнопку "Выход", в которой выполняется метод Close; , то потом эта проблема и возникает.
-
Очередная "чуча" от fmx(Delphi 10 Seattle)
Если просто читать без потока , кода работает на обоих платформах
begin if ThreadFile.BytesReady<=ThreadFile.Counter then begin BlockRead(FileByte,ThreadFile.Buf1,Len[4]); ThreadFile.Counter := 0; ThreadFile.BytesReady :=Len[4]; end; Move(ThreadFile.Buf1[ThreadFile.Counter],GetHidBufPointer^,Len[3]); ThreadFile.Counter := ThreadFile.Counter + Len[3]; end;
Если использовать потоки
begin if ThreadFile.BytesReady=0 then begin BlockRead(FileByte,ThreadFile.Buf1,Len[4]); ThreadFile.BackBuf := False; ThreadFile.BytesReady := Len[4]; ThreadFile.Resume; end; if ThreadFile.Counter=ThreadFile.BytesReady then begin ThreadFile.Counter := 0; ThreadFile.BytesReady :=0; ThreadFile.BackBuf := not ThreadFile.BackBuf; ThreadFile.Resume; end; if ThreadFile.BackBuf then Move(ThreadFile.Buf2[ThreadFile.Counter],GetHidBufPointer^,Len[3]) else Move(ThreadFile.Buf1[ThreadFile.Counter],GetHidBufPointer^,Len[3]); ThreadFile.Counter := ThreadFile.Counter + Len[3]; end; //------------- procedure TThreadFile.Execute; begin inherited; while True do begin if BackBuf then BlockRead(FileByte,Buf1,Len[4]) else BlockRead(FileByte,Buf2,Len[4]); BytesReady := BytesReady + Len[4]; Suspend; // Self. end; end;
То в этом случае всё работает только в fmx в версии win32 . В Андройде , увы читаются нули.
В принципе ошибка не критичная, т.к. второй вариант в итоге не даёт приросто производительности, но в общей случае настораживает.
-
Стоит Delphi 10.0
Разрешены две ориентации экрана LandscapeHomeright и LandscapeHomeleft. При открытии в одной ориентации приложения чаще всего вылетает, когда форма показывается. При открытии во второй всё перевёрнутое, но зато не вылетает . Можно перевернуть экран и тогда тоже не вылетает. Ну и естественно в Windows всё нормальное работате, программа никогда не вылетает .
Вопрос, что собственно это такое.
-
При обновление приложении иногда обновляется иногда рандомно пишет "приложение не установлено". Остановка приложение не всегда помогает. Устройство Samsung Galaxy Tab 8 , Android 9 . Но было с другими устройствами и другими системами тоже.
-
Допустим идут вычисления, мне надо в Label выводить, что они закончились на 10%...20%...100%
После изменения текста я делаю
Label1.Repaint; Invalidate;
При этом текст не изменяется, пока не окончатся вычисления. Хотя в Vcl версии хватает Repaint для формы.
-
Да, у меня на телефоне API 33.
Я вот почитал https://developer.android.com/training/data-storage/use-cases#opt-out-scoped-storage , что теперь только Downloads получается открыта?
Цитата-
Move any shared non-media files to an app-dedicated subdirectory of the
Downloads/
directory.
-
Move any shared non-media files to an app-dedicated subdirectory of the
-
Раньше у меня в директории assets она же android/data ,она же получаемая по TPath.GetSharedDocumentsPath располагался конфигурационный файл, который я мог править из файлового менеджера. Туда же скидывались логи и т.д.
Начиная с версии 10.0 Android эту возможность прикрыли. Теперь android/data пуста, конфигурационный файл я не вижу. В 10-й версии причём как-то "через раз" работает. В 11-м уже железно не работает.
Есть какая-это папка , которая доступна и для программы и для файлового менеджера? Или можно в assets как-то доступ из файлового менеджера получить?
-
Решил я загрузить на Samsung Galaxy Store своё приложение. При этом на Google Play Store аккаунта не имеют. Мне приложение заморозили по причине "Play Protect pop-up appears during installation." - то есть , что ругается защитник. Как показало гугление, для того, чтобы он не ругался надо загрузить приложение сначала на Google Play Store.
Вопрос , кто-то работал с а Samsung Galaxy Store? Можно к ним загружать уникальные приложения. Или только те, что на Google Play Store уже загрузил(тогда непонятно зачем они вообще нужны).
-
krapotkin - может вы и правы. Потестирую на других устройствах пока тестировал на Samsung A71. Вот ещё что есть интересного. Я протестировал в режиме портретном, там угол экрана всё-таки ровно по центру пальца оказывается. А в ланшафтном - увы.
Slym - я пробовал нажимать стандартные иконки. Там именно реакция на нажатие именно по центру пальца. Что в портретном режиме, что в ландшафтном.
---
UPD - на планшете Galaxy Tab 8a всё работает, левый верхний угол именно по центру.
UPD2 - на Galaxy A6+ тоже работает.
UPD3 - на A71 фронтальная камера расположена прямо на экране. При клике на фронтальную камеру ничего не происходит. При клике сверху или снизу камеры(если держать в ландшафтной ориентации) тоже никакой реакции. Если кликнуть чуть правее камеры, то левая часть прямоугольника устанавливается ровно слева от экрана. То есть сдвиг идёт ровно на ширину этой фронтальной камеры.
-
С помощью старших товарищей на этом форуме я научился отображать прямоугольники. Вот код, который мне подсказали.
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single); begin FCrd := PointF(X,Y); end; procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single); begin Invalidate; end; procedure TForm1.FormPaint(Sender: TObject; Canvas: TCanvas; const ARect: TRectF); begin Canvas.Fill.Color := TAlphaColorRec.Wheat; Canvas.FillRect(rectf(FCrd.X, FCrd.Y, FCrd.X+100, FCrd.Y+100), 0,0,[], 1); end;
Так вот в Windows , если нажать курсор, то как мы и ожидаем, левый верхний угол прямоугольника будет установлен именно туда , куда мы нажали. В Andoroid же левый верхний угол устанавливается где-то по левой верхней части пальца. А ожидается, что он будет установлен в центр пальца. В связи с этим вопросы.
1) X,Y -это координаты центра пальца или левой верхней его части?
2) Как получить координаты именно куда нажал центр пальца? Ведь я не знаю ни размера устройства ни размера пальца, поэтому просто прибавлять к X,Y какое-то значение, это такое себе..
В справке удалось нарыть только это - http://docwiki.embarcadero.com/Libraries/Sydney/en/FMX.Controls.TControl.MouseDown . Так никак не описывается поведение на планшетах.
-
Большое спасибо! Invalidate действительно работает и в моём проекте тоже, если поставить вместо InvalidateRect.
-
Увы, и это не работает.
InvalidateRect(WinRect); //FormPaint(Sender,Canvas,TestRect);
WinRect - посылается размер окна.
Естественно на win32 работает и этот вариант.
ЦитатаПо мне, так то, что в Windows это работает - это скорее упущение, баг, а не фича ))
Ну на VCL - это был скорее фича , можно было всё без танцев с бубном делать. Но на FMX на разных платформах должно работать единообразно - или везде или нигде. ПОтому , что любую программу надо будет тестировать на win32/64 , потом так же тщательно на Android , а потом ещё и на IoS. Вот у меня устойств с IOS нет , я уже понял, то доступ раз в недёлю "отца русской демократии" не спасёт.
-
Да , так работает лучше, но всё же всё-рано что-то не так.
Вот я отрабатываю клик мышкой.
TestRect.Left := XToEtalon(X)-50; TestRect.Top := XToEtalon(Y)-50; FormPaint(Sender,Canvas,TestRect); WriteToLog(report,FloatToStr(X)+' , '+ FloatToStr(Y));
И соотвественно,
redraw(0,0,1,false); redraw(Round(ARect.Left),Round(ARect.Top),1,true);
В итоге в Win32 всё работает отлично - куда я щёлкаю мышкой, появляются прямоугольники.
В Android - нулевая реакция.
При этом в логе записывается , что клик произошёл.
-
Данный код работает в windows-32 , но не хочет работать в Android.
Form1.Canvas.BeginScene; Form1.Canvas.Fill.Kind := TBrushKind.bkSolid; Form1.Canvas.Fill.Color := TAlphaColorRec.Red; form1.Canvas.FillRect(fs,0,0,AllCorners,1); Form1.Canvas.EndScene;
Просто ничего не отрисовывается. В чём может быть причина?
Прикрепляют также тестовый проект, вдруг на какой-то версии он нормально работает.
-
Пример который я выше привёл, всё-таки рабочий(на запись). Но в Delphi XE7 и ниже неправильно компилируется. В Delphi 10 нормально компилируется.
-
bytes_written := FUsbDeviceConnection.bulkTransfer({FUsbEPBO}FUsbEPII, Buffer, Size, 100);
Что характерно, если так вот записать, то есть пытаться передать данные в не ту EndPoint всё равно выдаёт,что передано 3 байта. Истина, похоже где-то рядом...
-
Я вот кстати пробовал реализовать более простой пример подключения , чем в этой библиотеке.
//NewUSB:=TUSB.Create; FEpOut:=nil; Memo1.Lines.Append('Begin'); if UsbManager=nil then UsbManager:= TJvHidDeviceController.Create(Self); //usbManager = context.getSystemService(Context.USB_SERVICE) as UsbManager DeviceList := UsbManager.FUsbManager.getDeviceList; iter := DeviceList.values.iterator; while iter.hasNext do begin LocalUSBDevice := TJUSBDevice.Wrap((iter.next as ILocalObject).GetObjectID); if (LocalUSBDevice.getVendorId <> VENDOR) or (LocalUSBDevice.getproductId <> PRODUCT) then continue;//continue; Memo1.Lines.Append('Stage 1'); for i:=0 to LocalUsbDevice.getInterfaceCount-1 do begin Memo1.Lines.Append('Stage 2'); LocalUsbInterface := LocalUsbDevice.getInterface(0); if LocalUsbInterface.getInterfaceClass=3 then break; end; //Open end; if NOT UsbManager.UsbManager.hasPermission(LocalUSBDevice) then begin PermissionIntent:=TJPendingIntent.JavaClass.getBroadcast(SharedActivityContext, 0, TJIntent.JavaClass.init(StringToJString(ACTION_USB_PERMISSION)), 0); Filter := TJIntentFilter.JavaClass.init; Filter.addAction(StringToJString(ACTION_USB_PERMISSION)); FBroadcastReceiverListener := TBroadcastReceiverListener.Create(UsbManager); FReceiver := TJFMXBroadcastReceiver.JavaClass.init(FBroadcastReceiverListener); SharedActivityContext.getApplicationContext.registerReceiver( FReceiver, Filter); UsbManager.UsbManager.requestPermission(LocalUSBDevice,PermissionIntent); exit; end; if LocalUsbInterface=nil then exit else Memo1.Lines.Append('Stage 3'); for I := 0 to LocalUsbInterface.getEndpointCount-1 do begin FUsbEP := LocalUsbInterface.getEndpoint(i); if FUsbEP.getType=3 then begin if FUsbEP.getDirection = TJUsbConstantsUSB_DIR_OUT then begin if FEpOut=nil then FEpOut := FUsbEP; end else if FUsbEP.getDirection = TJUsbConstantsUSB_DIR_IN then begin if FEpIn=nil then FEpIn := FUsbEP; end; end; end; if {(EpIn=nil) AND} (FEpOut=nil) then exit; Memo1.Lines.Append('Stage 4'); // Open device FUsbDeviceConnection := UsbManager.UsbManager.openDevice(LocalUSBDevice); if not assigned( FUsbDeviceConnection) then exit; Memo1.Lines.Append('Stage 5'); if not FUsbDeviceConnection.claimInterface(LocalUsbInterface, True) then exit; Memo1.Lines.Append('Stage 6'); btnHIDEnable.Enabled := True; btnGetSerial.Enabled := True; //FUsbDeviceConnection.
Соотвественно, передача делается через
S:=IntToStr(FUsbDeviceConnection.bulkTransfer(FEpOut, Buffer, {Buffer.Length}3, 0)); //можно 0 Memo1.Lines.Append('Retval = '+S);
Он кстати при подключении пишет, что всё нормально. Но при попытке отправки данных увы, ничего не передаёт. Даже более того, другие программы на Java , запущенные параллельно тоже после моей не могут ничего передать.
-
Вот например есть https://github.com/LongDirtyAnimAlf/Delphi-Android-USB-HID . К сожалению библиотека старая , не использует возможности последний версий API . И, подозреваю, глючная.
-
В итоге для определеления имени продукта изменил код на
FProductName := JStringToString(FUsbDevice.getProductName);
Вместо
ЦитатаFProductName := GetDeviceString(2); //FProductName := JStringToString(FUsbDevice.getDeviceName);
Серийный номер так и не получилось получать.
-
Приведу куски кода, которые , собственно эту хрень и вызывают.
function THidServer.DeviceName(HidDev: TJvHidDevice): string; begin if HidDev.ProductName <> '' then Result := HidDev.ProductName else Result := Format('Device VID=%.4x PID=%.4x', [HidDev.Attributes.VendorID, HidDev.Attributes.ProductID]); if HidDev.SerialNumber <> '' then Result := Result + Format(' (Serial=%s)', [HidDev.SerialNumber]); end;
Соотвественно HidDev.ProductName и HidDev.SerialNumber получаем такfunction TJvHidDevice.GetProductName: String; begin if FProductName = '' then begin FProductName := GetDeviceString(2); //FProductName := JStringToString(FUsbDevice.getDeviceName); end; Result := FProductName; end; function TJvHidDevice.GetSerialNumber: String; begin if FSerialNumber = '' then begin FSerialNumber:=GetDeviceString(3); //if Openfile then FSerialNumber:=JStringToString(FUsbDeviceConnection.getSerial); end; Result := FSerialNumber; end;
Наконец GetDeviceString - это вот что:
function TJvHidDevice.GetDeviceString(Idx: Byte): string; const STD_USB_REQUEST_GET_DESCRIPTOR = $06; STD_USB_REQUEST_GET_REPORT = $01; LIBUSB_FEATURE_REPORT = $0301; //Feature report, ID = 1 LIBUSB_DT_STRING = $03; var i,rdo:integer; rawDescs,buffer : TJavaArray<Byte>; requestidx:integer; S : String; begin if Openfile then begin rawDescs := FUsbDeviceConnection.getRawDescriptors; if (13+Idx)>rawDescs.Length then begin result:=''; exit; end; requestidx := rawDescs[13+Idx]; rawDescs.Free; buffer := TJavaArray<Byte>.Create(255); rdo := FUsbDeviceConnection.controlTransfer( (TJUsbConstantsUSB_DIR_IN OR TJUsbConstantsUSB_TYPE_STANDARD), STD_USB_REQUEST_GET_DESCRIPTOR, ((LIBUSB_DT_STRING SHL 8) OR requestidx), 0, buffer, $FF, 0); if rdo>100 then rdo:=100; if rdo<3 then begin result:=''; exit; end; S:=''; for i:=1 to (rdo-2) do begin S:=S+Char(buffer.Items[i+1]); end; result:=S; buffer.Free; end else result:=''; end;
Если изменить кусок кода так чтобы в явном виде выдавался код символов. В итоге получается такой лог
Arrival of #0 #0 #0 #0 #0 #0 #0 #0 #0 #0 #0 #0 #0 #0 #0 #0 (Serial= #0 #0 #0 #0 #0 #0 #0 #0 #0 #0 #0 #0 #0 #0 #0 #0 #0 #0 #0 #0 #0 #0 #0 #0)
-
Устанавливая в device_filter.xml устройство, с которым хочу работать. Например для PicKIT3 ставлю
<usb-device vendor-id="1240" product-id="36874"/>
После этого при подключении данного устройства он предлагает выполнить мою программу. Это было ожидаемый результат. Неожидаемый результат, что если не прописать это устройство, то например выдаётся
Device VID=04D8 PID=900
А если устройство прописать, то выдаётся хрень вида
(Serial= )
Это что, особенность планшета? Или это потому, что я к нему не правильно подключился? Или я как-то в лог могу неправильно записывать то, что он прислал?
-
Большое спасибо, всё заработало. Только у меня XE7, поэтому изменил параметр "Key: package"
-
Мне надо установить две версии своей программы на один планшет. Но при установке система говорит, что это я старую пытаюсь обновить. И по итогу установлена оказывается одна(которую я последней установил). Переименование проекта не спасает, он всё равно считает, что это одна и та же программа. Как заставить систему их различать?
Чтение файлов в отдельной потоке.
в Потоки и распределенные вычисления
Опубликовано · Изменено пользователем Андрей Рулин
Buf1,Buf2 : Array[0..13100] of byte; FileByte : File of byte; Len : array[0..7] of integer = (26,20,26,131,13100,36,36,36);
В отдельном потоке читаем файл. После каждого чтения поток "засыпает". Если у нас осталось меньше 13100 байт, опять будим поток.
Вот ещё вариант, накодил сегодня.
procedure TThreadSignal.Execute; begin inherited; while True do begin fCompleted := False; Task[fi].Solve; fCompleted := True; Suspend; end; end;
Тут вообще андройдовская версия намертво повисает. А под win32 всё исправно работает, производит вычисления.
Тут идея тоже самая почти. Надо провести 4 вычисления параллельно. Потом дождаться , пока все 4 выполнятся и идти дальше.