android - changing Activity UI from application class - android

I extended the Application class in order to create singleton-like object in android.
in this object I have all the HTTP work with my server, and all the other activities can access it and call methods to GET, POST etc.
Code:
public class HttpManagerInstance extends Application {
private HttpClient httpClient;
private HttpGet get;
#Override
public void onCreate() {
httpClient = new DefaultHttpClient();
get = new HttpGet("http://10.100.102.9:8000/users/");
super.onCreate();
}
public Void getUsers() throws Exception {
new executeRequest().execute(get);
return null;
}
private class executeRequest extends AsyncTask<HttpRequest, Void, Integer> {
#Override
protected Integer doInBackground(HttpRequest... params) {
// TODO Auto-generated method stub
HttpRequest request = params[0];
HttpResponse response;
String result="";
try {
response = httpClient.execute((HttpUriRequest) request);
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return responseCode;
}
#Override
protected void onPostExecute(Integer result) {
// TODO Auto-generated method stub
switch (result) {
case HttpStatus.SC_OK:
// request was fine
// Here I want to updated the GUI of the activity that called this method.
break;
}
}
}
}
This is how I call the method from the Activity:
HttpManagerInstance sampleApp = (HttpManagerInstance)getApplicationContext();
sampleApp.getUsers();
Again - I want to access the UI of the Activity that called the method to put an REQUEST ACCEPTED message.
Maybe pass a context? any ideas?

I'd create a listener:
public class HttpManagerInstance extends Application {
private HttpClient httpClient;
private HttpGet get;
public interface ResponseListener{
public void onSuccess(Object data);
}
#Override
public void onCreate() {
httpClient = new DefaultHttpClient();
get = new HttpGet("http://10.100.102.9:8000/users/");
super.onCreate();
}
public Void getUsers(ResponseListener listener) throws Exception {
new executeRequest(listener).execute(get);
return null;
}
private class executeRequest extends AsyncTask<HttpRequest, Void, Integer> {
private ResponseListener mListener;
public executeRequest(ResponseListener listener){
this.mListener = listener;
}
#Override
protected Integer doInBackground(HttpRequest... params) {
// TODO Auto-generated method stub
HttpRequest request = params[0];
HttpResponse response;
String result="";
try {
response = httpClient.execute((HttpUriRequest) request);
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return responseCode;
}
#Override
protected void onPostExecute(Integer result) {
// TODO Auto-generated method stub
switch (result) {
case HttpStatus.SC_OK:
// request was fine
// Here I want to updated the GUI of the activity that called this method.
if(this.mListener != null) mListener.onSuccess(whatEverDataYouWant);
break;
}
}
}
}
Then, in your activity:
HttpManagerInstance sampleApp = (HttpManagerInstance)getApplicationContext();
sampleApp.getUsers(new ResponseListener(){
public void onSuccess(Object data){
//update your ui!
}
});

The short answer is you can't directly reference to the UI from another activity. My advice would be for you to set up a callback on your Application class and call in on executeRequest#onPostExecute then implement that callback on your Activity and update your UI from there.
If you need help to implement the callback check this question

If you need to show message is good option the Dialog Class or the Toast Class, you can see more info are here:
Dialogs: http://developer.android.com/guide/topics/ui/dialogs.html
Toasts: http://developer.android.com/guide/topics/ui/notifiers/toasts.html
But if you want to access or modify a control in your actual activity, then use Runnable class, and context.runOnUiThread() method if you work inside AsyncTask. The real problem is that you can't change UI in a AsyncTask using declaration of the controls. You need to throw a Runnable process to communicate with activity!!. For example:
context.runOnUiThread(new Runnable() {
public void run() {
//Declaration of variables
TextView MyTextView = (TextView) context.findViewById(R.id.txtvMyControl);
MyTextView.setText("My title");
}
}
If I can helps you say me, good luck!

Related

getting result from AsyncTask

I am trying to get the result from the AsyncTask to another class. I am using interface to achieve this. I doing the same procedure in another module and it was working good but I fail to identify the issue in this case...
I'm calling like this from another class.
GroupDetails gd=new GroupDetails();
groups=gd.getGroupList("email");
public class GroupDetails implements AsyncResponse {
String result;
String[] groupList;
public String getGroupList(String userEmail){
ArrayList<NameValuePair> postParameters = new ArrayList<NameValuePair>();
postParameters.add(new BasicNameValuePair("user_email", userEmail));
PhpConnect phpcon=new PhpConnect("http://www.pinnacle2k14.com/letsmeet/get_group.php",postParameters);
phpcon.delegate=this;
phpcon.execute();
result="hello"
return result;
}
#Override
public void processFinish(String output) { //this method not functioning why?
// TODO Auto-generated method stub
result="hello";
//groupList=output.split(",");
}
}
PhpConnect.php
public class PhpConnect extends AsyncTask<String, Void, String> {
String url1;
ArrayList<NameValuePair> postParameters1;
public PhpConnect(String url,ArrayList<NameValuePair> postParameters){
url1=url;
postParameters1=postParameters;
}
public PhpConnect() {
// TODO Auto-generated constructor stub
}
String response;
public AsyncResponse delegate=null;
#Override
protected String doInBackground(String... arg0) {
// TODO Auto-generated method stub
try {
response = CustomHttpClient.executeHttpPost(url1,postParameters1);
} catch (Exception e) {
// TODO Auto-generated catch block
response=e.toString();
}
return response;
}
#Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
delegate.processFinish(result);
}
}
AsynResponse interface
public interface AsyncResponse {
void processFinish(String output);
}
You know you can do
PhpConnect phpcon=new PhpConnect("http://www.pinnacle2k14.com/letsmeet/get_group.php",postParameters) {
#Override
public void onPostExecute(String result) {
//DO YOUR STUFF
}
};
phpcon.execute();
This way you can save the callback.

Want to fire Intent after getting success==true from web service else incorrect/username password in asynctask?

I'm using web service through asynctask for login purpose.I am passing values username and password and in return getting back json of {"success":"true"} or {"success":"false"} .If true then it should fire intent and go to next activity else it should display incorrect username/password but i don't know why intent is not working in onPostExecute. Please help me.
This is my code
public class Dashboard extends Activity {
TextView map;
private String username;
private String password;
public String jArray;
public Boolean login;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dashboard);
Button rtn=(Button)findViewById(R.id.buttonsubmit);
EditText edit_text1=(EditText)findViewById(R.id.editText1);
EditText edit_text2=(EditText)findViewById(R.id.editText2);
String username=edit_text1.getEditableText().toString();
Log.d("username",username);
}
public void onClick(View v)
{
EditText edit_text1=(EditText)findViewById(R.id.editText1);
EditText edit_text2=(EditText)findViewById(R.id.editText2);
String username=edit_text1.getEditableText().toString();
String password=edit_text2.getEditableText().toString();
if(username==null)
{
map.setText("Please enter something");
}
else if(username.isEmpty() || password.isEmpty())
{
Toast.makeText(this, "empty value", Toast.LENGTH_SHORT).show();
}
else
{
Log.d("user",username);
Log.d("password",password);
new MyAsyncTaskMapNoGet().execute();
}
}
public boolean webservreqMAPNOGET(){
try {
//HttpParams httpParams = new BasicHttpParams();
//HttpConnectionParams.setConnectionTimeout(httpParams, TIMEOUT_MILLISEC);
//HttpConnectionParams.setSoTimeout(httpParams, TIMEOUT_MILLISEC);
HttpParams p = new BasicHttpParams();
p.setParameter("user", "1");
// Instantiate an HttpClient
HttpClient httpclient = new DefaultHttpClient(p);
EditText edit_text1=(EditText)findViewById(R.id.editText1);
EditText edit_text2=(EditText)findViewById(R.id.editText2);
String username=edit_text1.getEditableText().toString();
String password=edit_text2.getEditableText().toString();
Log.d("username1",username);
String url = url;
Log.d("url",url );
HttpPost httppost = new HttpPost(url);
// Instantiate a GET HTTP method
try {
Log.i(getClass().getSimpleName(), "send task - start");
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("user", "1"));
httppost.setEntity((HttpEntity) new UrlEncodedFormEntity(nameValuePairs));
ResponseHandler<String> responseHandler = new BasicResponseHandler();
String responseBody = httpclient.execute(httppost, responseHandler);
Log.d("respnse",responseBody);
// Parse
JSONObject json1 = new JSONObject(responseBody);
String jArray = json1.getString("success");
Log.d("success", jArray);
if(jArray=="true")
{
Boolean login=true;
}
else
{
Boolean login=false;
}
return true;
}
catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}
}
catch (Throwable t) {
//Toast.makeText(this, "Request failed: " + t.toString(),Toast.LENGTH_LONG).show();
return false;
}
}
public class MyAsyncTaskMapNoGet extends AsyncTask<Void, Void, Boolean>
{
ProgressDialog mProgressDialog3;
private String json1;
#Override
public void onPostExecute(Boolean result) {
mProgressDialog3.dismiss();
mProgressDialog3.dismiss();
mProgressDialog3.dismiss();
}
#Override
public void onPreExecute() {
mProgressDialog3 = ProgressDialog.show(Dashboard.this, "Loading...", "Data is Loading...");
}
#Override
public Boolean doInBackground(Void... params) {
if(webservreqMAPNOGET()){
Log.d("yay","SUCCESS");
return true;
}
else{
Log.d("err","ERROR");
return false;
}
}
public void onPostExecute() {
// dismiss the dialog once done
if(login)
{
startActivity(new Intent("com.example.esstel___ippbx.secondactivity"));
}
else
{
Toast.makeText(Dashboard.this, "incorrect username/password", Toast.LENGTH_LONG).show();
}
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.dashboard, menu);
return true;
}
}
Change your onPostExecute to
#Override
public void onPostExecute(Boolean result) {
super.onPostExecute(result);
mProgressDialog3.dismiss();
if(result) // true
{
// start activity
}
else
{
// display toast
}
}
Why do you have 3 statments mProgressDialog3.dismiss() remove the other two.
Also remove this you already have a Overriden onPostExecute
public void onPostExecute() {
Also you are get the text from editext in doInbackground. Initialize edittext's as a class member. Initialize in onCreate. get the text on button click. pass the values directly to doInbackground or to the constructor asynctask and use the same.
Also
public class Dashboard extends Activity implements OnClickListenr{
In onCreate
rtn.setOnClickListener(this);
Also there is no need to initialize views every time. Initialize it in onCreate once
You are having two postExecute method in your asynctask. The logic for transmitting to a new activity is mentioned in your custom postexecute method (not the overridden one ). As you are having two postexecutes, your async task is only identifying the first overridden one . you need to call your custom postexecute method from the overidden method like::
#Override
public void onPostExecute(Boolean result) {
mProgressDialog3.dismiss();
mProgressDialog3.dismiss();
mProgressDialog3.dismiss();
onPostExecute();
}
Also your TextView map is not initialised.you are doing a setText() to an uninitialised textView ,as a result it will give a NPE.

Progress Dialog does not display due to use of thread.get() method

I want to display a Progress Dialog while I have two threads running one after the other, but my data structure that I use gets populated via the threads, becomes null. Thus I used thread.get() method to wait for the thread to be finished....not sure how I can get around this here is an example of one of my Async Threads:
private void performDetailSearch(String reference) {
String addplus = searchterm.replace(" ", "+");
RestClientDS restpSd = new RestClientDS();
String url = PLACES_DETAILS_URL +"reference="+ reference + "&sensor=false&key=" + API_KEY;
Log.d("url",url);
String[] URL = {url};
restpSd.execute(URL);
try {
restpSd.get();
}
catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
catch (ExecutionException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
Use AsyncTask instead of Thread and call another task after one gets completed.
AsyncTask can be called this way new FetchData().execute();
private class FetchData extends AsyncTask<String, Void, Boolean> {
private ProgressDialog dialog = new ProgressDialog(HomeActivity.this);
/** progress dialog to show user that the backup is processing. */
/** application context. */
protected void onPreExecute() {
this.dialog.setMessage(getResources().getString(
R.string.Loading_String));
this.dialog.show();
}
protected Boolean doInBackground(final String... args) {
try {
//do your background work
return true;
} catch (Exception e) {
Log.e("tag", "error", e);
return false;
}
}
#Override
protected void onPostExecute(final Boolean success) {
if (dialog.isShowing()) {
dialog.dismiss();
}
if (success) {
//call the another asynctask from here.
// new FetchData2().execute();
}
}
}

Comments on my MVP pattern for Android

I am planning to use MVP pattern for my new Android project. I have done some sample code and I would like to know, have I implemented it correctly? Please give comments on the code and also post your suggestions.
my activity class I am extending it from my BaseView class and I am implementing an interface. this activity simply calls an webservice in a new thread and updates the value in the textview.
public class CougarTestView extends BaseView implements ICougarView,
OnClickListener {
CougarTestPresenter _presenter;
public String activityName = "CougarHome";
/** Called when the activity is first created. */`enter code here`
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState, activityName);
setContentView(R.layout.main);
_presenter = new CougarTestPresenter(this);
getSubmitBtn().setOnClickListener(this);
getCallInfoBtn().setOnClickListener(this);
}
private Button getCallInfoBtn() {
return (Button) findViewById(R.id.btn_callinfo);
}
public void setServiceValue(String retVal) {
// TODO Auto-generated method stub
getResultLabel().setText(retVal);
setPbar(false);
// toastMsg(retVal);
}
public void ResetPbar() {
getProgressBtn().setProgress(0);
}
public void setProcessProgress(int progress) {
if (getProgressBtn().getProgress() < 100) {
getProgressBtn().incrementProgressBy(progress);
} else {
setPbar(false);
}
}
private TextView getResultLabel() {
return (TextView) findViewById(R.id.result);
}
private Button getSubmitBtn() {
return (Button) findViewById(R.id.btn_triptype);
}
private ProgressBar getProgressBtn() {
return (ProgressBar) findViewById(R.id.pgs_br);
}
public void setPbar(boolean visible) {
if (!visible) {
getProgressBtn().setVisibility(View.GONE);
} else
getProgressBtn().setVisibility(View.VISIBLE);
}
#Override
public void setHttpResult(String retVal) {
// TODO Auto-generated method stub
setServiceValue(retVal);
}
private void toastMsg(String msg) {
Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
}
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.btn_triptype: {
try {
_presenter.valueFromService(RequestType.CallInfo, 0);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
}
default:
setServiceValue("default");
}
}
}
My activity class: in my activity class i am having a textview and a button. when i press the button , it call the webservice to get the data in the presenter class. the presenter class calls the webservice parses the response and sets the value in the textview of the activity.
My presenter class
public class CougarTestPresenter {
ICougarView mIci;
RequestType mRtype;
public String result= "thisi s result i";
Handler mHandle;
public CougarTestPresenter(ICougarView ici) {
mIci = ici;
}
public void valueFromService(RequestType type, int x) throws Exception{
String url = getURLByType(type);
// GetServiceresult service = new GetServiceresult();
// service.execute(url);
Handler handle = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case Globals.IO_EXPECTION: {
Toast.makeText(mIci.getContext(), msg.toString(),
Toast.LENGTH_LONG).show();
NetworkConnectivityListener connectivityListener = NetworkConnectivityListener
.getInstace();
mHandle = CustomHandler.getInstance(mIci.getContext(),
connectivityListener, mIci);
connectivityListener.registerHandler(mHandle,
Globals.CONNECTIVITY_MSG);
connectivityListener.startListening(mIci.getContext());
mIci.setPbar(false);
}
break;
case Globals.RHAPSODY_EXCEPTION:{
ExceptionInfo exInfo =null;
try {
exInfo = Utility.ParseExceptionData(msg.obj.toString());
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mIci.setServiceValue(exInfo.Message + exInfo.Type +exInfo.Detail);
// new HandleRhapsodyException(mIsa, exInfo);
}
break;
default: {
Toast.makeText(mIci.getContext(), msg.toString(),
Toast.LENGTH_LONG).show();
mIci.setServiceValue(msg.obj.toString());
}
}
}
};
ServiceResult thread = new ServiceResult(handle, url);
mIci.setPbar(true);
thread.start();
}
public String getURLByType(RequestType type) {
// TODO Auto-generated method stub
switch (type) {
case CallInfo: {
return ("www.gmail.com");
}
case TripType: {
return ("www.google.com");
}
default:
return ("www.cnet.com");
}
}
private class ServiceResult extends Thread {
Handler handle;
String url;
public ServiceResult(Handler handle, String url) {
this.handle = handle;
this.url = url;
}
public void run() {
sendExceptionLog(handle);
}
}
public void sendExceptionLog(Handler handle) {
DebugHttpClient httpClient = new DebugHttpClient();
HttpGet get = new HttpGet(
"https://192.168.194.141/TripService/service1/");
try {
HttpResponse response = httpClient.execute(get);
HttpEntity r_entity = response.getEntity();
String xmlString = EntityUtils.toString(r_entity);
// setdvrid.setText(xmlString + " "
// + response.getStatusLine().getStatusCode());
httpClient.getConnectionManager().shutdown();
if (response.getStatusLine().getStatusCode() != 200) {
handle.sendMessage(Message.obtain(handle, Globals.RHAPSODY_EXCEPTION,
xmlString));
result= Utility.ParseExceptionData(xmlString).Message;
}
else
{
handle.sendMessage(Message.obtain(handle, Globals.SERVICE_REPONSE,
response.getStatusLine().getStatusCode()
+ response.getStatusLine().getReasonPhrase()
+ xmlString));
}
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
handle.sendMessage(Message.obtain(handle, Globals.OTHER_EXPECTION,
e.getMessage().toString() + "she"));
} catch (IOException e) {
// TODO Auto-generated catch block
handle.sendMessage(Message.obtain(handle, Globals.IO_EXPECTION, e
.getMessage().toString() + "he"));
} catch (Exception e) {
handle.sendMessage(Message.obtain(handle, Globals.OTHER_EXPECTION,
e.getMessage().toString() + "it"));
}
}
the below interface is implemented in the activity class and the instance of the activity class is sent as interface object to the constructor of the presenter class.
my view interface
public interface ICougarView {
public void setServiceValue(String retVal);
public void setProcessProgress(int progress);
public void setPbar(boolean b);
public void ResetPbar();
public Context getContext();
}
Sorry for the late :)
I've use MVP on Android this way.
Activities are presenters. Every presenter has a link to model(s) (sometimes it is services, sometimes not, depending from the task) and to view(s). I create custom view and set it as the content view for activity.
See:
public class ExampleModel {
private ExampleActivity presenter;
public ExampleModel(ExampleActivity presenter) {
this.presenter = presenter;
}
//domain logic and so on
}
public class ExampleActivity extends Activity {
private ExampleModel model;
private ExampleView view;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
model = new ExampleModel(this);
view = new ExampleView(this);
setContentView(view);
}
// different presenter methods
}
public class ExampleView extends LinearLayout {
public ExampleView(Context context) {
super(context);
}
}
Also, I've discussed this topic here.
I should warn you, that Activity shouldn't be considered as the view. We had very bad expirience with it, when we wrote with PureMVC which considered Activity as view component. Activity is excellently suitable for controller/presenter/view model (I've tried all of them, I like MVP the most), it has excellent instrumentation for managing the views (View, Dialog and so on) while it's not a view itself.

