Suitable Performance wise Android Background processing method - java

Code Summary:
MainActivity is starting the NearbyPlacesMainActivity using an intent.
In the NearbyPlacesMainActivity, I nested AsyncTask class that gets all the nearby places’ bearings and names and get it stored in an ArrayList and display it.
My Goal: My only goal is to pass the nearby places’ names and bearings ArrayList to MainActivity not to update the UI.
Question:
As I just want the nearby places’ names and bearings to get stored in ArrayList and then pass it to MainActivity for later use, not to display it right now, so is it a professional approach and suitable performance wise? If not what will be the good approach in this scenario?
NearbyPlacesMainActivity
package com.example.atifarain.customizedcamera;
public class NearbyPlacesMainActivity extends ActionBarActivity {
AlertDialogManager alert = new AlertDialogManager();
GooglePlaces googlePlaces;
PlacesList nearPlaces;
// KEY Strings
public static String KEY_REFERENCE = "reference"; // id of the place
public static String KEY_NAME = "name"; // name of the place
ArrayList<HashMap<String, String>> placesListItems = new ArrayList<HashMap<String,String>>();
ArrayList<String> nearbyData = new ArrayList<String>();
public static double lat1 ;
public static double lon1 ;
MainActivity mainActivityObj;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_nearby_places_main);
bearingView = (TextView) findViewById(R.id.textView3);
Bundle extras = getIntent().getExtras();
Location location = (Location)extras.get("key1");
lat1 = location.getLatitude();
lon1 = location.getLongitude();
new LoadPlaces().execute();
}
class LoadPlaces extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
protected String doInBackground(String... args) {
// creating Places class object
googlePlaces = new GooglePlaces();
try {
String types = "cafe|restaurant|atm";
double radius = 2000; // 1000 meters
nearPlaces = googlePlaces.search(lat1, lon1, radius, types);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(String file_url) {
runOnUiThread(new Runnable() {
public void run() {
// Get json response status
String status = nearPlaces.status;
// Check for all possible status
if(status.equals("OK")){
// Successfully got places details
if (nearPlaces.results != null) {
// loop through each place
ArrayList<String> coordinates = new ArrayList<String>();
ArrayList<Double> bearings = new ArrayList<Double>();
for (Place p : nearPlaces.results) {
HashMap<String, String> map = new HashMap<String, String>();
// Place reference is used to get "place full details"
map.put(KEY_REFERENCE, p.reference);
map.put(KEY_NAME, p.name); // Place name
double lat2 = p.geometry.location.lat;
double lon2 = p.geometry.location.lng;
double _bearing = bearing(lat1, lon1, lat2, lon2);
bearings.add(_bearing);
String lat = Double.toString(lat2);
String lon = Double.toString(lon2);
String latlon = lat + " , " + lon;
coordinates.add(latlon);
String nearbyDat = Double.toString(_bearing)+" , "+p.name;
nearbyData.add(nearbyDat);
placesListItems.add(map); // adding HashMap to ArrayList
}
bearingView.setText("");
for (int k = 0; k < bearings.size(); k++){
bearingView.append(k+1 + ": " + nearbyData.get(k) + "\n");
}
}
}
else if(status.equals("ZERO_RESULTS")){
alert.showAlertDialog(NearbyPlacesMainActivity.this, "Near Places",
"Sorry no places found. Try to change the types of places", false);
}
else if(status.equals("UNKNOWN_ERROR")){
alert.showAlertDialog(NearbyPlacesMainActivity.this, "Places Error",
"Sorry unknown error occured.", false);
}
else if(status.equals("OVER_QUERY_LIMIT")){
alert.showAlertDialog(NearbyPlacesMainActivity.this, "Places Error",
"Sorry query limit to google places is reached", false);
}
else if(status.equals("REQUEST_DENIED")){
alert.showAlertDialog(NearbyPlacesMainActivity.this, "Places Error",
"Sorry error occured. Request is denied", false);
}
else if(status.equals("INVALID_REQUEST")){
alert.showAlertDialog(NearbyPlacesMainActivity.this, "Places Error",
"Sorry error occured. Invalid Request", false);
}
else{
alert.showAlertDialog(NearbyPlacesMainActivity.this, "Places Error", "Sorry error occured.", false);
}
}
});
}
protected double bearing(double lat1, double lon1, double lat2, double lon2) {
double Longitude_Difference = Math.toRadians(lon2 - lon1);
double latitude_1 = Math.toRadians(lat1);
double Latitude_2 = Math.toRadians(lat2);
double y = Math.sin(Longitude_Difference) * Math.cos(Latitude_2);
double x = Math.cos(latitude_1) * Math.sin(Latitude_2) - Math.sin(latitude_1) * Math.cos(Latitude_2) * Math.cos(Longitude_Difference);
double result = Math.toDegrees(Math.atan2(y, x));
return (result+360.0d)%360.0d;
}
}
}
PS. I am very new to android, though I went through all the Handler, Thread and AsyncTask stuff but didn’t get much in practical so I don’t know much about the performance things in android that which are more suitable so please bear with me and if anyone finds it off topic or too broad then before negative voting please do let me know in comments, so I could improve it. Thanks :)

