Android AsyncTask : UI operation not working in Android from Background Task - java

What i want :
wait for connection. Until the connection is received, display a
blank screen
as soon as connected, set the current view to a custom view ( using setContentView() ). This I'm trying to do from Background Thread( AsyncTask )
Then after that I'll keep accepting the points from client and keep updating them on UI thread. For this I'm accepting points from client and sending to publishProgess()
But for some reason, the second step itself isn't working.
MainActivity.java
public class MainActivity extends AppCompatActivity {
public ServerSocket server;
public Socket socket;
public Slate slate ;
private Paint mPaint;
public static MainActivity context;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
context = this;
(new ServerTask()).execute();
}
public static MainActivity getContext()
{
return context;
}
public void start_slate(){
slate = new Slate(this);
slate.setBackgroundColor(Color.parseColor("#000000"));
setContentView(slate);
}
public class Slate extends View {
.....
.....
draw(){
....
....
}
} /*custom drawing view*/
}
Background Task
/*Background Task*/
class ServerTask extends AsyncTask<Void, Action, Void>
{
private WeakReference<MainActivity> mainActivity;
private Action action;
#Override
protected void onPreExecute() {
super.onPreExecute();
mainActivity = new WeakReference<>(MainActivity.getContext());
}
#Override
protected Void doInBackground(Void... voids) {
ObjectInputStream stream;
try{
mainActivity.get().server = new ServerSocket(3107);
mainActivity.get().socket = mainActivity.get().server.accept();
stream = new ObjectInputStream(mainActivity.get().socket.getInputStream());
MainActivity.getContext().runOnUiThread(new Runnable() {
#Override
public void run() {
MainActivity.getContext().start_slate();
}
}); /*BUT THE VIEW IS NOT CHANGING*/
while(true)
{
if(isCancelled()){
break;
}
action = (Action)stream.readObject();
publishProgress(action);
}
}catch (Exception exception)
{
exception.printStackTrace();
}
return null;
}
#Override
protected void onProgressUpdate(Action... actions) {
super.onProgressUpdate(actions);
((mainActivity.get()).slate).draw(actions[0]);
}/*this will send the co-ordinates to current drawing view*/
}
NOTE : even if i try to set the view in onProgressUpdate() , it still does not happen.
It happens only in onPostExecute(). But I don't want that because, after changing the view, I still have to accept coordinates (The while loop part)

Related

Can onProgressUpdate be overloaded in activity?

I am trying to accept socket connections from clients.
But in my AsyncTask i came across two situations where I'll need to update UI thread. the first case where as soon as socket is connected, it should change the current content view. And 2nd case where I'm receiving constant stream of objects which I'm updating on UI through publishProgress().
How do I go about doing so?
public class MainActivity extends AppCompatActivity {
myCustomDrawingView view;
....
....
.
public static MainActivity getContext(){return context;}
....
..
public class myCustomDrawingView extends View {
..
..
}
setNewContentView(){
view = new myCustomDrawingView(this);
setContentView(view);
}
}
class ServerTask extends AsyncTask<Void, Action, Void>
{
private WeakReference<MainActivity> mainActivity;
private Action action;
#Override
protected void onPreExecute() {
super.onPreExecute();
mainActivity = new WeakReference<>(MainActivity.getContext());
}
#Override
protected Void doInBackground(Void... voids) {
ObjectInputStream stream;
try{
mainActivity.get().server = new ServerSocket(3107);
mainActivity.get().socket = mainActivity.get().server.accept();
stream = new ObjectInputStream(mainActivity.get().socket.getInputStream());
(mainActivity.get()).setNewContentView();
/*I know this won't work....
But I want something like this to happen.
What are Alternatives?*/
while(true)
{
if(isCancelled()){
break;
}
action = (Action)stream.readObject();
publishProgress(action);
}
}catch (Exception exception)
{
exception.printStackTrace();
}
return null;
}
#Override
protected void onProgressUpdate(Action... actions) {
super.onProgressUpdate(actions);
((mainActivity.get()).myCustomDrawingView).draw(actions[0]);
}
}