Updating main thread tablelayout from async thread

I have a problem with updating my table-layout from my async class.
MY async class is fetching XML data so I don't block the main thread. My logs show the XML data is coming through but I don't know how to update my view with the data.
So I am attempting to put the data in tablerows and add the rows to the TableLayout but the logs show errors suggesting the Async class is not allowed to update my TableLayout view.
My code is as follows:
public class RemotePrimary extends Activity {
private static String SERVER_PATH = "http://test2.icerge.com/";
private static String XML_FILE1 = "samplexml";
//private static String SERVER_PATH = "http://tqs.mamlambo.com/";
//private static String XML_FILE1 = "scores.jsp";
private String[] data = new String[10];
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TableLayout datatable = (TableLayout)findViewById(R.id.TableLayout_data);
Downloader downloader = new Downloader();
downloader.execute(SERVER_PATH + XML_FILE1, datatable);
}
private class Downloader extends AsyncTask<Object, String, Boolean>{
TableLayout table;
#Override
protected Boolean doInBackground(Object... params) {
// TODO Auto-generated method stub
String path = (String)params[0];
table = (TableLayout)params[1];
XmlPullParser xmldata = null;
try {
URL serverPath = new URL(path);
xmldata = XmlPullParserFactory.newInstance().newPullParser();
xmldata.setInput(serverPath.openStream(), null);
addRecord(xmldata, table);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return true;
}
#Override
protected void onProgressUpdate(String... values) {
// TODO Auto-generated method stub
//super.onProgressUpdate(values);
}
private boolean addRecord(XmlPullParser data, TableLayout table){
int eventType = -1;
boolean bFoundScores = false;
//find some records from xml
while(eventType != XmlResourceParser.END_DOCUMENT){
if( eventType == XmlResourceParser.START_TAG ){
//get the name of the tag(eg scores or score)
String strName = data.getName();
if( strName.equals("node") ){
bFoundScores = true;
String scoreValue = data.getAttributeValue(null, "Title");
String scoreRank = data.getAttributeValue(null, "Type");
String scoreUserName = data.getAttributeValue(null, "Nid");
Log.e("ADDING: ", scoreValue);
//Log.e("RETRIEVED", "collected : "+scoreValue+", "+scoreRank+", "+scoreUserName);
//publishProgress(scoreValue, scoreRank, scoreUserName);
TableRow newRow = new TableRow(RemotePrimary.this);
TextView rowText = new TextView(RemotePrimary.this);
rowText.setText(scoreValue);
newRow.addView(rowText);
table.addView(newRow);
}
}
try {
eventType = data.next();
} catch (XmlPullParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return true;
}
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
}
#Override
protected void onPostExecute(Boolean result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
}
}//close Downloader class
}//close RemotePrimary class
It's a bit much I know but I'll appreciate any help.
Thanks a great deal :-)
You can only make changes from the UI on the UI thread. The AsyncTask gives you an easy place to do this via onPostExecute. As it says in the docs, onPostExecute is always performed on the UI thread.
In doInBackground, do all of the hard work of building up the structured data that wish to display. Return that data so that it will be passed into onPostExecute, then in there add the appropriate table rows.

Categories

Resources