I want to send logout information to server, when the app gets destroyed.
Here's the code:
#Override
protected void onDestroy() {
try {
Log.i("myApp", "Activity destroyed");
SharedPreferences prefs1 = getSharedPreferences("com.my.app", Context.MODE_PRIVATE);
Log.i("myApp", "step1");
String response;
Log.i("myApp", "step2");
response = HttpPOSTer.logout(EventCodes.LOGOUT, LOGOUT_EVENTCODE, prefs.getString("sessionID", "null"));
Log.i("myApp", "step3");
if (response.equals("logout")) {
Log.i("myApp", "logged out succesfully");
} else {
Log.i("myApp", "couldn't perform logout");
}
prefs1.edit().clear().commit();
}
catch (InterruptedException e) {
e.printStackTrace();
}
catch (ExecutionException e) {
e.printStackTrace();
}
super.onDestroy();
}
But here's the log, when I close the app from home button's long click menu:
I can't even debug here. I place breakpoint, but it never gets fired while debugging.
Is there any reason, why AsyncTask doesn't get called from onDestroy()?
its not a good idea to use asyntask in onDestroy() instead you can have an activity that extends IntentService and give a call to that activity from onDestroy
Related
I'm having trouble with AsyncTask running multiple methods in doInBackground. this is my AsyncTask code:
public class FETCHDATA extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
pdialog = new ProgressDialog(getContext());
pdialog.setTitle("Please Wait");
pdialog.setMessage("Fetching data...");
pdialog.show();
}
#Override
protected Void doInBackground(Void... voids) {
try{
method1();
method2();
method3();
method4();
method5();
method6();
method7();
}catch (Throwable e){
e.printStackTrace();
}
}
#Override
protected void onPostExecute(Void aVoid) {
if (pdialog.isShowing()){
pdialog.dismiss();
}
}
Instead running and waiting the first method is done, the doInBackground proceeds to the next method. and the ProgressDialog dismiss by one second.
Note
Every Method will get data from our API and save it on my SQLiteDatabase .
QUESTION
How can i execute my methods when the first method has finished getting and saving data before moving to the second methods.
Maybe you have to create multiples AsyncTask and whenever the first method finish, communicate it with returning a boolean instead of void instance here ---> extends AsyncTask.
This is weird.
I assume that your methodX() are asynchronous call?
In that case, you can use Thread.join() or CountDownLatch.
You are violating usage of async task. Async task is designed for doing short async operations and update the UI easily before, during and after, It is not for doing 7 network & Sqlite operations at once.
You can read more here, : https://developer.android.com/reference/android/os/AsyncTask
So you need to implement some kind of job for yourself to execute these operations at once or use some popular libraries like Retrofit.
If you insist to use async task, since an async task need to be executed from UI thread, you need to create new async task an execute it from onPostExecute every time when it is done and you of course need to pass a param(a counter or something) to doInBackground to know which method should be called.
You can put a counter with a switch case statment in the doInBackground in wich you choose the methode to execute and then in the onPostExecute call new FETCHDATA().execute() recursively
EDIT : working code ( i forgot break; after case;)
int counter = 1; // global
class Fetchdata extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
}
#Override
protected Void doInBackground(Void... voids) {
try {
switch (counter) {
case 1:
method1();
break;
case 2:
method2();
break;
case 3:
method3();
break;
case 4:
method4();
break;
case 5:
method5();
break;
default:
cancel(true);
counter = 1;
break;
}
} catch (Throwable e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
counter+=1;
Log.d(TAG, "onPostExecute: "+counter);
// cancel(true);
new Fetchdata().execute();
}
}
void method1(){
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d(TAG, "methode1: coucou");
}
void method2(){
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d(TAG, "methode2: ");
}
void method3(){
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d(TAG, "methode3: ");
}
void method4(){
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d(TAG, "methode4: ");
}
void method5(){
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d(TAG, "methode5: ");
}
I think the problem is that your all methods or some methods already runs on a separate thread . So whenever you call a method which already runs on separate thread doInBackground() i.e current thread will not wait for it and continue the execution.
Apart from that The way you put try-catch is not a proper way to do it . Also if you want to call several threads one after another you should go with ThreadPoolExecuter.
If you are not using a Network library To make API calls you can use RetroFit.
I used this code it's working when i called from activity and fragment
import com.google.android.gms.ads.identifier.AdvertisingIdClient.Info;
Info adInfo = null;
try {
adInfo = AdvertisingIdClient.getAdvertisingIdInfo(mContext);
} catch (IOException e) {
e.printStackTrace();
} catch (GooglePlayServicesAvailabilityException e) {
e.printStackTrace();
} catch (GooglePlayServicesNotAvailableException e) {
e.printStackTrace();
}
String AdId = adInfo.getId();
But when i called from pending intent like Package Removed then i want to call the web service at that time i need advertising id but i got null.if you people had done previously please suggest me.thanks in advance.
try use app context
as receivers could use activity context or app context - depends who&how started the receiver
AdvertisingIdClient.getAdvertisingIdInfo(context.getApplicationContext());
You can try this code and call the bellow method on onCreate
public void getAAID()
{
AsyncTask.execute(new Runnable() {
#Override
public void run() {
try {
AdvertisingIdClient.Info adInfo = AdvertisingIdClient.getAdvertisingIdInfo(MyActivity.this);
String myId = adInfo != null ? adInfo.getId() : null;
Log.i("UIDMY",myId);
} catch (Exception e) {
Log.e("error", e);
}
}
});
}
Check complete post: how to get AAID programmatically
I have a problem that I am not able to check the value of AsyncTask result in order to start new activity if the result is desirable.
Here is my onPostExecute method:
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
Toast.makeText(LoginActivity.this, s, Toast.LENGTH_SHORT).show();
}
It toasts string value from php file and it has two possible values, "You are successfully logged in" or "Incorrect email or password". Everything is working fine until I want to check what the toasted message is, because if login is successfull I need to start a new activity.
This is how I tried to do that:
public void onClick(View v) {
AttemptLogin login = new AttemptLogin();
try {
String res = login.execute("http://10.0.2.2/loginApp.php").get();
if (res.equals("You are successfully logged in"))
startActivity(new Intent(LoginActivity.this,ConnectActivity.class));
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
I am totally confused because when I toast res, I get the desirable message, so the problem is with this line,if (res.equals("You are successfully logged in")). The app behaves like this line doesn't exist at all.
I also tried with if(AsyncTask.getStatus() == FINISHED) and then to check AsyncTask result but it didn't help.
I really don't have idea what is going on, can anyone please help me with this?
AsyncTask has OnPostExecute and OnPreExecute methods.
Both of them can call items, variables and methods as if they were normal methods.
So in your onPostExecute you can easily check the result and start your activity using this:
#Override
protected void onPostExecute(String s) {
super.onPostExecute();
try {
if (s.equals("You are successfully logged in")){
Intent i = new Intent(LoginActivity.this,ConnectActivity.class);
startActivity(i);
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
Toast.makeText(LoginActivity.this, s, Toast.LENGTH_SHORT).show();
}
I have a fragment that contains a Button btn_connect that when it is pressed a WiFi Direct connection is established between 2 devices. This fragment implements ConnectionInfoListener. So it has onConnectionInfoAvailable function where I want to execute an AsyncTask class. The problem that I have is that in one Activity, I am doing:
fragment.mContentView.findViewById(R.id.btn_connect).performClick();
And the button is being clicked and the connection is established so the code goes into the onConnectionInfoAvailable function but the AsyncTask is not being executed.
#Override
public void onConnectionInfoAvailable(final WifiP2pInfo info) {
//..code..
Log.d("Test 1", "Test 1");
new MasterServerTask().execute();
}
public class MasterServerTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... arg0) {
//**************
Log.d("IM INSIDE ASYNCTASK CLASS", "SOCKET");
try {
serverSocket = new ServerSocket(8090);
} catch (IOException e) {
e.printStackTrace();
}
while (true) {//wait for clients
Socket socket = null;
try {
socket = serverSocket.accept();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.d("ACCEPTED A SLAVE DEVICE "+num_clients, "ACCEPTED A SLAVE DEVICE "+num_clients);
num_clients++;
OutputStream os=null;
try {
os = socket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
proxy.addSlaveOutputStream(os);
}
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
}
}
mContentView.findViewById(R.id.btn_connect).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {//Phone that connects first is NOT the group owner
// port = Integer.parseInt(editTextPort.getText().toString());
Log.d("IM IN THE OTHER FRAGMENT", "Connect");
WifiP2pConfig config = new WifiP2pConfig();
config.groupOwnerIntent = 0;
config.deviceAddress = device.deviceAddress;
config.wps.setup = WpsInfo.PBC;
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
}
progressDialog = ProgressDialog.show(getActivity(), "Press back to cancel",
"Connecting to :" + device.deviceAddress, true, true
);
((DeviceActionListener) getActivity()).connect(config);
}
});
Is there an easy workaround solution for this?
Check how/where you are calling WifiP2pManager.initialize() to create the WifiP2pManager.Channel object. The Looper you provide it is the one which will receive all callbacks for your instance of WifiP2pManager.ConnectionInfoListener. If you are giving it a background thread then the AsyncTask will not execute - it must be started from the main (UI) thread.
The comments on the question were really helpful. The reason why the AsyncTask was not getting executed is because it was called from another task that is currently being executed. So in order for it to work, I replaced the AsyncTask with Thread classes. All the code in the doInBackground() was placed inside the thread's run() function. Now the performClick() executes a Thread, not an AsyncTask and it worked.
i built up an application based on aSmack, and obviously every thing about connection is running in a service, so it is very important to keep its connection Alive, as we know services running in background, may get killed upon phone's low sources (usually Ram) , so with the START_STICKY flag on the service, it restarts itself with a null intent.
now i wonder if there be no network on the phone ,or suddenly an unexpected temporary exception happenes in that time, (and because service is restarted reconnectionManager hasnt been set up yet), so the app must get restarted to retrieve its connection. my question is how can i handle these exceptions ? i know i can do some thing like this:
public void connect(){
try {
connection.connect();
} catch (SmackException | IOException | XMPPException e) {
if(getIntent() == null){
connect();
return;
}
}
}
but this is unprofessional imo, i know there was a way to determine temporary exceptions but unfortunanly i cant either remember or find them. any information is appreciated. thanks alot
so here is what i have done, works perfectly and every thing is counted in that.
this is awhat my service does every time it starts
private void connect(){
if (!connection.isConnected()){
try {
connection.connect();
} catch (SmackException | IOException | XMPPException e) {
mainHandler.post(new Runnable() {
#Override
public void run() {
if(intent ==null){
Toast.makeText(getBaseContext(),"Could not Connect to The Server , Network Problems , Retrying in 30 Seconds...", Toast.LENGTH_LONG).show();
}else{
Toast.makeText(getBaseContext(),"Could not Connect to The Server , Network Problems...", Toast.LENGTH_LONG).show();
}
}
});
if(intent == null){
//When intent is null, It Means that service got Destroyed middle of app, which
//means user has already connected and Authenticated once, but can not do it again.
//so thats the key
nonMainHandler.postDelayed(new Runnable() {
#Override
public void run() {
connect();
}
},30000);
}
e.printStackTrace();
}
}
try {
if (connection.isConnected() && !connection.isAuthenticated()) {
try {
connection.login(LMApplication.userName,LMApplication.passWord);
} catch (SmackException | IOException | XMPPException e) {
mainHandler.post(new Runnable() {
#Override
public void run() {
if(intent != null){
Toast.makeText(getBaseContext(),"Could not Login Using this Information..", Toast.LENGTH_LONG).show();
}
}
});
e.printStackTrace();
configEnterButton(-1);
}
}
if(connection.isAuthenticated()){
configEnterButton(100);
try {
Thread.sleep(300);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
goAhead();
Log.i("XMPPChatDemoActivity", "Logged in as" + LMApplication.Raw_CurrentUser);
//TODO
// check if need to set presence from shared preferences
Presence p = new Presence(Presence.Type.available,"", 42, Mode.available);
try {
connection.sendPacket(p);
} catch (NotConnectedException e1) {
e1.printStackTrace();
}
}else if(intent == null){
nonMainHandler.post(new Runnable() {
#Override
public void run() {
if(connection.isConnected() && !connection.isAuthenticated()){
try {
connection.login(LMApplication.userName,LMApplication.passWord);
} catch (XMPPException | SmackException
| IOException e) {
e.printStackTrace();
}
}
if(connection.isConnected() && connection.isAuthenticated()){
notifyReconnect();
}else if(connection.isConnected()){
nonMainHandler.postDelayed(this,10000);
}
}});
}
my question is how can i handle these exceptions ?
By performing a reconnect. Most applications I know do schedule the reconnect after a few seconds.