Native call blocks main thread - android

I have some Android app that should load some data on start and process it as soon as possible. For better performance data processing done in native code.
But in some time data amount was increased and it becomes to block UI while processing. The weird thing is that I launch JNI call from background thread and I believe native code should also work in background.
So few questions:
how to detect is native code works in main thread?
how to detect who blocks UI?
Some code sample:
// java
new Thread(new Runnable() {
#Override
public void run() {
ResourceLoader.loadListsAndParse(); // native call
}
}).start();
// c++
void RulesManager::loadRules() {
if (!rules_loaded_) {
using namespace std;
base::FilePath my_dir;
GetCacheDirectory(&my_dir);
this->loadRulesInternal(my_dir, true);
}
}
void RulesManager::loadRulesInternal(base::FilePath& path, bool processExceptions) {
base::FileEnumerator files(path, false, base::FileEnumerator::FILES);
for (base::FilePath name = files.Next(); !name.empty(); name = files.Next()) {
this->loadRulesFromFile(name.AsUTF8Unsafe(), processExceptions);
}
}
bool RulesManager::loadRulesFromFile(const std::string& filePath, bool processException) {
bool result = false;
std::ifstream file(filePath);
std::string str;
while (std::getline(file, str)) {
result = this->addRule(str, processException);
}
return result;
}

Android has system calls getpid() and gettid() defined in <unistd.h>. If the pid_t return values are equal, then your native code runs on the UI thread.

I use BlockCanary for that purposes. If you know about LeakCanary, BlockCanary provides reports about UI blocking in the same way.

How to detect is native code works in main thread?
You can apply Log method inside your code.
For example your code is:
if(myInt > 0){
doSth();
}
Insert Log method;
if(myInt > 0){
doSth();
Log.i("Info", "if statement is true.");
}
now your device will type to the console if your if statement runs. So in your thread, you can insert Log method to critical lines to see if it is running or not.
how to detect who blocks UI?
As in my first answer, again you can see it from the console if you implement Log methods to your code.
But if you want to do it properly, I suggest you to check Asynctask. This will take time to learn how to implement it properly but the most practical way to pass the long jobs to background in Android is Asynctask.

Related

Method called by another method running in thread will run in that thread also?

public static void main(String[] args) {
new Thread(new Runnable() {
#Override
public void run() {
getLinks();
}
});
}
}
private void getLinks(){
String link;
// my work
Download(link);
}
private void Download(String Link){
// my work
}
Will the other method also run in that thread, as we called getlinks() then getlinks() called the Download() method, will the downloading will run in the background or I have to stay my activity open, in my android app.
Fact: When we are using IntelliJ IDE and we all know that there is a method named as public static void main(String ars[]){ } remember? So this is a method and all the code that runs in this method will run in the main thread.
Answer - So if we call a method from a thread then each line of code in that method, will run in that thread.
Example : So the thread is a car and anything that is called by this car will travel in that car , even if a person is called by a person who is already traveling in that car will have to travel in that car. Each person need a car to travel. Each method needs a thread to run.
Extra Fact - You know in android, there is a thread called UI thread, so whenever you want to make changes to UI then u have to use that thread or it will crash the app.
I recommend you this udemy course [ by Michael Pogrebinsky ] to understand multithreading in java. Java Multithreading, Concurrency & Performance Optimization

In Android run asyn task inside Worker class of WorkManager

I've a Worker in which i first want to apply FFMPEG command before uploading it to server. As Worker is already running in background so to keep the result on hold until file uploads I've used RxJava .blockingGet() method. But I'm unable to understand that how to execute FFmpeg command synchronously by anyway i.e. RxJava etc. One tip that I found is to use ListenableWorker but it's documentation says that it stops working after 10 minutes. So, i don't want to go with that solution. Following is the method of FFmpeg just like any other async method. How can i make it synchronous or integrate it with RxJava? Any ideas would be appreciable.
ffmpeg.execute(command, new ExecuteBinaryResponseHandler() {
#Override
public void onFailure(String s) {
}
#Override
public void onSuccess(String s) {
uploadMediaItem(mediaUpload);
}
#Override
public void onProgress(String s) {
}
#Override
public void onStart() {
}
#Override
public void onFinish() {
// countDownLatch.countDown();
}
});
This is the flow of my Worker:
check pending post count in DB.
Pick first post and check if it has pending media list to upload.
Pick media recursively and check if editing is required on it or not.
Apply FFmpeg editing and upload and delete from DB.
Repeat the cycle until last entry in the DB.
Thanks
If you wanna create a syncronous job you need to use the CountDownLatch class (there is a comment in your code).
CountDownLatch is a syncronization object that can be used in cases like this.
As for now there isn't a valid method to have sync workers.
Listenable workers is useful when you want to monitor the worker itself from your app using a Livedata that return useful information (e.g. the status).
If I remember correctly the standard Worker class also descend from Listenable worker so you can use that.
In your case is useful to have two workers: the first apply a FFMPEG command, and the second worker that take the output of this command to do the network upload. Separating this two operations allows you to have more time for complete the two works (10 + 10).
In your case you can do something like this for the first worker:
private final CountDownLatch syncLatch = new CountDownLatch(1);
...ctor
doWork(){
//your asyncronous call
...
#Override
public void onFinish() {
//you need to save error status into a onSuccess and onFailure
syncLatch.countDown();
}
...
//end
syncLatch.await();
...
//evaluate if there are errors
...
//create output to pass to the next worker
Data outputData = ...
//pass the result to second worker, remember that onfailure will stop all subsequent workers
if(error==true)
{
return Result.failure(outputData);
}else{
return Result.success(outputData);
}
}
For the second worker you can do the same according to your upload function behavihour to syncronize the call.
Hope this help.
Cheers.