Consider using EventBus library which allows you easily communicate between different parts of Android application and prevents from producing related boilerplate code.

There are few things I want to point out.
Creating an AsyncTask as an inner class of your activity could potentially cause a leak since inner classes have an implicit reference to outer one and your background thread may outlive the activity. For example if the screen is rotated while the task is executing, your activity will be destroyed/recreated, you should be handling that case.
onPostExecute already runs on UI thread as per documentation so you do not need to explicitly call runOnUiThread
There are lot of ways of communicating back to the activity if you move your async task out. I normally create an interface and have my activity implement that interface. Then pass the reference to your activity to the AsyncTask but hold on to that reference Weakly so you don't leak if your activity dies before the AsyncTask completes. And then invoke the call back from your interface in onPostExecute()

Related

How to draw the current location information in osmdroid

Assumption and what I want to achieve
 I'm working on an application that receives current location information from an external RTK-GPS via serial communication, and draws dots or lines on an osmdroid map.
 I have already realized receiving the location information and converting the received data to a type that can be displayed on TextView.
For serial communication, I am using FTDI's "usb-serial-for-android" library, and for map functions, I am using "osmdroid".
Currently
Receive location data from RTK-GPS via serial communication.
Get the latitude and longitude in double type from the received data (String type).
Create a GeoPoint from the acquired latitude and longitude, set it to a marker, and draw it on the map. At this time, the GeoPoint is also stored in the GeoPoint list.
The following procedure is used to display the marker of the current location on the map. Currently, the received latitude and longitude are set to the marker and all the markers are drawn.
Eventually, I'd like to draw the trajectory of movement as a line while updating the current location marker.
Problems and error messages
The problem we are experiencing is that when we start drawing, the application immediately becomes sluggish and freezes.
Since 10 data are sent from GPS per second, if we try to draw all the received data on the map, the number of markers will be huge and the app will freeze.
Therefore, we tried to draw markers in 10 marker skips, but even so, the application became sluggish and froze as soon as it started drawing.
Next, when the number of data exceeded 100, I deleted the oldest data first, and the application did not freeze after starting drawing. However, I don't think it is possible to draw all the loci with this method. If possible, I would like to draw all the loci that have been moved.
My questions are as follows.
Is it possible to draw the movement locus using the above method and policy?
Is it impossible to draw such a moving locus in Android?
Does OSMDROID have a function to draw the movement locus?
Are there any similar questions?
Please let me know.
Here is my code.
public class MapGeneratorMainActivity extends Activity {
private static final double MAP_ZOOM = 15.0;
private static final double MAP_ZOOM2 = 17.0;
static MapView mapGeneratorMainMap = null;
public static List<Marker> currentMarkers = new ArrayList<>();
ArrayList<GeoPoint> currentPoints = new ArrayList<>();
ArrayList<GeoPoint> currentPoints2hz = new ArrayList<>();
ArrayList<Polyline> currentTrajectory = new ArrayList<>();
public static int receiveCount = 0;
public static GeoPoint currentP2hz;
public MapGeneratorMainActivity() {
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
org.osmdroid.config.Configuration.getInstance().load(getApplicationContext(),
PreferenceManager.getDefaultSharedPreferences(getApplicationContext()));
setContentView(R.layout.map_generator_main_activity);
MapView mapGeneratorMainMap = findViewById(R.id.MapGaneratorMainMap);
mapGeneratorMainMap.setMultiTouchControls(true);
IMapController mapController = mapGeneratorMainMap.getController();
mapController.setZoom(MAP_ZOOM);
GeoPoint centerPoint = new GeoPoint(aveLat, aveLon);
mapController.setCenter(centerPoint);
mapGeneratorMainMap.setTilesScaledToDpi(true);
final MapTileProviderBasic tileProvider = new MapTileProviderBasic(getApplicationContext());
ITileSource tileSource = new XYTileSource("GSI", 14, 24, 256, ".jpg", new String[]{TILE_SEVER});
tileProvider.setTileSource(tileSource);
final TilesOverlay tilesOverlay = new TilesOverlay(tileProvider, this.getApplicationContext());
tilesOverlay.setLoadingBackgroundColor(Color.TRANSPARENT);
mapGeneratorMainMap.getOverlays().add(tilesOverlay);
mapGeneratorMainMap.invalidate();
FloatingActionButton myLocationButton = findViewById(R.id.myLocationButton);
myLocationButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intentService = new Intent(getApplication(), gpsService.class); //位置情報受信サービス
intentService.putExtra("REQUEST_CODE", 1);
startForegroundService(intentService);
}
});
//Receiver
UpdateReceiver receiver = new UpdateReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("DO_ACTION");
registerReceiver(receiver, filter);
}
protected class UpdateReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
String currentLat = null;
String currentLon = null;
MapView mapGeneratorMainMap = findViewById(R.id.MapGaneratorMainMap);
mapGeneratorMainMap.setMultiTouchControls(true);
IMapController mapController = mapGeneratorMainMap.getController();
mapController.setZoom(MAP_ZOOM2);
Bundle extras = intent.getExtras();
String msg = extras.getString("message"); //String型の位置情報
TextView currentLocatonTextView = findViewById(R.id.CurrentLocation);
currentLocatonTextView.setText(msg);
String[] currentLocaton = msg.split(",", -1);
currentLat = currentLocaton[0];
currentLon = currentLocaton[1];
double Lat = Double.parseDouble(currentLat);
double Lon = Double.parseDouble(currentLon);
GeoPoint currentP = new GeoPoint(Lat, Lon);
if(receiveCount == 0){
currentP2hz = new GeoPoint(Lat, Lon);
currentPoints.add(currentP);
currentPoints2hz.add(currentP2hz);
currentPtMarker = new Marker(mapGeneratorMainMap);
Drawable currentMarkerIcon = ResourcesCompat.getDrawable(getResources(), R.drawable.current_point_marker, null);
currentPtMarker.setIcon(currentMarkerIcon);
currentPtMarker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_CENTER);
currentPtMarker.setPosition(currentP);
currentMarkers.add(currentPtMarker);
mapGeneratorMainMap.getOverlayManager().add(currentPtMarker);
mapGeneratorMainMap.invalidate();
}
else if(receiveCount == 100) {
currentPoints.add(currentP);
currentP2hz = new GeoPoint(Lat, Lon);
currentPoints2hz.add(currentP2hz);
receiveCount = 0;
currentPtMarker = new Marker(mapGeneratorMainMap);
Drawable currentMarkerIcon = ResourcesCompat.getDrawable(getResources(), R.drawable.current_point_marker, null);
currentPtMarker.setIcon(currentMarkerIcon);
currentPtMarker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_CENTER);
currentPtMarker.setPosition(currentP);
currentMarkers.add(currentPtMarker);
mapGeneratorMainMap.getOverlayManager().add(currentPtMarker);
mapGeneratorMainMap.invalidate();
}
if(currentMarkers.size() >= 100){
currentMarkers.get(0).remove(mapGeneratorMainMap);
currentMarkers.remove(0);
}
receiveCount += 1;
}
}
Good morning everyone.
I was able to solve this problem.
The reason why it didn't work was that some of the data received by serial communication was not good.
After eliminating this bad data and receiving only the good data, I was able to do what I wanted.
thanks so much.

