Requesting Android permissions in Qt 6 - qt6

I am trying to convert a Qt 5 app to Qt 6.
In Qt 5 we can request Android permissions as follows:
QStringList permissions;
//...
QtAndroid::PermissionResultMap resultHash = QtAndroid::requestPermissionsSync(permissions);
for (const auto &perm : permissions)
{
if(resultHash[perm] == QtAndroid::PermissionResult::Denied)
{
qDebug() << "Permission denied:" << perm;
return false;
}
}
What is the equivalent in Qt 6? Or is the only way to manually implement this using JNI?
Regards

Here is the new Qt6 permission API (which is still under development, however can be used): QtAndroidPrivate Namespace
Example:
#include <QtCore/private/qandroidextras_p.h>
bool checkPermission()
{
auto r = QtAndroidPrivate::checkPermission(QtAndroidPrivate::Storage).result();
if (r == QtAndroidPrivate::Denied)
{
r = QtAndroidPrivate::requestPermission(QtAndroidPrivate::Storage).result();
if (r == QtAndroidPrivate::Denied)
return false;
}
return true;
}

There is no permission handling API in Qt6 yet. However, it is under making. You can follow the situation from QTBUG-90498. It looks like it is scheduled for Qt6.4 release which I assume will be due some time in the fall 2022. You can find a code review link from the bug report which might help you in writing your own implementation.
I would recommend you to take a look into QNativeInterface::QAndroidApplication::runOnAndroidMainThread which you can use for asynchronous calling on the Android UI thread.

Related

Display Opencv image send by event to Qt GUI

I am trying for days now to find a proper solution to the following problem(stated below), and I have no more ideas now. Therefore, I need help from more experienced devs:
I have a class independant from QT (and I want it to stay like this) that generate openCV images in a secundary thread. Then it raise an event which pass the images.
while (1)
{
if (timerActived & this->_camReady)
{
vector<Mat>* images = new vector<Mat>;
images = this->AcquireImg();
__raise this->frameAcquired(images);
}
this_thread::sleep_for(chrono::milliseconds(_frameTimeLaps));
}
This event is hooked by my MainWindow and a method is supposed to display my images on my GUI.
void MainWindow::displayFrame(vector<Mat>* frames) {
vector<Mat>* frames2 = new vector<Mat>();
frames2 = frames;
for (int i = 0; i < frames2->size(); ++i) {
this->camFrames->at(i)->showImage(frames2->at(i));
}
}
During the runTime, when the Main Thread access the images I get the following error :
ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects owned by a different thread.
I understand that I am not using threads properly, but I have no idea how to create an asynchronous event now.
Thank you for help,
Valentin
EDIT 1 :
It seems to me that the real question is : can I use normal std::thread and native event to communicate with the main Qthread ?
Here is my solution to solve the problem, after all.
The idea is to give the main thread access to the Mat coming from the second thread. So I modified my function displayFrame like this :
void MainWindow::displayFrame(vector<Mat>* frames) {
//QThread::
QThread* this_thread = QThread::currentThread();
FrameWrapper* worker = new FrameWrapper();
worker->moveToThread(this_thread);
QObject::connect(worker, SIGNAL(frameSent(vector<Mat>*)), this, SLOT(showImg(vector<Mat>*)));
emit worker->frameSent(frames);
//this->camFrames->at(0)->showImage(frame);
}
The new function showImg is doing the job of the old displayFrame. The signal/slot process permit to access image from the GUI Thread as wanted.

Platform Event Loops in C++ Node Addon