Android NDK Thread invalid use of non-static member function

I need to use threads in my android application because I am doing image processing w/ native opencv. Here is my code:
void Detector::processBinary(Mat &binary) {
//do stuff
}
void Detector::Detect() {
...
thread t1(processBinary, binary);
t1.join();
}
However, I get the error "invalid use of non-static member function" from thread t1(processBinary, binary) whenever I try to run the app. This line, however, works perfectly in visual studio. Can anyone help me with this? Thanks in advance!
You use member function, that needs this argument (it must be called on some object). There are two alternatives:
Use static class function (or non-class function at all):
void processBinary(Mat &binary) {
//do stuff
}
void Detector::Detect() {
...
thread t1(processBinary, binary);
t1.join();
}
Or pass proper arguments if we want utilize member function:
void Detector::processBinary(Mat &binary) {
//do stuff
}
void Detector::Detect() {
...
thread t1(&Detector::processBinary, *this, binary);
t1.join();
}

How to correctly use a Workerthread?

I've been writing android apps for some months now, and I'm at the point where I'm building an actual needed app.
As I want that to work nice and fast, I made a Workerthread to do all kinds of tasks in the background while the UI can...build up and work and stuff.
It's based on the Android Studio Drawer app blueprint.
In Main.onCreate I got my operator=new Operator(), which extends Thread.
Now, when loading a new Fragment, it sometimes calls MainActivity.operator.someMethod() (I made operator static so I can use it from anywhere), and after some time I realized, the only tasks actually running in background are those in the operators run() method and an Asynctask my login Fragment runs. Everything else the UI waits for to complete and therefore gets executed by the UI thread.
So I thought: no problem! My operator gets a handler which is built in run(), and I change those tasks:
public void run() {
Looper.prepare(); //Android crashed and said I had to call this
OpHandler = new Handler();
LoadLoginData();
[...Load up some Arrays with hardcoded stuff and compute for later use...]
}
public void LoadLoginData() {
OpHandler.post(LoadLoginDataRunnable);
}
private Runnable LoadLoginDataRunnable = new Runnable() {
#Override
public void run() {
if(sharedPreferences==null)
sharedPreferences= PreferenceManager.getDefaultSharedPreferences(context);
sessionID=sharedPreferences.getString("sessionID", null);
if(sessionID!=null) {
postenID = sharedPreferences.getString("postenID", PID_STANDARD);
postenName = sharedPreferences.getString("postenName", PID_STANDARD);
context.QuickToast(sessionID, postenName, postenID);
}
}
};
context is my MainActivity, I gave the operator a reference so I could send Toasts for Debugging.
But now, the Runnables seem to not run or complete, any Log.e or Log.d stuff doesn't arrive in the console.
After some googeling and stackoverflowing, everyone is just always explaining what the difference is between Handlers, Asynctask, and Threads. And the multitask examples always only show something like new Thread(new Runnable{run(task1)}).start times 3 with different tasks.
And so became my big question:
How to correctly, over a longer time (~lifecycle of the MainActivity), with different tasks, use a background thread?
Edit: to clarify, I would also like a direct solution to my special problem.
Edit 2: after reading nikis comment (thank you), the simple answer seems to be "use HandlerThread instead of thread". Will try that as soon as I get home.
Trying a HandlerThread now. It seems my OpHandler, initialized in run(), gets destroyed or something after run() has finished, not sure whats up here (this is btw another mystery of the kind I hoped would get answered here). I get a NullpointerException as soon as I try to use it after run() has finished.
Make your worker thread own a queue of tasks. In the run() method, just pop a task from the queue and execute it. If the queue is empty, wait for it to fill.
class Operator extends Thread
{
private Deque<Runnable> tasks;
private boolean hasToStop=false;
void run()
{
boolean stop=false;
while(!stop)
{
sychronized(this)
{
stop=hasToStop;
}
Runnable task=null;
synchronized(tasks)
{
if(!tasks.isEmpty())
task=tasks.poll();
}
if(task!=null)
task.run();
}
}
void addTask(Runnable task)
{
synchronized(tasks)
{
tasks.add(task);
}
}
public synchronized void stop()
{
hasToStop=true;
}
}

AsyncTask starts after function is finished

I just have a public function where I have some loops etc. and in the beginning of my function I start my AsyncTask which returns me a value which is needed in the near of the end of this function. But somehow the AsyncTask just starts after this function finished ? Is there a way to run the Asynctask before or parallel ? Until today I thought AsyncTask are normally running parallel. I found out the method
.get()
but this is freezing the thread ... I need an alternative or fix
public void my_function ()
{
new async_task().execute()
... //do something
if (returned_value_from_async_task == 10) //Here I need the variable which is returned in the async_task
{
... //do something
}
} //End of function
//When I go to debug mode the AsyncTask starts right here
Yes. Thats the "Async" part of AsyncTask. The code at the end of the function isn't going to wait for the task to finish. so you can't rely on that data to be there. The code you're running in your function probably takes less time than it takes the ThreadPoolExecutor to spool up your task.
Execute the code that depends on the data from the AsyncTask in onPostExecute
EDIT:
Without knowing what "more complex" means, it's hard to say what your best option is. But you could split the function, thusly
public void preExecutePrep() {
YourTask yourTask = new YourTask();
yourTask.execute();
//do what you can without the result
}
private void postExecuteCode(int result) {
if (result != 10) return;
//do the rest
}
then call postExecuteCode in onPostExecute. If this isn't going to cut it, I'll need more specific information to help

Categories

Resources