Wednesday, March 12, 2014

AcyncTask that calls JNI Background process with update progress

When you need to call JNI method that does a background job, and report its progress, AsycTask can't do that job, since the background job is a black box, and you can't report the progress from it.
Assuming you can get the progress using other means (file size, read a file, etc)
you can use this pattern:
Use a Class with 2 threads, one for the worker and one for the progress report.
The last updates the progress bar (which is a member).
Here is an Example code:

public class ProgressBarExample extends Activity  {

public ProgressDialog progressBar;


@Override
 public void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
   

     setContentView(R.layout.ffmpeg_demo_client);
   
   
   
     Button invoke =  (Button)findViewById(R.id.invokeButton);
     invoke.setOnClickListener(new OnClickListener() {
public void onClick(View v){
doWork();
}
});
   
   
 
}

private Handler handler = new Handler() {
        @Override
            public void handleMessage(Message msg) {
        if (progressBar != null) {
        progressBar.dismiss();
        }
           

        }
    };

public void doWork() {
 progressBar = new ProgressDialog(ProgressBarExample.this);
 progressBar.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
 progressBar.setMax(100);
 progressBar.setProgress(0);
 progressBar.show();
   
     new Thread() {
         public void run() {
         Log.d(Prefs.TAG,"Worker started");
             try {
             doWorkNative();
                 handler.sendEmptyMessage(0);

             } catch(Exception e) {
                 Log.e("threadmessage",e.getMessage());
             }
         }
     }.start();
   
     // Progress update thread
     new Thread() {
         public void run() {
       
         try {
         while (true) {
         sleep(300);
         progress = calcProgress();
         if (progress != 0 && progress < 100) {
         progressBar.setProgress(progress);
         }
         else if (progress == 100) {
         Log.i(Prefs.TAG, "==== progress is 100, exiting Progress update thread");
         break;
         }
         }

         } catch(Exception e) {
         Log.e("threadmessage",e.getMessage());
         }
         }
     }.start();
 }

public native void doWorkNative();




private int calcProgress() {
int progree = getProgressFromFile();
return progress;
}

}