AsyncTask.execute() doesn't wait for doInBackground to complete

I know this is a duplicate question but please hold on. I have read some similar questions and answer but none of them seems working for me.
What to do:
I have to do a search which will send a request to a web service and receive a response.
As i can't consume network on UI thread, I used AsyncTask.
What i tried:
I tried using task.execute() this returns immediately without even showing progressdialog box and i receive response as null (set in onPostExecute)
if i use task.execute.get() then it freezes screen and again no dialog box shows up (but i receive response correctly).
Below is my code with task.execute. Kindly correct me.
public class LookIn extends AppCompatActivity implements View.OnClickListener{
private Button btn=null;
private TextView txtPinCode=null;
private Service service=null;
private final static int timeout=20;
private String jsonResponse;
//private ProgressBar helperSearchProgressBar;
private String pincode="";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_look_in);
btn=(Button)findViewById(R.id.button);
btn.setOnClickListener(this);
txtPinCode=(TextView) findViewById(R.id.txtPinCode);
this.service=(Service) ParamFactory.getParam(ConstantLabels.SELECTED_SERVICE_ID);
// this.helperSearchProgressBar=(ProgressBar)findViewById(R.id.helperSearchProgressBar);
}
#Override
public void onClick(View v) {
String pincode= txtPinCode.getText().toString();
if(pincode==null || pincode.isEmpty() || pincode.length()!=6)
{
this.txtPinCode.setError("Please enter a 6 degit pin code from 700000 to 700200");
return;
}
ParamFactory.setParam(ConstantLabels.PINCODE_ID,pincode);
this.pincode=pincode;
loadHelper();
Intent intent= new Intent(LookIn.this,SearchResult.class);
startActivity(intent);
}
public void setJsonResponse(String jsonResponse)
{
this.jsonResponse=jsonResponse;
}
private void loadHelper()
{
Log.v("Callme", "Running thread:" + Thread.currentThread().getId());
ArrayAdapter<User> adapter=null;
String params=this.pincode+","+this.service.getId();
List<User> result=null;
try {
new CallmeGetHelperAsyncTask().execute(params); //my task.execute()
result= RestUtil.getUserList(jsonResponse);
adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, result);
ParamFactory.setParam("getHelperForService", adapter);
}
catch(JSONException x)
{
Log.e("Callme", Log.getStackTraceString(x));
}
}
class CallmeGetHelperAsyncTask extends AsyncTask<String,Void,String > {
// private Context context=null;
private ProgressDialog dialog=null;
private String jsonResponse;
private LookIn activity;
public CallmeGetHelperAsyncTask(){}
public CallmeGetHelperAsyncTask(LookIn activity)
{
this.activity=activity;
}
#Override
protected void onPreExecute() {
this.dialog= new ProgressDialog(LookIn.this);
this.dialog.setMessage("Loading...");
this.dialog.show();
Log.v("Callme","Dialog Shown");
}
#Override
protected void onPostExecute(String s) {
if(s!=null)
{
this.activity.setJsonResponse(s);
}
else
{
Log.v("Callme","kill me");
}
if(this.dialog.isShowing())
{
Log.v("Callme","Closing Dialog");
this.dialog.dismiss();
}
}
#Override
protected String doInBackground(String... params) {
Log.v("Callme","From Background:"+Thread.currentThread().getId());
String pincode=params.clone()[0].split(",")[0];
String serviceId=params.clone()[0].split(",")[1];
String url=String.format(URL.GET_HELPER,serviceId,pincode);
jsonResponse= null;
try {
jsonResponse = RestUtil.makeRestRequest(url);
} catch (IOException e) {
e.printStackTrace();
}
return jsonResponse;
}
}
}
Note: I haven't tried using while loop to waiting for the asynctask, because i think that will also end up freezing my screen. Please correct me if i am wrong
I haven't tried using while loop to waiting for the asynctask
No need to use loop for waiting AsyncTask Result.
Because onPostExecute method execute after doInBackground so instead of using jsonResponse just after call of execute method, do it inside setJsonResponse method, because this method called from onPostExecute which always run on Main UI Thread:
public void setJsonResponse(String jsonResponse)
{
this.jsonResponse=jsonResponse;
//Create adapter object here
result= RestUtil.getUserList(jsonResponse);
adapter = new ArrayAdapter(...);
ParamFactory.setParam("getHelperForService", adapter);
}

