0

I have written an Android app which send the GPS data periodically to a web server. I have used locationmanager and httpget classes of Android.

Its working fine. But the issue is the app is mysteriously closing without any error message not invoking activity closing method. I even set my activity screen always on, so that the screen never goes out after time out. Also I have added some vibration functionality in onClose or onDestroy methods by overriding them, so that when the app get closed, I can write the error log to a file.

But still nothing happened. Those methods are not at all invoking and the app gets mysteriously closed.

The app runs perfectly for sometime. I test it by turning on GPS and 3G and walk in street for sometime. But when I reach home, I found the app is already closed.

Please help he if I am missing some handling or is it memory overflow?

Here is my source code

MainActivity.java

package com.test.partha1.gps1;

import android.app.*;
import android.content.*;
import android.location.*;
import android.os.*;
import android.view.*;
import android.widget.*;

import android.net.ConnectivityManager;
import android.net.NetworkInfo;

import org.apache.http.HttpResponse;
import org.apache.http.client.*;
import org.apache.http.client.methods.*;
import org.apache.http.impl.client.DefaultHttpClient;

import java.io.*;
import java.net.*;
import java.util.*;

public class MainActivity extends Activity implements LocationListener {
Button urlBtn;
ToggleButton toggleBtn;
TextView txt1;
TextView urlServer;

long prevTime = -1;
double prevLatitude;
double prevLongitude;

boolean isGPSEnabled = false;
int count = 0;
protected LocationManager locationManager;
RandomAccessFile outFile;

String TimeStamp = "";

String UserID = "4084";

String server = "http://www.parthasarathimishra.com";

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

File externalStorageDir = Environment.getExternalStorageDirectory();
File myFile = new File(externalStorageDir, "ErrLogFile.txt");

txt1 = (TextView) findViewById(R.id.gpsVal);
urlServer = (TextView) findViewById(R.id.urlTxt);
urlBtn = (Button) findViewById(R.id.urlBtn);
urlBtn.setOnClickListener(urlBtnClick);
toggleBtn = (ToggleButton) findViewById(R.id.toggleButton);

try
{
    if(!myFile.exists())
    {
        myFile.createNewFile();
    }

    outFile = new RandomAccessFile(myFile, "rw");
    outFile.seek(myFile.length());
}
catch(Exception e)
{
    txt1.setText(e.getMessage());
}

locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
}

@Override
public void onStop () {

try
{
    outFile.close();
}
catch(Exception e)
{
}

super.onStop();
}

@Override
protected void onDestroy()
{
Vibrator v = (Vibrator)this.getSystemService(Context.VIBRATOR_SERVICE);
v.vibrate(2000);

super.onDestroy();
 }


@Override
public void onLocationChanged(Location location) {

if(!urlBtn.isEnabled() && ((prevTime == -1) || (System.currentTimeMillis() - prevTime >= 10000)))
 {
    try
    {
        UpdateTimeStamp();
        connectWithHttpGet(String.valueOf(location.getLatitude()), String.valueOf(location.getLongitude()), TimeStamp);

        prevTime = System.currentTimeMillis();
        prevLatitude = location.getLatitude();
        prevLongitude = location.getLongitude();

        txt1.setText(String.valueOf(prevLatitude) + "/" + String.valueOf(prevLongitude));
    }
    catch(Exception e)
    {
        txt1.setText(e.getMessage());

        try
        {
            outFile.writeBytes("\r\n" + e.getMessage());
        }
        catch (Exception e2)
        {
            txt1.setText(e2.getMessage());
        }
    }
}
else
{
    txt1.setText("");
}
}

@Override
public void onStatusChanged(String provider, int status, Bundle extras) {

}

@Override
public void onProviderEnabled(String provider) {

txt1.setText("GPS ON");
isGPSEnabled = true;
}

@Override
public void onProviderDisabled(String provider) {

txt1.setText("GPS OFF");
isGPSEnabled = false;
}

private boolean isNetworkAvailable()
{
ConnectivityManager connectivityManager
        = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}

private void UpdateTimeStamp()
{
Date date = new Date();
date.setTime(System.currentTimeMillis());
String cTime = date.toString();

Calendar cal = Calendar.getInstance();
String day   = cTime.split(" ")[2];
String month = String.valueOf(cal.MONTH);
String year  = cTime.split(" ")[cTime.split(" ").length - 1];

String hr  = cTime.split(" ")[3].split(":")[0];
String min = cTime.split(" ")[3].split(":")[1];
String sec = cTime.split(" ")[3].split(":")[2];

TimeStamp = day + "," + month + "," + year + "," + hr + "," + min + "," + sec;
}

private View.OnClickListener urlBtnClick = new View.OnClickListener() {
   @Override
   public void onClick(View v) {
   server = urlServer.toString();
}
};

  public void toggleBtnChange(View view)
{
boolean on = ((ToggleButton)view).isChecked();

if(on)
{
    if(isNetworkAvailable())
    {
        urlBtn.setEnabled(false);
        urlServer.setEnabled(false);
            locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
    }
    else
    {
        txt1.setText("No Network!! Enable the Network Connectivity.");
    }
}
else
{
    urlBtn.setEnabled(true);
    urlServer.setEnabled(true);
    locationManager.removeUpdates(this);
}

}
private void connectWithHttpGet(final String pLatitude, final String pLongitude, final String timeStamp) {

class HttpGetAsyncTask extends AsyncTask<String, Void, String>{
    String url = "";
    String Lat = pLatitude;
    String Lng = pLongitude;
    String tStamp = timeStamp;

    @Override
    protected String doInBackground(String... params) {
        url = server + "/" + UserID + "/add.php?lat=" +
                Lat + "&long=" + Lng + "&time=" + tStamp;
        try
        {
            HttpClient httpClient = new DefaultHttpClient();
            HttpGet httpGet = new HttpGet(url);
            HttpResponse httpResponse = httpClient.execute(httpGet);
            int status = httpResponse.getStatusLine().getStatusCode();

            if(status != 200)
            {
                txt1.setText("Unable to Send");
            }
        }
        catch(Exception e)
        {
            txt1.setText(e.getMessage());

            try
            {
                outFile.writeBytes("\r\n" + e.getMessage());
            }
            catch (Exception e2)
            {
                txt1.setText(e2.getMessage());
            }
        }
        return "";
    }

    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);
    }
}
// Initialize the AsyncTask class
HttpGetAsyncTask httpGetAsyncTask = new HttpGetAsyncTask();
// Parameter we pass in the execute() method is relate to the first generic type of the AsyncTask
// We are passing the connectWithHttpGet() method arguments to that
httpGetAsyncTask.execute(pLatitude, pLongitude);
}