How to call a function while a indeterminate material dialog is in progress?

Right now i am using Material Dialog in my application like this:
dialog = new MaterialDialog.Builder(MainActivity.this)
.title("Please Wait")
.content("Loading")
.progress(true, 0)
.titleColor(getResources().getColor(R.color.grey))
.widgetColor(getResources().getColor(R.color.grey))
.progressIndeterminateStyle(true)
.show();
I want to call the function in the background while progress bar is running
like for example address() is the function name now where should i call this function ?
I have tried using determinate progress dialog box but it didn't worked as i thought
while (dialog.getCurrentProgress() != dialog.getMaxProgress()) {
// If the progress dialog is cancelled (the user closes it before it's done), break the loop
if (dialog.isCancelled()) break;
// Wait 50 milliseconds to simulate doing work that requires progress
try {
Thread.sleep(50);
} catch (InterruptedException e) {
break;
}
// Increment the dialog's progress by 1 after sleeping for 50ms
dialog.incrementProgress(1);}
This is what i am calling in a function but it returns a null value for the first time because it takes time to mobile GPS to send lat lng. I want that this function should be done in background while progress dialog is being shown till this function returns a non null value.
private void Address() {
gps.getLocation();
if (gps.canGetLocation == false) {
// Here you can ask the user to try again, using return; for that
Toast.makeText(MainActivity.this, "Check your internet connection", Toast.LENGTH_SHORT).show();
//return;
} else {
// Getting location co-ordinates
double latitude = gps.getLatitude();
double longitude = gps.getLongitude();
// Toast.makeText(this, "Latitude:" + latitude + " | Longitude: " + longitude, Toast.LENGTH_LONG).show();
address = gps.getLocationAddress();
street = gps.getLocationArea();
String[] compare = {"Jawahar Nagar", "Tilak Nagar", "Sector 4", "Adarsh Nagar", "Gurunanakpura",
"Raja Park", "Janta Colony", "Jhalana Doongri", "Sector 5", "Sector 1", "Sector 2", "Sector 3", "Sector 6", "Sector 7"};
if (Arrays.asList(compare).contains(street) && address.equals("null")) {
int zip = Integer.parseInt("302004");
address = String.valueOf(zip);
}
}}
You can build the Dialog and use the reference for showing and dismissing. You also have to set cancelable as false.
e.g. like this
dialog = new MaterialDialog.Builder(MainActivity.this)
.title("Please Wait")
.content("Loading")
.progress(true, 0)
.titleColor(getResources().getColor(R.color.grey))
.widgetColor(getResources().getColor(R.color.grey))
.progressIndeterminateStyle(true)
.cancelable(false)
.build();
Your method address() could look like this
dialog.show();
// do logic
dialog.dismiss();
You need AsyncTask to do background process in android. Example :
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
MaterialDialog dialog;
protected void onPreExecute () {
dialog = new MaterialDialog.Builder(MainActivity.this)
.title("Please Wait")
.content("Loading")
.progress(true, 0)
.titleColor(getResources().getColor(R.color.grey))
.widgetColor(getResources().getColor(R.color.grey))
.progressIndeterminateStyle(true)
.show();
}
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
protected void onPostExecute(Long result) {
dialog.dismiss();
}
}
Then in your method to call your dialog :
new DownloadFilesTask().execute(url1, url2, url3);
Your background process goes to doInBackground method.
You can use the AsyncTask like this
private class LongOperation extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
//Call the address() method
return "";
}
#Override
protected void onPostExecute(String result) {
//Stop showing your progress bar
}
#Override
protected void onPreExecute() {
//Start showing your progress bar
}
}