AsyncTask data communication with nested Classes

I have a specific scenario and I need your help.
I'm trying to build an App in Android that involves network communication.
I am using AsyncTask for the http POST requests.
I have another class called Proxy (not a good one.. will be changed) which holds different kinds of functionalities (registerUser, setUserName, getUserPermission...)
And Of course, I have an Activity.
My Activity holds an instance of Proxy class.
My goal, is to push a button in the activity, it will call a method from Proxy class, which in its turn calls the AsyncTask's execute() method that actually run the http POST.
I was wondering how to get the data from AsyncTask's onPostExecute to my activity.
What I have in mind is to have an interface in AsyncTask, which will be implemented in Proxy class, and another interface in Proxy class which will be implemented in my Activity class.
Roll the data all the way to my Activity.
I want to hear your thoughts about whether this is the way to go, or another approach is preffered.
Thanks a lot for your help.
Adding some code
public class RegisterActivity extends FragmentActivity implements Proxy.OnProxyHttpPostResponseListener {
private Proxy proxy;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register);
this.proxy = new Proxy();
this.proxy.setHttpPostResponseListener(this);
}
#Override
public void onProxyHttpPostResponse(String response) {
//Do something when http post returns
}
}
public class Proxy {
public interface OnProxyHttpPostResponseListener {
void onProxyHttpPostResponse(String response);
}
private OnProxyHttpPostResponseListener httpPostResponseListener;
public void setHttpPostResponseListener(OnProxyHttpPostResponseListener listener) {
this.httpPostResponseListener = listener;
}
private class HttpPostAsync extends AsyncTask<Pair<String, ArrayList<Pair<String, String>>>, Void, String> {
#Override
protected String doInBackground(Pair<String, ArrayList<Pair<String, String>>>... params) {
return this.httpPost(params[0].first, params[0].second);
}
protected void onPostExecute(String response) {
httpPostResponseListener.onProxyHttpPostResponse(response);
}
}
If you're just needing HTTP POST functionality then an AsyncTask might not be the best choice. AsyncTask really shines if you need to get progress updates as the task is executing (with onProgressUpdate(Progress... progress)). If you'd like to use AsyncTask nonetheless, iroiroys' reply should help.
A bit more simply, you could just use a Handler thread straight up. Something like this:
public class HandlerExampleActivity extends Activity {
private Button postButton;
private Button getButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handler_example);
backgroundThread = new BackgroundThread();
backgroundThread.start();
postButton = (Button) findViewById(R.id.button_post);
postbutton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
backgroundThread.post("DATA_HERE");
}
});
getButton = (Button) findViewById(R.id.button_get);
getbutton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
backgroundThread.get("URL_HERE");
}
});
}
#Override
protected void onDestroy() {
super.onDestroy();
backgroundThread.exit();
}
private class BackgroundThread extends Thread {
private Handler backgroundHandler;
public void run() {
Looper.prepare();
backgroundHandler = new Handler();
Looper.loop();
}
public void post(DataType data) {
backgroundHandler.post(new Runnable() {
#Override
public void run() {
// pull data and do the POST
uiMsg = uiHandler.obtainMessage(POST_COMPLETE, whatever_data_passing_back, 0, null);
uiHandler.sendMessage(uiMsg);
}
});
}
public void get(URL data) {
backgroundHandler.post(new Runnable() {
#Override
public void run() {
// GET data
uiMsg = uiHandler.obtainMessage(GET_COMPLETE, whatever_data_passing_back, 0, null);
uiHandler.sendMessage(uiMsg);
}
});
}
public void exit() {
backgroundHandler.getLooper().quit();
}
}
private final Handler uiHandler = new Handler() {
public void handleMessage(Message msg) {
switch(msg.what) {
case POST_COMPLETE:
// handle it
break;
case GET_COMPLETE:
// handle it
break
case MESSAGE_BACK_TO_UI_THREAD:
// do something
break;
case OPERATION_FAIL:
// oh no!
break;
case OPERATION_SUCCESS:
// yay!
break;
}
}
};
}
I suggest you try Handler and Handler.Callback.
Below I made it simple example..
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Handler.Callback;
import android.os.Message;
public class MainActivity extends Activity implements Callback {
Handler handler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
handler = new Handler(this);
Proxy proxy = new Proxy(handler);
proxy.foo();
}
private class Proxy {
Handler handler;
public Proxy(Handler handler) {
this.handler = handler;
}
private void foo() {
new myAsync().execute();
}
private class myAsync extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
Message msg = handler.obtainMessage();
msg.obj = result;
handler.sendMessage(msg);
}
}
}
#Override
public boolean handleMessage(Message msg) {
// Handle Message here!
return false;
}
}