@Override
protected void onResume(){
super.onResume();
}
}

activity_main.xml

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:paddingLeft="@dimen/activity_horizontal_margin"
  android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".MainActivity"
android:background="#ff3f3dad"
android:id="@+id/lay"
android:keepScreenOn="true">

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Update URL"
android:id="@+id/urlBtn"
android:textColor="#ff000000"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true" />

<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/gpsVal"
android:textColor="#ffffffff"
android:textSize="10dp"
android:background="#ff000000"
android:layout_alignParentBottom="true"
android:layout_marginBottom="50dp"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true" />

<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/urlTxt"
android:text="www.parthasarathimishra.com"
android:textColor="#fffff500"
android:editable="true"
android:background="#ff000000"
android:layout_below="@+id/urlBtn"
android:layout_alignParentLeft="true"
android:layout_marginTop="41dp"
android:layout_alignParentRight="true" />

<ToggleButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ON"
android:id="@+id/toggleButton"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="45dp"
android:onClick="toggleBtnChange" />

 </RelativeLayout>

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.test.partha1.gps1" >

 <application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
    android:name=".MainActivity"
    android:label="@string/app_name" >
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

</application>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</manifest>

I am using Android Studio for these. I am using target version 2.3.3 (API 10), since I don't have higher Android version in my phone.

Please let me know, if any thing I have missed. Its mysteriously crashing without any notice after few HttpGet sends.

  • Put you device in debug mode and check the logcat if you see any exception. Have you done that? – Blacklight Mar 13 '15 at 12:57
  • Does your app have an activity that's visible on the screen, and despite that it's being closed? Or is it only running in the background (in which case you would need a foreground service to have a decent chance of not getting killed by the system). – JHH Mar 13 '15 at 13:00
  • @Blacklight No. I haven't done it. Actually its hard to put it in debug mode and test. GPS signal u can get only outside the room, So connecting to PC and test is tough. – Partha Sarathi Mishra Mar 13 '15 at 13:00
  • @JHH No. I have only one activity, and its not running in background. I have no services. – Partha Sarathi Mishra Mar 13 '15 at 13:02
  • @Partha You will need to do that. Of course you can catch exceptions at every possible place, show a toast etc., but I guess you don't even know where to look. You can also use the emulator, try to simulate location and read the exception from the logcat etc. http://stackoverflow.com/questions/2279647/how-to-emulate-gps-location-in-the-android-emulator – Blacklight Mar 13 '15 at 13:05
  • @Blacklight OK. I will try. But is it true that every app closing doesn't invoke onDestroy(), onResume() or onClose() methods? – Partha Sarathi Mishra Mar 13 '15 at 13:07
  • @Partha Those are regular `Activity`/`Fragment` lifecycle methods. So yes, if your app crashes unexpectedly then those methods are usually not called, because crashing is not part of the regular UI element lifecyle. – Blacklight Mar 13 '15 at 13:09
  • If, by "app" you actually mean "activity", its onDestroy method is not called if the application crashes, is killed by the system for low memory reasons etc. The latter would be very rare if your activity is in the foreground though. It sounds like some kind of silent crash, but without a logcat - and preferably some source code - it's basically impossible to say. – JHH Mar 13 '15 at 13:09
  • @JHH Ok. Soon I will send the source code. – Partha Sarathi Mishra Mar 13 '15 at 13:14
  • @JHH I have sent the source code in my answer section. Please go through. – Partha Sarathi Mishra Mar 26 '15 at 09:16
  • @Blacklight I have sent the source code in my answer section. Please go through. – Partha Sarathi Mishra Mar 26 '15 at 09:17
  • 1
    @Partha This is not how it works. First: edit your question, don't add additional info as an answer. Second: as we told you: you need to post the logcat, i.e. exceptions that are thrown when your app crashes. You most likely won't get any help this way, show some effort. – Blacklight Mar 26 '15 at 09:20
  • @Blacklight I have edited my question, and deleted the code in the answer part. Now please kindly go through it and let me know if I have done something inappropriate. I have tested this code many times while traveling, but many times it closes automatically. Debugging is very tough as it need GPS simulation and in PC it may not happen as it may get enough memory unlike in the real phone. First inspect the code when you have time. I have given everything from my project. – Partha Sarathi Mishra Mar 26 '15 at 09:57

1 Answers1

0

I do not think this has anything to do with a specific development environment and its relative coding. I think this is purely an Android issue. I developed 2 test applications, one with a location sensor control and one using the Android API. Both gather the GPS information and both crash after a few readings. You never see this issue in iOS (however, where iOS succeeds in some areas, it fails miserably in other areas).

In my opinion both Android and iOS are still infants and are experiencing major maturing problems and that makes it difficult to trust coding any exotic features into applications.

t j
  • 413
  • 1
  • 7
  • 12