AsyncTask inside of onPostExecute of another Asynctask and return the result

In my first AsyncTask doInBackground method I run a method that get a list of places from Google Place Api. Inside the postExecute of this first AsyncTask, I get all the names of these places and show them all in a ListView.
I now would like to show the driving distance of a single place from my current location (I can already get it). To do so, I created, in another class, another AsyncTask to get this distance. Here is the code:
public class Distance extends AsyncTask<Double, Double, String> {
GooglePlaces googlePlaces;
String distancePlace = null;
#Override
final protected String doInBackground(Double... params) {
double lat1,lat2,lon1,lon2;
lat1=params[0];
lon1=params[1];
lat2=params[2];
lon2=params[3];
googlePlaces = new GooglePlaces();
distancePlace= googlePlaces.getDistance(lat1,lon1,lat2,lon2);
return distancePlace;
}
}
and this is the code of my first AsyncTask postExecute:
protected void onPostExecute(String s) {
runOnUiThread(new Runnable() {
#Override
public void run() {
//get json status
String status = nearPlaces.status;
if (status.equals("OK")){
if (nearPlaces.results != null){
//every single place
for (Place p : nearPlaces.results){
//just a try, here I would like to get the distance
/*
Double[] myparams = {gps.getLatitude(),gps.getLongitude(),
p.geometry.location.lat,p.geometry.location.lng};
new Distance().execute(myparams);*/
HashMap<String,String> map = new HashMap<String, String>();
map.put(KEY_NAME,p.name);
//add hashmap
placesListItems.add(map);
}
ListAdapter adapter = new SimpleAdapter(GpsActivity.this, placesListItems, R.layout.list_item, new String[] {KEY_REFERENCE,KEY_NAME},
new int[] {R.id.reference, R.id.name});
//add into listview
lv.setAdapter(adapter);
}
My problem is how to execute the "distance AsyncTask" inside my postExecute and return its result into my first AsyncTask, to show it in my ListView.
You can do something like this:
Distance distance = new Distance(){
protected void onPostExecute(final String result1) {
// First AsyncTask result.
Distance distance2 = new Distance(){
protected void onPostExecute(String result2) {
// process the second result.
// Because the first result "result1" is "final",
// it can be accessed inside this method.
}
};
distance2.execute(...);
}
};
distance.execute(...);
Also, you don't need to use runOnUiThread(...) because the onPostExecute(...) method is executed on the UI thread.

Parse Swift syntax to Android

I had trouble trying to retrieve user based on search distance, and have received great support from this community. The code boiled down to the following:
let userLocation = PFGeoPoint(latitude: userLatitude, longitude: userLongitude)
query.whereKey("location", nearGeoPoint:userLocation, withinKilometers: 100)
The issue is that the code is tailored to swift/xcode, and when I tried "converting it to" android it came down to
query.whereWithinKilometers("location", ParseGeoPoint point, 100);
I am not sure if this is the proper way of writing it in Java (android), and not sure what to do ParseGeoPoint point.
I have looked into https://parse.com/docs/android/api/com/parse/ParseGeoPoint.html, but is a bit stuck.
If you need any clarification, let me know.
Thanks
Update:
Below is how I store the location point of the current user into Parse
#Override
public void onLocationChanged(Location loc) {
// TODO Auto-generated method stub
double lati = loc.getLatitude();
double longi = loc.getLongitude();
ParseUser currentUser = ParseUser.getCurrentUser();
currentUser.saveInBackground();
ParseGeoPoint point = new ParseGeoPoint(lati, longi);
currentUser.put("location", point);
currentUser.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
setProgressBarIndeterminateVisibility(false);
if (e == null) {
// Success!
} else {
}
}
});
Below is how I attempt to retrieve it, and see if user who fall within range
ParseQuery<ParseUser> query = ParseUser.getQuery();
ParseGeoPoint point = new ParseGeoPoint(47, -122); //Ideally it would be best if (47, -122) reflected the current user location
query.whereWithinKilometers("location", point, 100);
I'd recommend reading through this for documentation on the Android SDK's GeoPoints. This would be the basic syntax for you.
#Override
public void onLocationChanged(Location loc) {
double lati = loc.getLatitude();
double longi = loc.getLongitude();
//User's current location
ParseGeoPoint point = new ParseGeoPoint(lati, longi);
ParseQuery<ParseObject> query = ParseQuery.getQuery("Locations");
query.whereWithinKilometers("location", point, 100);
query.findInBackground(new FindCallback<ParseObject>() { ... });
}

Why doesn't my call to the Facebook Graph API display anything?

Ok, so I'm editing this to include the whole class with some new code I added over the past couple of hours. Basically, I'm looking to populate a Google Map with markers that represent a Facebook user's checkins. Unfortunately, my code has not been cooperating - I've tried reviewing the documentation that Facebook provides and searching the web for answers without coming up with anything useful. So far all I've been able to get the app to do is validate the app's permissions with Facebook and display the map, though I had tested the ability to add markers with dummy values in an earlier version of the app and that worked fine.
My earlier question dealt with why my calls to the Graph API weren't displaying anything - I had made the same call as listed in the AuthorizeListener sub-class, but was merely attempting to output the raw JSON string in a log entry instead of manipulating it. I think that whatever was the cause of that problem is probably the same cause of my current problem.
Anyway, how do I get my app to display markers for locations a user has checked in to? I think my code gets me off to a pretty good start, but there are obviously issues in my AuthorizeListener sub-class. What do you guys think?
public class FBCTActivity extends MapActivity {
public static Context mContext;
List<Overlay> mapOverlays;
FBCTMarkerOverlay markerLayer;
ArrayList<OverlayItem> overlays = new ArrayList<OverlayItem>();
// Facebook Application ID
private static final String APP_ID = "";
Facebook mFacebook = new Facebook(APP_ID);
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mContext = this;
setContentView(R.layout.main);
// Set up Facebook stuff
mFacebook.authorize(this, new String[]{"user_checkins", "offline_access"}, new AuthorizeListener());
// Set up map stuff
MapView mMapView = (MapView)findViewById(R.id.map);
mMapView.setSatellite(true);
MapController mMapController = mMapView.getController();
mMapController.animateTo(getCurrentLocation());
mMapController.setZoom(3);
// Set up overlay stuff
mapOverlays = mMapView.getOverlays();
Drawable drawable = this.getResources().getDrawable(R.drawable.icon);
markerLayer = new FBCTMarkerOverlay(drawable);
// markerLayer is populated in the AuthorizeListener sub-class
mapOverlays.add(markerLayer);
}
/**
* Determines the device's current location, but does not display it.
* Used for centering the view on the device's location.
* #return A GeoPoint object that contains the lat/long coordinates for the device's location.
*/
private GeoPoint getCurrentLocation() {
LocationManager mLocationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
Criteria mCriteria = new Criteria();
mCriteria.setAccuracy(Criteria.ACCURACY_COARSE);
mCriteria.setPowerRequirement(Criteria.POWER_LOW);
String mLocationProvider = mLocationManager.getBestProvider(mCriteria, true);
Location mLocation = mLocationManager.getLastKnownLocation(mLocationProvider);
int mLat = (int)(mLocation.getLatitude()*1E6);
int mLong = (int)(mLocation.getLongitude()*1E6);
return new GeoPoint(mLat, mLong);
}
#Override
protected boolean isRouteDisplayed() {
// TODO Auto-generated method stub
return false;
}
private class AuthorizeListener implements DialogListener {
public void onComplete(Bundle values) {
new Thread() {
#Override
public void run() {
try {
String response = mFacebook.request("me/checkins"); // The JSON to get
JSONObject jObject = Util.parseJson(response);
JSONArray jArray = jObject.getJSONArray("data"); // Read the JSON array returned by the request
for (int i = 0; i < jArray.length(); i++) { // Iterate through the array
JSONObject outerPlace = jArray.getJSONObject(i); // The outer JSON object
JSONObject place = outerPlace.getJSONObject("place"); // Second-tier JSON object that contains id, name, and location values for the "place"
String placeName = place.getString("name"); // The place's name
JSONObject placeLocation = place.getJSONObject("location"); // Third-tier JSON object that contains latitude and longitude coordinates for the place's "location"
int lat = (int) (placeLocation.getDouble("latitude")*1E6); // The place's latitude
int lon = (int) (placeLocation.getDouble("longitude")*1E6); // The place's longitude
String date = outerPlace.getString("created_time"); // Timestamp of the checkin
overlays.add(new OverlayItem(new GeoPoint(lat, lon), placeName, "Checked in on: " + date)); // Add the place's details to our ArrayList of OverlayItems
}
mFacebook.logout(mContext); // Logout of Facebook
for (int i = 0; i < overlays.size(); i++) {
markerLayer.addOverlayItem(overlays.get(i));
}
} catch(IOException e) {
Log.v("FBCTActivity", e.getMessage());
} catch(JSONException e) {
Log.v("FBCTActivity", e.getMessage());
}
}
}.start();
}
public void onFacebookError(FacebookError e) {
Log.w("FBCTActivity", e.getMessage());
// TODO: Add more graceful error handling
}
public void onError(DialogError e) {
Log.w("FBCTActivity", e.getMessage());
}
public void onCancel() {
// TODO Auto-generated method stub
}
}
}
It might not be the reason but you haven't defined your app ID:
private static final String APP_ID = "";
Also, you have to override the onActivityResult in the activity where you call the mFacebook.authorize, so add this to your code:
#Override
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
mFacebook.authorizeCallback(requestCode, resultCode, data);
}
If you don't do so, your app won't get the token for the Graph and your connection will return a JSON error msg.

Categories

Resources