VideoView in Android is not playing video correctly

I am having a strange issue playing a VideoView. I have done my best to simplify the code as much as possible. Below are 4 classes: A, MirrorActivity, Replay, and MyTask. Assume the following occurs in this order:
A is created.
MirrorActivity() is created.
Inside MirrorActivity()'s onCreate(), that instance calls A's setMirrorActivity() to allow A to have a reference to it.
A's doThis() method is called, which executes mirrorActivity.playVideo().
playVideo() is executed.
Replay's executeVideo() is called.
MyTask is executed.
For some strange reason, when the above is executed, the video does not play. However, when the myButton ImageButton is pressed inside MirrorActivity, it plays the video on command. Both of these seem to be doing the same thing by calling MirrorActivity's playVideo(). Do you know why the above does not execute?
A
public class A{
private static final A instance = new A();
private MirrorActivity mirrorActivity;
public static A getInstance() {
return instance;
}
public void setMirrorActivity(MirrorActivity mirrorActivity) {
this.mirrorActivity = mirrorActivity;
}
public void doThis(String url){
mirrorActivity.playVideo(String url);
}
}
MirrorActivity
public class MirrorActivity extends Activity {
public static String VIDEO_URL = "example.mp4";
public VideoView mVideoView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_overlay_gradient);
// Set Mirror Activity
A.getInstance().setMirrorActivity(this);
mVideoView = (VideoView) findViewById(R.id.mirrorVideoView);
MyTask vTask = new MyTask(mVideoView);
ImageButton myButton = (ImageButton) findViewById(R.id.myButton);
myButton.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v)
{
MirrorActivity.this.playVideo(MirrorActivity.VIDEO_URL);
}
});
}
public void playVideo(String videoURL)
{
MyTask mt = new MyTask(mVideoView);
Replay.executeVideo(MirrorActivity.VIDEO_URL,
this,
mVideoView,
mt);
}
}
Replay
public class Replay{
public static void executeVideo(String uri, Activity activity, VideoView vid, MyTask mt)
{
vid.setMediaController(new MediaController(activity););
vid.setVideoURI(Uri.parse(uri));
mt.execute();
}
}
MyTask
public class MyTask extends AsyncTask<Void, Integer, Void> {
private VideoView video;
private int duration = 0; // in milliseconds
public MyTask(VideoView vid) {
video = vid;
}
#Override
protected Void doInBackground(Void... params) {
video.start();
video.requestFocus();
video.setOnPreparedListener(new OnPreparedListener(){
#Override
public void onPrepared(MediaPlayer mp) {
duration = video.getDuration();
}
});
return null;
}
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}
}
I think UI element cannot access in doInBackground . And also start() after every declaration.
Try this method too.
private MediaController ctlr;
#Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.activity_overlay_gradient);
getWindow().setFormat(PixelFormat.TRANSLUCENT);
// Set Mirror Activity
A.getInstance().setMirrorActivity(this);
mVideoView = (VideoView) findViewById(R.id.mirrorVideoView);
Uri uri=Uri.parse(videourl or video path);
mVideoView .setVideoURI(uri);
mVideoView .setVideoPath(videourl);
ctlr=new MediaController(this);
ctlr.setAnchorView(video);
ctlr.setMediaPlayer(video);
mVideoView .setMediaController(ctlr);
mVideoView .requestFocus();
mVideoView .start();
}
Omg. I believe I found the solution. I'm sorry to those who were investigating, but here is what I did to get it to work both ways. Pressing imageButton and calling A.doThis() will be able to play the video now.
I modified MirrorActivity's playVideo() function to use the following:
public void playVideo(final String videoURL)
{
Runnable runnable = new Runnable(){
#Override
public void run()
{
MyTask mt = new MyTask(mVideoView);
Replay.executeVideo(videoURL,
MirrorActivity.this,
mVideoView,
mt);
}
});
Handler mainHandler = new Handler(Looper.getMainLooper());
mainHandler.post(runnable);
}