I am very new to node. I am actually making the switch to using electron as I found it super awesome for rapid/quality/cross-platform development. However I needed to do some platform API stuff on Windows/Mac/*nix. So I was going to follow this guide here:
http://blog.scottfrees.com/building-an-asynchronous-c-addon-for-node-js-using-nan
to create a node addon sort of thing. I have never done this before (kind of new to C++ too), but I am familiar with platform APIs as I used to use it with FFI's. Is it possible to run event loops in it as we do in a typical platform process?
Or is the only option spawning a child process and running event loop in that child-app?
Typical winapi (Windows) event loop:
MSG msg;
BOOL bRet;
while(1) {
bRet = GetMessage(&msg, NULL, 0, 0);
....
}
Typical X11/XCB (*nix) event loop:
xcb_generic_event_t *event;
while ( (event = xcb_wait_for_event (connection)) ) {
switch (event->response_type & ~0x80) {
....
}
free (event);
}
Typical Cocoa (Mac) event loop:
[[NSApplication sharedApplication] run];

How to enable user to re-entry(or) reuse the same dialog in MFC

I'm currently doing a FTP download using MFC. Is a very simple program which takes 2 inputs from user and click a download button in order to download from server. Everything is fine and im able to download it from. But i realized this program can only be executed once. Either successful or fail user has to open the .exe again to download another file. I'm a beginner in C&C++ with a simple knowledge i put OnInitDialog() at the last line of the download function hopping it will loop back and initialize again. Of course it doesn't work. Below are my current codes for the download button
BOOL CFTPDOWNLOADDlg::Log_In(char* path, char* ID, char* password {
m_pFtpConnection = NULL;
try{
// path
// ID
// password
m_pFtpConnection = m_Session.GetFtpConnection(path,
ID,password,INTERNET_INVALID_PORT_NUMBER);
}
catch(CInternetException *pEx){
pEx->ReportError(MB_ICONEXCLAMATION);
m_pFtpConnection = NULL;
pEx->Delete();
return FALSE;
}
return TRUE;
}
BOOL CFTPDOWNLOADDlg::Download(){
m_Edit3.SetWindowText("Downloading..");
m_Session.EnableStatusCallback(TRUE);
if(m_pFtpConnection->GetFile(serv_Loc,host_Loc,
FALSE,FILE_ATTRIBUTE_NORMAL,FTP_TRANSFER_TYPE_BINARY,1) != 0){
MessageBox("Download Complete");
m_Edit3.SetWindowText("");}
else{
MessageBox("Download Fail");
return FALSE;
}
// Log_out Session
m_Session.Close();
m_pFtpConnection->Close();
if(m_pFtpConnection!=NULL) delete m_pFtpConnection;
else MessageBox("Download Complete");
return TRUE;
}
BOOL CFTPDOWNLOADDlg::get_Path(){
...
...
...
sprintf(serv_Loc,"soft\\%s\\%d\\%s.zip",s_No,r_Number,r_No);
sprintf(host_Loc,"%s\\%s.zip",buff2,r_No);
return TRUE;
}
void CFTPDOWNLOADDlg::OnCancel() {
// Log_out Session
m_Session.Close();
m_pFtpConnection->Close();
if(m_pFtpConnection!=NULL)
delete m_pFtpConnection;
CDialog::OnCancel();
}
void CFTPDOWNLOADDlg::OnDLButton() {
//get path from user input
get_Path();
// start download
Download();
}
I've tried to search online, i couldn't find anything which is close. Sorry for my poor explanation.
Thank you in advance for your kindness in replying
Here is what you need to do:
You should make CInternetSession m_Session; a member of your CWinApp-derived class.
You should call m_Session.Close() in ExitInstance() method of your CWinApp-derived class.
In your CDialog-derived class you should only deal with CFtpConnection related stuff. So when user clicks on Download button you should call GetFtpConnection() and initialize your m_pFtpConnection and do the rest. When download/upload is done call m_pFtpConnection->Close(); and delete m_pFtpConnection;
Please also use CString instead of char*. There are lots of benefits like automatic UNICODE support, etc.
Please also consider using CString::Format() method instead of sprintf().
You should also consider using threads to perform upload/download tasks in a separate worker thread. Use AfxBeginThread() to start the thread. This way you'll not affect Windows message pump that is a part of main application (GUI) thread. So your GUI wont lock up while you uploading/downloading files.

Automation implementation using Busy Waiting or Threads in c++

I am trying to automate the handler equipment(a robot picks a chip and put it onto a hardware platform) with the following requirement:
1.There are 6 sites for the handler , once handler puts a device onto that site, handler will return an errorcode:
code1 for ready to test, code2 for error, and if in process no code have returned.
2.There is a master PC that controls the handler operation, and the communication b/w master and site PCs are using Staf
3.I need to use that code to run some tests(which already implemented and working properly).
Handler puts the device in a FIFO order, first site returns code first, and last site returns code last.
4.The Site PC is acting passively, which master PC will determine when to run and how to run the tests. Site PC will only know if handler is ready then execute the tests.
So my question would be: In this case, for the site-PCs(Windows based with perl and .net enabled), is busy waiting method better or is the wait condition mechanism suits better:
For example: the sample code would be:
void runTestonSite()
{
for(;;)
{
if(returnCode == code1)
{
testStart(arg1,arg2,arg3);
}
}
}
or is there any better way to do this kind of task?
#include <boost/thread.hpp>
void getReturnCode() {
// do stuff
}
void RunTestOnSite() {
// do stuff
}
int main (int argc, char ** argv) {
using namespace boost;
thread thread_1 = thread(getReturnCode);
thread thread_2 = thread(RunTestOnSite);
// do other stuff
thread_2.join();
thread_1.join();
return 0;
}
Please advise,
thanks

WebClient and SOAP calls lock up in MonoTouch 4.0.0 and 4.0.1. Works in 3.2.6. Demo inside. What's causing it?

My app is making heavy use of webservice calls. Lately, some of the calls got stuck. After playing around I figured out that it
happens mostly for release builds
happens in the Simulator AND on the device (iPad, iOS 4.3)
happens more often on iPad 1 than on iPad 2
it is not limited to web services an SOAP but also affects the System.Net.WebClient
does not affest [NSString stringWithContentsOfUrl:] if invoked manually, since not bound
The effect is that the CPU load of the device drops to zero. memory is stable (in my demo project 8.5MB). If I put Console.WriteLines() everywhere, I can see that the code is stuck inside one of the WebClient.Download*() methods.
The code below demonstrates that (if built RELEASE with MT 4.0.1, LLVM off or on does not matter) downloading a file from the web over and over again fails sometimes right away on the first try, sometimes after 10 times, sometimes after around 30 downloads.
It is totally random. If you think it works, kill the app and restart it and eventually it will hang.
When building the same using MT 3.2.6, the downloading goes on all day without issues. It is impossible to break it.
MONO installed is the latest available version.
Can somebody from the MT team comment on it?
using System;
using System.IO;
using System.Threading;
using System.Net;
using System.Collections.Generic;
using System.Linq;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
namespace iOSTest
{
public class Application
{
static void Main (string[] args)
{
UIApplication.Main (args);
}
}
// The name AppDelegate is referenced in the MainWindow.xib file.
public partial class AppDelegate : UIApplicationDelegate
{
private Thread oThread;
// This method is invoked when the application has loaded its UI and its ready to run
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
// Make a release build and run on iPad 1 with iOS 4.3.2.
// Fails after downloading between 1 time and 30 times on MT 4.0.1.
// It is possible that it seems to work. Then just kill the app and restart and suddenly the effect
// will become visible. If you watch it with Instruments, CPU suddenly drops to zero. The app then is
// stuck somewhere inside WebClient. After about 10 minutes, an exception will be thrown (timeout).
// Never fails on MT 3.2.6
Console.WriteLine(MonoTouch.Constants.Version);
// A label that counts how often we downloaded.
UILabel oLbl = new UILabel(new System.Drawing.RectangleF(40, 100, 150, 30));
window.AddSubview(oLbl);
// This thread downloads the same file over and over again.
// The thread is not required to demonstrate the issue. The same problem occurs
// if the download is running on the main thread.
this.oThread = new Thread(delegate()
{
using(var oPool = new NSAutoreleasePool())
{
int i = 0;
while(true)
{
// Setup webclient and download a file from my website (around 2.4 MB)
WebClient oClient = new WebClient();
// It would be nice to hange it to your own URL to save me from all the traffic.
oClient.DownloadFile(new Uri("http://www.wildsau.net/image.axd?picture=2011%2f4%2fDSC05178.JPG"), Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "test.jpg"));
// Increase counter and update label.
i++;
this.InvokeOnMainThread(delegate { oLbl.Text = i.ToString(); });
Console.WriteLine("Done " + i + " times.");
}
}
});
// Have a button that starts the action.
UIButton oBtn = UIButton.FromType(UIButtonType.RoundedRect);
oBtn.SetTitle("Download", UIControlState.Normal);
oBtn.Frame = new System.Drawing.RectangleF(40, 40, 150, 30);
oBtn.TouchUpInside += delegate(object sender, System.EventArgs e)
{
this.oThread.Start();
};
window.AddSubview(oBtn);
window.MakeKeyAndVisible ();
return true;
}
// This method is required in iPhoneOS 3.0
public override void OnActivated (UIApplication application)
{
}
}
}
From Gonzalo-
When the problem occurs, "kicking" the threadpool by adding another
work item will make the problem go away.
Something like this (not tested or compiled ;-) should do:
Timer timer = new Timer (AddMe);
...
WebClient wc = new WebClient ();
Uri uri = new Uri(url);
timer.Change (0, 500); // Trigger it now and every 500ms
byte[] bytes = wc.DownloadData(uri);
timer.Change (Timeout.Infinite, Timeout.Infinite);
....
static void AddMe (object state)
{
// Empty.
}
#
Works 100% of the time - for me at least - YMMV. And it did, once we put the code under stress (Lots of files to download) it stalled again. Just heard from MT that 4.0.6 will have the fix in it. Should see it later this week!
Promised to be fixed by Xamarin in the next major release. Still does not work in 4.0.4 though.

Resources