I'm retrieving some information from the server using REST. I make a Get call using AsyncTask. But I need to wait for the results... Is there any way to do it synchronously? So I can get the result.
Code:
private void sendStuff(Context context, String[] params) {
RESTGet restGet = new RESTGet(context);
restGet.setMessageLoading("Loading...");
try {
restGet.execute(params);
} catch (Exception e) {
e.printStackTrace();
}
restGet.stopMessageLoading();
Intent intent = new Intent(context, ShowPictures.class);
((Activity)context).startActivity(intent);
}
Thanks...
You can use get() to wait for the task to end and even get its result. But I would not recommend this, because it will freeze your app.
Example assuming that RESTGet extends AsyncTask:
private void sendStuff(Context context, String[] params) {
final int TIMEOUT = 2000;
RESTGet restGet = new RESTGet(context);
restGet.setMessageLoading("Loading...");
try {
restGet.execute(params).get(TIMEOUT, TimeUnit.MILLISECONDS);
} catch (Exception e) {
e.printStackTrace();
}
restGet.stopMessageLoading();
Intent intent = new Intent(context, ShowPictures.class);
((Activity)context).startActivity(intent);
}
Instead of using get, put your code in onPostExecute method, so it will be called after the task execution.
Ex:
private void sendStuff(Context context, String[] params) {
RESTGet restGet = new RESTGet(context) {
#Override
protected void onPostExecute(String feed) {
super.onPostExecute(feed);
this.stopMessageLoading();
Intent intent = new Intent(context, ShowPictures.class);
((Activity)context).startActivity(intent);
}
}.execute(params);
}
Hope it helps...
Related
I am trying to set up iAP for a Premium membership.
I've added my app and my signed apk to the developer console and then I started following this example: Implementing In-app Billing
I've noticed a tricky part that says:
Warning: Do not call the getSkuDetails method on the main thread. Calling this method triggers a network request which could block your main thread. Instead, create a separate thread and call the getSkuDetails method from inside that thread.
so this is the code I wrote:
public class class...
Bundle querySkus = new Bundle();
/** gestisce gli acquisti in app */
IInAppBillingService mService;
ServiceConnection mServiceConn = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = IInAppBillingService.Stub.asInterface(service);
}
#Override
public void onServiceDisconnected(ComponentName name) {
mService = null;
}
};
and in my onCreate() method:
Intent serviceIntent = new Intent("com.android.vending.billing.InAppBillingService.BIND");
serviceIntent.setPackage("com.android.vending");
bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE);
ArrayList<String> skuList = new ArrayList<String>();
skuList.add("premiumUpgrade");
querySkus.putStringArrayList("chords_premium", skuList);
AsyncTask.execute(new Runnable() {
#Override
public void run() {
Bundle skuDetails = mService.getSkuDetails(3, getPackageName(), "inapp", querySkus);
}
});
now on Bundle skuDetails = mService.getSkuDetails(3, getPackageName(), "inapp", querySkus); I'm getting:
Unhandled Exception: android.os.RemoteException
First of all, how do I fix it?
I'm implementing this code in my main activity even though the button the should redirect to the buying dialog is in another activity. Am I doing it right? Do I need to pass it to the other Activity? if so, how? Is it better that I put the whole code that handles iAP inside the specific activity?
**EDIT: **
I've tried to catch the exception like this:
AsyncTask.execute(new Runnable() {
#Override
public void run() {
try {Bundle skuDetails = mService.getSkuDetails(3, getPackageName(), "inapp", querySkus); }
catch (RemoteException e) {e.printStackTrace();};
}
});
It won't work becuase I cannot set int response = skuDetails... (in the doc linked above)
Haven't tested your code.. but I think you can try this:
AsyncTask.execute(new Runnable() {
#Override
public void run() {
Bundle skuDetails = null;
try {
skuDetails = mService.getSkuDetails(3,
getPackageName(), "inapp", querySkus);
} catch (RemoteException e) {
e.printStackTrace();
}
int response = skuDetails.whateverYouWantToDoWithThis();
}
});
OR
AsyncTask.execute(new Runnable() {
#Override
public void run() throws RemoteException {
Bundle skuDetails = mService.getSkuDetails(3,
getPackageName(), "inapp", querySkus);
int response = skuDetails.whateverYouWantToDoWithThis();
}
});
Read more about throws vs try-catch here: try/catch versus throws Exception
I'm sure this is pretty simple but I can't figure out and it sucks I'm up on suck on (what should be) an easy step.
ok. I have a method that runs one function that give a response. this method actually handles the uploading of the file so o it takes a second to give a response. I need this response in the following method. sendPicMsg needs to complete and then forward it's response to sendMessage. Please help.
b1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if(!uploadMsgPic.equalsIgnoreCase("")){
Log.v("response","Pic in storage");
sendPicMsg();
sendMessage();
}else{
sendMessage();
}
1st Method
public void sendPicMsg(){
Log.v("response", "sendPicMsg Loaded");
if(!uploadMsgPic.equalsIgnoreCase("")){
final SharedPreferences preferences = this.getActivity().getSharedPreferences("MyPreferences", getActivity().MODE_PRIVATE);
AsyncHttpClient client3 = new AsyncHttpClient();
RequestParams params3 = new RequestParams();
File file = new File(uploadMsgPic);
try {
File f = new File(uploadMsgPic.replace(".", "1."));
f.createNewFile();
//Convert bitmap to byte array
Bitmap bitmap = decodeFile(file,400);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bitmap.compress(CompressFormat.PNG, 0 /*ignored for PNG*/, bos);
byte[] bitmapdata = bos.toByteArray();
//write the bytes in file
FileOutputStream fos = new FileOutputStream(f);
fos.write(bitmapdata);
params3.put("file", f);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
params3.put("email", preferences.getString("loggedin_user", ""));
params3.put("webversion", "1");
client3.post("http://*******.com/apiweb/******upload.php",params3, new AsyncHttpResponseHandler() {
#Override
public void onSuccess(String response) {
Log.v("response", "Upload Complete");
refreshChat();
//responseString = response;
Log.v("response","msgPic has been uploaded"+response);
//parseChatMessages(response);
response=picurl;
uploadMsgPic = "";
if(picurl!=null){
Log.v("response","picurl is set");
}
if(picurl==null){
Log.v("response", "picurl no ready");
};
}
});
sendMessage();
}
}
2nd Method
public void sendMessage(){
final SharedPreferences preferences = this.getActivity().getSharedPreferences("MyPreferences", getActivity().MODE_PRIVATE);
if(preferences.getString("Username", "").length()<=0){
editText1.setText("");
Toast.makeText(this.getActivity(), "Please Login to send messages.", 2);
return;
}
AsyncHttpClient client = new AsyncHttpClient();
RequestParams params = new RequestParams();
if(type.equalsIgnoreCase("3")){
params.put("toid",user);
params.put("action", "sendprivate");
}else{
params.put("room", preferences.getString("selected_room", "Adult Lobby"));
params.put("action", "insert");
}
Log.v("response", "Sending message "+editText1.getText().toString());
params.put("message",editText1.getText().toString() );
params.put("media", picurl);
params.put("email", preferences.getString("loggedin_user", ""));
params.put("webversion", "1");
client.post("http://peekatu.com/apiweb/*********.php",params, new AsyncHttpResponseHandler() {
#Override
public void onSuccess(String response) {
refreshChat();
//responseString = response;
Log.v("response", response);
//parseChatMessages(response);
if(picurl!=null)
Log.v("response", picurl);
}
});
editText1.setText("");
lv.setSelection(adapter.getCount() - 1);
}
From what I understand, you need serial execution of background tasks.
What I do in the case is use a class that extends AsyncTask, takes some sort of listener in its constructor and calls the listener's callback in onPostExecute.
A quick example:
class ExampleTask<T,S,U> extends AsyncTask<T,S,U>
{
public interface ExampleListener
{
public void onTaskCompleted(boolean success);
}
private ExampleListener mListener;
public ExampleTask(ExampleListener listener)
{
mListener = listener;
}
...
#Override
protected void onPostExecute(U result)
{
...
if (mListener != null)
{
mListener.onTaskCompleted(yourBooleanResult);
}
}
}
Just pass a new ExampleListener implementation that calls the second method.
Here's an implementation of the listener:
ExampleListener sendMessageListener = new ExampleListener()
{
public void onTaskCompleted(boolean success)
{
if(success)
sendMessage();
}
}
Don't mix this IO and RPC intensive with your client thread. When your button is clicked, start another thread which handles the communication.
In that thread (potentially a separate class) you send the picture and wait for response; at the same time mark your button to be disabled to avoid clicking again. Then when you receive response, send the message again. Afterwards, raise an event back to the GUI thread, enable the button and display the message.
An easy way to solve this; call your method sendMessage() after the sendPicMsg() in the "onSuccess()" method
I'm trying to develop an app which gets some data from an HTML webpage and displays it every second.
For that i'm using a runnable in this way:
In the OnCreate() method:
mHandler.removeCallbacks(mMuestraMensaje);
mHandler.postDelayed(mMuestraMensaje, 5000);
And then this other method:
private Runnable mMuestraMensaje = new Runnable() {
public void run() {
try {
returned = test.GetSensorData(newString);
rowTextView.setText(returned);
} catch (Exception e) {
e.printStackTrace();
}
mHandler.removeCallbacks(mMuestraMensaje);
mHandler.postDelayed(this, 500);
}
};
The problem is that if i press the back button, for example, the app starts to behave slowly and until i don't force close the whole app the device runs too slow!
Thank you!
EDIT
This is the whole class:
public class HttpExample extends Title {
GetMethodEx test, moredata ;
String returned;
TextView rowTextView, rowTextView2;
LinearLayout ll;
private Handler mHandler = new Handler();
String newString;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.httpexample);
rowTextView = (TextView)findViewById(R.id.textView2);
rowTextView2 = (TextView)findViewById(R.id.textView1);
mHandler.removeCallbacks(mMuestraMensaje);
mHandler.postDelayed(mMuestraMensaje, 5000);
Bundle extras = getIntent().getExtras();
newString = extras.getString("STRING_I_NEED");
test = new GetMethodEx();
moredata = new GetMethodEx();
try {
String name = moredata.GetName(newString);
rowTextView2.setText(name);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ScheduledExecutorService executor =
Executors.newSingleThreadScheduledExecutor();
executor.scheduleAtFixedRate(mMuestraMensaje , 0, 500, TimeUnit.MILLISECONDS );
}
private Runnable mMuestraMensaje = new Runnable() {
public void run() {
try {
returned = test.GetSensorData(newString);
} catch (Exception e) {
e.printStackTrace();
}
MainActivity.this.runOnUiThread(new Runnable(){
rowTextView.setText(returned);
});
}
};
}
Your program slows down because you are running the thread on the GUI thread. That isn't recommended. However, I notice you are setting text after you are done. Here's a few things you could do.
Run the sensor data gathering in a different thread. Update the text by the runOnUiThread command.
Use an AsyncTask, this seems to be an ideal situation for one.
For such a regular occurrence, that doesn't require a UI thread, I would suggest using a ScheduledExecutorService.
The simplest to start with would be the first, but I would look carefully at the second option. The first option would be something like this: (Note, you will need to replace MainActivity with the name of your activity)
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
executor.scheduleAtFixedRate(mMuestraMensaje , 0, 500, TimeUnit.MILLISECONDS );
private Runnable mMuestraMensaje = new Runnable() {
public void run() {
try {
returned = test.GetSensorData(newString);
} catch (Exception e) {
e.printStackTrace();
}
MainActivity.this.runOnUiThread(new Runnable(){
rowTextView.setText(returned);
});
}
};
You can attach you Handler to work on a different thread by using HandlerThread. For example:
HandlerThread ht = new HandlerThread("nonUiThread");
ht.start();
Handler mHandler = new Handler(ht.getLooper());
but more preferably, I would suggest you to use AsyncTask in your case.
Got it to work with this:
private Runnable mMuestraMensaje = new Runnable() {
public void run() {
try {
returned = test.GetSensorData(newString);
} catch (Exception e) {
e.printStackTrace();
}
HttpExample.this.runOnUiThread(new Runnable(){
#Override
public void run() {
// TODO Auto-generated method stub
rowTextView.setText(returned.get(0)+returned.get(1));
rowTextView2.setText(returned.get(2));
}
});
}
};
I have this activity class that won't catch the if block. Because I'm a beginner, I couldn't think of any other way to catch the given userID("001") to launch a specific intent(AdminTab) after the Splash Thread.
Could someone please help me point out what i'm doing wrong or advice me with some sample code? Thank you!
public class Splash extends Activity{
#Override
protected void onCreate(Bundle savedInstanceState) {
final UserFunctions userFunction = new UserFunctions();
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
Thread timer = new Thread(){
public void run(){
String id = "";
id = userFunction.getID(getApplicationContext());
try{
sleep(1000);
//Should open AdminTab if user id is "001"
if("001".equals(id)){
Intent i = new Intent(getApplicationContext(),
AdminTab.class);
startActivity(i);
}else{
Intent i = new Intent(getApplicationContext(),
UserTab.class);
startActivity(i);
}
} catch (InterruptedException e){
e.printStackTrace();
}finally {
}
}
};
timer.start();
}
This is the getID method from UserFunctions Class.
getUserID from a sqlite database handler.
UserFunctions.java
public String getID(Context context) {
String id = "";
DatabaseHandler db = new DatabaseHandler(context);
Cursor cursor = db.getUserID();
if(cursor != null) {
while(cursor.moveToNext()) {
id = cursor.getString(0);
}
} else {
id = "";
}
cursor.close();
db.close();
return id;
}
Your code should work fine, are you getting an error?
maybe change it to id.equals("001")
If this isn't the main activity why don't you just send the id through in the intent if required?
I'm not entirely sure what the problem is.
There is no prob in "001".equals(id).
Please check the id that you are getting from getID(). There is some problem with the id that you are fetching from the database. Try to print the value and cross check.
As I can refresh the content of an activity?, for example, I have a menu and a button send me an application content that displays information online, but to go back and return again, the information is not updated.
This is my Activity.
public class Bovalpo extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bovalpo);
Button buttonExit = (Button)this.findViewById(R.id.cerrar);
buttonExit.setOnClickListener(
new View.OnClickListener() {
public void onClick(View v) {
System.exit(0);
}
}
);
TextView myListView = (TextView) findViewById(R.id.tv);
try {
myListView.setText(getPage());
if(getPage().contains("Abierto")){
myListView.setTextColor(Color.parseColor("#008000"));
}else{
myListView.setTextColor(Color.parseColor("#FF0000"));
}
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private String getPage() throws MalformedURLException, IOException {
HttpURLConnection con = (HttpURLConnection) new URL("http://www.bovalpo.com/cgi-local/xml_bcv.pl?URL=1").openConnection();
con.connect();
if (con.getResponseCode() == HttpURLConnection.HTTP_OK) {
return inputStreamToString(con.getInputStream());
} else {
return null;
}
}
private String inputStreamToString(InputStream in) throws IOException {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(in));
StringBuilder stringBuilder = new StringBuilder();
String line = null;
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append("Mercado: " + line + "\n");
}
bufferedReader.close();
return stringBuilder.toString();
}
public void lanzar(View view){
Intent i = new Intent(this, xml7009.class);
startActivity(i);
}
public void lanzar3(View view){
Intent i = new Intent(this, tabla7009.class);
startActivity(i);
}
public void lanzar4(View view){
Intent i = new Intent(this, xml6503.class);
startActivity(i);
}
public void onClick(View arg0) {
// TODO Auto-generated method stub
finish();
}
}
put your code here
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
// make your work to data bind
}
The code that fetches your data and sets list view color should be put in onResume() instead of onCreate if you want it to run each time your Activity is shown.
Simply you can put your update code in the onResume() method of the activity. OnResume() method will be called when ever you return from the other activity.
But onResume() method is often called when your activity is resume for example. If you open and dismiss the dialog then your activity will be Resume. SO if you are calling some network call in onResume then it will consume the process and Network speed.
The alternate solution is use startActivityForResult() method to receive the result from the next activity and bases of the activity result you can call your web API or any work. You can get the result of the next activity in onActivityResult() method.
But before using the startActivityForResult method ensure that the next activity will set the result by calling setResult() method.
If you want to update your data every time you came to activity, you need to set your updated values in onResume
like below
#Override
protected void onResume() {
super.onResume();
try {
myListView.setText(getPage());
if(getPage().contains("Abierto")){
myListView.setTextColor(Color.parseColor("#008000"));
}else{
myListView.setTextColor(Color.parseColor("#FF0000"));
}
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}