Calling activity from inside a background thread

I have an acitivity with three fragments is attched on it and there is a class that is responsible for my tcp connection in activity. TCP class works as async. Inside onCreate method of main activity I am starting the tcp connection. Then when I click a button I am starting a new activity and getting the current tcp connection in new activity using a singleton class. I can send messages from the new activity to server using the available tcp. However it is an asyc task so I can't do changes in new activity according to the message that is received from server.
How can I change the layout of new activity from async task?
//Activity code:
public class MainScreen extends FragmentActivity implements ActionBar.TabListener {
TCPClient mTcpClient;
connectTask cnnTask;
///The class is responsible for tcp connection
public class connectTask extends AsyncTask<String, String, TCPClient> {
#Override
public TCPClient doInBackground(String... message) {
//we create a TCPClient object
mTcpClient = new TCPClient(new TCPClient.OnMessageReceived() {
#Override
//here the messageReceived method is implemented
public void messageReceived(String message) {
//do process
}
}
protected void onCreate(Bundle savedInstanceState) {
SharedPreferences preferences = null;
super.onCreate(savedInstanceState);
try {
cnnTask = new connectTask();
preferences = this.getSharedPreferences("MyPreferences",
Context.MODE_PRIVATE);
mTcpClient.SERVERIP = preferences.getString("IPAddress", "0");
mTcpClient.SERVERPORT = Integer.parseInt(preferences.getString("Port", "13759"));
cnnTask.execute("");
} catch (Exception e) {
}
//..
SingletonTCP .getInstance().setmTCPClient(mTcpClient);
}
//Fragment code:
public class FragmentDesign extends Fragment implements View.OnClickListener {
public void onClick(View v) {
String name = v.getTag().toString();
Intent intent = new Intent(getActivity(),NewActivity.class);
intent.putExtra("Name", this._name);
startActivity(intent);
}
}
//Singleton class to set and get the current TCPClient.
public class SingletonTCP {
private TCPClient mTCPClient;
public TCPClient getmTCPClient() { return mTCPClient; }
public void setmTCPClient(TCPClient mTCPClient) {this.mTCPClient = mTCPClient;}
private static final SingletonTCP holder = new SingletonTCP ();
public static SingletonTCP getInstance() {return holder;}
}
enter code here
//New activity code.
public class NewActivity extends Activity implements View.OnClickListener {
public class TCP extends AsyncTask<String, String, TCPClient> {
#Override
protected TCPClient doInBackground(String... params) {
mTCPClient = new TCPClient(new TCPClient.OnMessageReceived() {
#Override
public void messageReceived(String message) {
mes = message;
}
});
return null;
}
}
#Override
public void onClick(View v) {
String command = "<message>";
this.mTCPClient.sendMessage(command);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
mTCPClient = SingletonTCP .getInstance().getmTCPClient();
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new_activity);
Bundle extras = getIntent().getExtras();
departmanAdi = extras.getString("Name");
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(this);
tcp = new TCP();
tcp.execute("");
}
}
You could call publishProgress() from inside doInBackground(), which will call the onProgressUpdate() on the UI thread. In onProgessUpdate(), you can access and make changes to your activity.
This is described in the documentation here.

Categories

Resources