diff --git a/app/build.gradle b/app/build.gradle index cff33c2..e3ee386 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -47,4 +47,5 @@ dependencies { compile('com.crashlytics.sdk.android:crashlytics:2.6.2@aar') { transitive = true; } + compile 'org.apache.commons:commons-lang3:3.4' } diff --git a/app/src/androidTest/java/pl/tpolgrabia/urbanexplorer/utils/WikiUtilsTest.java b/app/src/androidTest/java/pl/tpolgrabia/urbanexplorer/utils/WikiUtilsTest.java new file mode 100644 index 0000000..4ba000c --- /dev/null +++ b/app/src/androidTest/java/pl/tpolgrabia/urbanexplorer/utils/WikiUtilsTest.java @@ -0,0 +1,7 @@ +package pl.tpolgrabia.urbanexplorer.utils; + +/** + * Created by tpolgrabia on 11.09.16. + */ +public class WikiUtilsTest { +} diff --git a/app/src/main/java/pl/tpolgrabia/urbanexplorer/AppConstants.java b/app/src/main/java/pl/tpolgrabia/urbanexplorer/AppConstants.java index c6701da..3915e21 100644 --- a/app/src/main/java/pl/tpolgrabia/urbanexplorer/AppConstants.java +++ b/app/src/main/java/pl/tpolgrabia/urbanexplorer/AppConstants.java @@ -5,4 +5,6 @@ package pl.tpolgrabia.urbanexplorer; */ public class AppConstants { public static final String GOOGLE_API_KEY = "AIzaSyDAnmEK6cgovRrefUuYojL1pxPEbIBLZUw"; + public static final long MIN_TIME = 60000; + public static final float MIN_DISTANCE = 100; } diff --git a/app/src/main/java/pl/tpolgrabia/urbanexplorer/MainActivity.java b/app/src/main/java/pl/tpolgrabia/urbanexplorer/MainActivity.java index 3280ae5..64ece64 100644 --- a/app/src/main/java/pl/tpolgrabia/urbanexplorer/MainActivity.java +++ b/app/src/main/java/pl/tpolgrabia/urbanexplorer/MainActivity.java @@ -1,6 +1,11 @@ package pl.tpolgrabia.urbanexplorer; +import android.content.Context; +import android.content.Intent; +import android.location.Location; +import android.location.LocationManager; import android.os.Bundle; +import android.provider.Settings; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; @@ -10,7 +15,6 @@ import android.util.Log; import android.view.GestureDetector; import android.view.MenuItem; import android.view.MotionEvent; -import android.widget.LinearLayout; import android.widget.Toast; import com.crashlytics.android.Crashlytics; import com.nostra13.universalimageloader.cache.memory.impl.WeakMemoryCache; @@ -18,7 +22,9 @@ import com.nostra13.universalimageloader.core.DisplayImageOptions; import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.core.ImageLoaderConfiguration; import io.fabric.sdk.android.Fabric; -import pl.tpolgrabia.urbanexplorer.dto.PanoramioImageInfo; +import pl.tpolgrabia.urbanexplorer.callbacks.StandardLocationListener; +import pl.tpolgrabia.urbanexplorer.callbacks.StandardLocationListenerCallback; +import pl.tpolgrabia.urbanexplorer.dto.panoramio.PanoramioImageInfo; import pl.tpolgrabia.urbanexplorer.fragments.HomeFragment; import pl.tpolgrabia.urbanexplorer.fragments.PanoramioShowerFragment; import pl.tpolgrabia.urbanexplorer.fragments.WikiLocationsFragment; @@ -26,6 +32,7 @@ import pl.tpolgrabia.urbanexplorer.utils.ImageLoaderUtils; public class MainActivity extends ActionBarActivity implements GestureDetector.OnGestureListener { + private static final int LOCATION_SETTINGS_REQUEST_ID = 1; private static final String CLASS_TAG = MainActivity.class.getSimpleName(); private static final String PHOTO_BACKSTACK = "PHOTO_BACKSTACK"; private static final float SWIPE_VELOCITY_THRESHOLD = 20; @@ -37,6 +44,19 @@ public class MainActivity extends ActionBarActivity implements GestureDetector.O private GestureDetectorCompat gestureDetector; private float SWIPE_THRESHOLD = 50; private int currentFragmentId = 0; + private LocationManager locationService; + private StandardLocationListener locationCallback; + + private boolean gpsLocationEnabled; + private boolean networkLocationEnabled; + private boolean locationEnabled; + private String locationProvider; + private boolean locationServicesActivated = false; + + + public StandardLocationListener getLocationCallback() { + return locationCallback; + } @Override public boolean onTouchEvent(MotionEvent event) { @@ -47,7 +67,6 @@ public class MainActivity extends ActionBarActivity implements GestureDetector.O @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - Fabric.with(this, new Crashlytics()); setContentView(R.layout.activity_main); // Toolbar toolbar = (Toolbar) findViewById(R.id.navbar); // setSupportActionBar(toolbar); @@ -67,12 +86,14 @@ public class MainActivity extends ActionBarActivity implements GestureDetector.O getSupportFragmentManager() .beginTransaction() - .add(R.id.fragments, new HomeFragment()) + .replace(R.id.fragments, new HomeFragment()) .commit(); - + // lLinearLayout locations = (LinearLayout) findViewById(R.id.locations); // locations.setOnTouchListener(new OnSwipeTouchListener); gestureDetector = new GestureDetectorCompat(this, this); + locationCallback = new StandardLocationListener(); + initLocalication(); Fabric fabric = new Fabric.Builder(this).debuggable(true).kits(new Crashlytics()).build(); Fabric.with(fabric); } @@ -190,7 +211,6 @@ public class MainActivity extends ActionBarActivity implements GestureDetector.O } private void swipeDown() { - Toast.makeText(this, "Swiped down", Toast.LENGTH_SHORT).show(); } @@ -232,4 +252,91 @@ public class MainActivity extends ActionBarActivity implements GestureDetector.O currentFragmentId = (int)Math.min(MAX_FRAGMENT_ID, currentFragmentId+1); switchFragment(); } + + private void initLocalication() { + if (checkForLocalicatonEnabled()) return; + + final Context ctx = this; + + locationCallback.addCallback(new StandardLocationListenerCallback() { + @Override + public void callback(Location location) { + double lat = location.getLatitude(); + double lng = location.getLongitude(); + // getSupportFragmentManager().findFragmentById(R.id.wiki_) + // TextView locationInfo = (TextView) findViewById(R.id.locationInfo); + // locationInfo.setText("Location: (" + lat + "," + lng + ")"); + Toast.makeText(ctx, "Location: (" + lat + "," + lng + ")", Toast.LENGTH_SHORT).show(); + } + }); + } + + private boolean checkForLocalicatonEnabled() { + + locationService = (LocationManager) getSystemService(LOCATION_SERVICE); + + checkLocationSourceAvailability(); + + if (!locationEnabled) { + Intent locationSettingsIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS); + startActivityForResult(locationSettingsIntent, LOCATION_SETTINGS_REQUEST_ID); + return true; + } + return false; + } + + private void checkLocationSourceAvailability() { + gpsLocationEnabled = locationService.isProviderEnabled(LocationManager.GPS_PROVIDER); + networkLocationEnabled = locationService.isProviderEnabled(LocationManager.NETWORK_PROVIDER); + locationEnabled = gpsLocationEnabled || networkLocationEnabled; + if (gpsLocationEnabled) { + locationProvider = LocationManager.GPS_PROVIDER; + return; + } + + if (networkLocationEnabled) { + locationProvider = LocationManager.NETWORK_PROVIDER; + return; + } + } + + @Override + protected void onResume() { + super.onResume(); + + if (locationProvider != null) { + locationService.requestLocationUpdates(locationProvider, + AppConstants.MIN_TIME, + AppConstants.MIN_DISTANCE, + locationCallback); + locationServicesActivated = true; + Toast.makeText(this, "Location resumed", Toast.LENGTH_LONG).show(); + } + } + + @Override + protected void onPause() { + super.onPause(); + if (locationServicesActivated) { + locationService.removeUpdates(locationCallback); + } + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + + switch (requestCode) { + case LOCATION_SETTINGS_REQUEST_ID: + checkLocationSourceAvailability(); + if (!locationEnabled) { + // sadly, nothing to do except from notifing user that program is not enable working + Toast.makeText(this, "Sorry location services are not working." + + " Program cannot work properly - check location settings to allow program working correctly", + Toast.LENGTH_LONG).show(); + } + break; + default: + super.onActivityResult(requestCode, resultCode, data); + } + } } diff --git a/app/src/main/java/pl/tpolgrabia/urbanexplorer/adapters/WikiLocationsAdapter.java b/app/src/main/java/pl/tpolgrabia/urbanexplorer/adapters/WikiLocationsAdapter.java new file mode 100644 index 0000000..7b723cf --- /dev/null +++ b/app/src/main/java/pl/tpolgrabia/urbanexplorer/adapters/WikiLocationsAdapter.java @@ -0,0 +1,59 @@ +package pl.tpolgrabia.urbanexplorer.adapters; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.TextView; +import com.nostra13.universalimageloader.core.ImageLoader; +import pl.tpolgrabia.urbanexplorer.MainActivity; +import pl.tpolgrabia.urbanexplorer.R; +import pl.tpolgrabia.urbanexplorer.dto.wiki.app.WikiAppObject; + +import java.util.List; + +/** + * Created by tpolgrabia on 01.09.16. + */ +public class WikiLocationsAdapter extends ArrayAdapter { + public WikiLocationsAdapter(Context ctx, List locations) { + super(ctx, R.layout.wiki_locations_item, locations); + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + final LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + View inflatedView; + if (convertView != null) { + // reusing old view + inflatedView = convertView; + } else { + inflatedView = inflater.inflate(R.layout.wiki_locations_item,parent,false); + } + + WikiAppObject wikiPage = getItem(position); + + // wiki page image preview + ImageView imgPreview = (ImageView) inflatedView.findViewById(R.id.wiki_locs_item_img_preview); + String url = wikiPage.getThumbnail() != null ? wikiPage.getThumbnail() : null; + + TextView locDistanceInfo = (TextView) inflatedView.findViewById(R.id.wiki_locs_item_distance); + locDistanceInfo.setText("" + wikiPage.getDistance() / 1000.0 + " km"); + + if (url != null) { + ImageLoader.getInstance().displayImage( + url, + imgPreview, + MainActivity.options); + } + + // wiki page title + TextView pageTitle = (TextView) inflatedView.findViewById(R.id.wiki_locs_item_title); + pageTitle.setText(wikiPage.getTitle()); + + + return inflatedView; + } +} diff --git a/app/src/main/java/pl/tpolgrabia/urbanexplorer/callbacks/PanoramioResponseCallback.java b/app/src/main/java/pl/tpolgrabia/urbanexplorer/callbacks/PanoramioResponseCallback.java index 787e343..2ee430c 100644 --- a/app/src/main/java/pl/tpolgrabia/urbanexplorer/callbacks/PanoramioResponseCallback.java +++ b/app/src/main/java/pl/tpolgrabia/urbanexplorer/callbacks/PanoramioResponseCallback.java @@ -1,6 +1,7 @@ package pl.tpolgrabia.urbanexplorer.callbacks; -import pl.tpolgrabia.urbanexplorer.dto.PanoramioImageInfo; + +import pl.tpolgrabia.urbanexplorer.dto.panoramio.PanoramioImageInfo; import java.util.List; diff --git a/app/src/main/java/pl/tpolgrabia/urbanexplorer/callbacks/StandardLocationListener.java b/app/src/main/java/pl/tpolgrabia/urbanexplorer/callbacks/StandardLocationListener.java new file mode 100644 index 0000000..dbbbc30 --- /dev/null +++ b/app/src/main/java/pl/tpolgrabia/urbanexplorer/callbacks/StandardLocationListener.java @@ -0,0 +1,48 @@ +package pl.tpolgrabia.urbanexplorer.callbacks; + +import android.location.Location; +import android.location.LocationListener; +import android.os.Bundle; +import android.util.Log; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by tpolgrabia on 28.08.16. + */ +public class StandardLocationListener implements LocationListener { + private static final String CLASS_TAG = StandardLocationListener.class.getSimpleName(); + private List locationChangedCallbacks = new ArrayList<>(); + + @Override + public void onLocationChanged(Location location) { + Log.i(CLASS_TAG, "Location provider changed: " + location); + for (StandardLocationListenerCallback callback : locationChangedCallbacks) { + callback.callback(location); + } + } + + @Override + public void onStatusChanged(String provider, int status, Bundle extras) { + // Log.i(CLASS_TAG, "Location provider status changed") + } + + @Override + public void onProviderEnabled(String provider) { + Log.i(CLASS_TAG, "Provider " + provider + " enabled"); + } + + @Override + public void onProviderDisabled(String provider) { + Log.i(CLASS_TAG, "Provider " + provider + " disabled"); + } + + public void addCallback(StandardLocationListenerCallback callback) { + locationChangedCallbacks.add(callback); + } + + public boolean removeCallback(StandardLocationListenerCallback callback) { + return locationChangedCallbacks.remove(callback); + } +} diff --git a/app/src/main/java/pl/tpolgrabia/urbanexplorer/callbacks/StandardLocationListenerCallback.java b/app/src/main/java/pl/tpolgrabia/urbanexplorer/callbacks/StandardLocationListenerCallback.java new file mode 100644 index 0000000..a113dd8 --- /dev/null +++ b/app/src/main/java/pl/tpolgrabia/urbanexplorer/callbacks/StandardLocationListenerCallback.java @@ -0,0 +1,11 @@ +package pl.tpolgrabia.urbanexplorer.callbacks; + +import android.location.Location; + +/** + * Created by tpolgrabia on 28.08.16. + */ +public interface StandardLocationListenerCallback { + + void callback(Location location); +} diff --git a/app/src/main/java/pl/tpolgrabia/urbanexplorer/callbacks/WikiResponseCallback.java b/app/src/main/java/pl/tpolgrabia/urbanexplorer/callbacks/WikiResponseCallback.java new file mode 100644 index 0000000..d76cc2b --- /dev/null +++ b/app/src/main/java/pl/tpolgrabia/urbanexplorer/callbacks/WikiResponseCallback.java @@ -0,0 +1,10 @@ +package pl.tpolgrabia.urbanexplorer.callbacks; + +import pl.tpolgrabia.urbanexplorer.dto.wiki.generator.WikiResponse; + +/** + * Created by tpolgrabia on 28.08.16. + */ +public interface WikiResponseCallback { + void callback(WikiStatus status, WikiResponse response); +} diff --git a/app/src/main/java/pl/tpolgrabia/urbanexplorer/callbacks/WikiStatus.java b/app/src/main/java/pl/tpolgrabia/urbanexplorer/callbacks/WikiStatus.java new file mode 100644 index 0000000..7835c06 --- /dev/null +++ b/app/src/main/java/pl/tpolgrabia/urbanexplorer/callbacks/WikiStatus.java @@ -0,0 +1,10 @@ +package pl.tpolgrabia.urbanexplorer.callbacks; + +/** + * Created by tpolgrabia on 28.08.16. + */ +public enum WikiStatus { + SUCCESS, + NETWORK_ERROR, + GENERAL_ERROR +} diff --git a/app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/PanoramioImageInfo.java b/app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/panoramio/PanoramioImageInfo.java similarity index 97% rename from app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/PanoramioImageInfo.java rename to app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/panoramio/PanoramioImageInfo.java index 1fbe599..955d48a 100644 --- a/app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/PanoramioImageInfo.java +++ b/app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/panoramio/PanoramioImageInfo.java @@ -1,4 +1,4 @@ -package pl.tpolgrabia.urbanexplorer.dto; +package pl.tpolgrabia.urbanexplorer.dto.panoramio; import java.io.Serializable; diff --git a/app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/PanoramioMapLocation.java b/app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/panoramio/PanoramioMapLocation.java similarity index 94% rename from app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/PanoramioMapLocation.java rename to app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/panoramio/PanoramioMapLocation.java index bdbd88f..a8c4e40 100644 --- a/app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/PanoramioMapLocation.java +++ b/app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/panoramio/PanoramioMapLocation.java @@ -1,4 +1,4 @@ -package pl.tpolgrabia.urbanexplorer.dto; +package pl.tpolgrabia.urbanexplorer.dto.panoramio; import java.io.Serializable; diff --git a/app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/PanoramioResponse.java b/app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/panoramio/PanoramioResponse.java similarity index 96% rename from app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/PanoramioResponse.java rename to app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/panoramio/PanoramioResponse.java index ef07cdb..df29686 100644 --- a/app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/PanoramioResponse.java +++ b/app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/panoramio/PanoramioResponse.java @@ -1,4 +1,4 @@ -package pl.tpolgrabia.urbanexplorer.dto; +package pl.tpolgrabia.urbanexplorer.dto.panoramio; import java.io.Serializable; import java.util.List; diff --git a/app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/wiki/app/WikiAppObject.java b/app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/wiki/app/WikiAppObject.java new file mode 100644 index 0000000..6dbb1b8 --- /dev/null +++ b/app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/wiki/app/WikiAppObject.java @@ -0,0 +1,84 @@ +package pl.tpolgrabia.urbanexplorer.dto.wiki.app; + +import java.io.Serializable; + +/** + * Created by tpolgrabia on 05.09.16. + */ +public class WikiAppObject implements Serializable { + private String url; + private String thumbnail; + private String title; + private Double latitude; + private Double longitude; + private Double distance; + private Long pageId; + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getThumbnail() { + return thumbnail; + } + + public void setThumbnail(String thumbnail) { + this.thumbnail = thumbnail; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public Double getLatitude() { + return latitude; + } + + public void setLatitude(Double latitude) { + this.latitude = latitude; + } + + public Double getLongitude() { + return longitude; + } + + public void setLongitude(Double longitude) { + this.longitude = longitude; + } + + public Double getDistance() { + return distance; + } + + public void setDistance(Double distance) { + this.distance = distance; + } + + @Override + public String toString() { + return "WikiAppObject{" + + "url='" + url + '\'' + + ", thumbnail='" + thumbnail + '\'' + + ", title='" + title + '\'' + + ", latitude='" + latitude + '\'' + + ", longitude='" + longitude + '\'' + + ", distance='" + distance + '\'' + + '}'; + } + + public Long getPageId() { + return pageId; + } + + public void setPageId(Long pageId) { + this.pageId = pageId; + } +} diff --git a/app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/wiki/generator/WikiLocation.java b/app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/wiki/generator/WikiLocation.java new file mode 100644 index 0000000..f8d45e1 --- /dev/null +++ b/app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/wiki/generator/WikiLocation.java @@ -0,0 +1,60 @@ +package pl.tpolgrabia.urbanexplorer.dto.wiki.generator; + +import java.io.Serializable; + +/** + * Created by tpolgrabia on 28.08.16. + */ +public class WikiLocation implements Serializable{ + private static final long serialVersionUID = 2574692501816893919L; + private String globe; + private Double latitude; + private Double longitude; + private String primary; + + public static long getSerialVersionUID() { + return serialVersionUID; + } + + public String getGlobe() { + return globe; + } + + public void setGlobe(String globe) { + this.globe = globe; + } + + public Double getLatitude() { + return latitude; + } + + public void setLatitude(Double latitude) { + this.latitude = latitude; + } + + public Double getLongitude() { + return longitude; + } + + public void setLongitude(Double longitude) { + this.longitude = longitude; + } + + public String getPrimary() { + return primary; + } + + public void setPrimary(String primary) { + this.primary = primary; + } + + @Override + public String toString() { + return "WikiLocation{" + + "globe='" + globe + '\'' + + ", latitude=" + latitude + + ", longitude=" + longitude + + ", primary='" + primary + '\'' + + '}'; + } +} diff --git a/app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/wiki/generator/WikiPage.java b/app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/wiki/generator/WikiPage.java new file mode 100644 index 0000000..624259e --- /dev/null +++ b/app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/wiki/generator/WikiPage.java @@ -0,0 +1,75 @@ +package pl.tpolgrabia.urbanexplorer.dto.wiki.generator; + +import java.util.List; + +/** + * Created by tpolgrabia on 28.08.16. + */ +public class WikiPage { + private List coordinates; + private Long index; + private Long ns; + private Long pageId; + private WikiThumbnail thumbnail; + private String title; + + public List getCoordinates() { + return coordinates; + } + + public void setCoordinates(List coordinates) { + this.coordinates = coordinates; + } + + public Long getIndex() { + return index; + } + + public void setIndex(Long index) { + this.index = index; + } + + public Long getNs() { + return ns; + } + + public void setNs(Long ns) { + this.ns = ns; + } + + public Long getPageId() { + return pageId; + } + + public void setPageId(Long pageId) { + this.pageId = pageId; + } + + public WikiThumbnail getThumbnail() { + return thumbnail; + } + + public void setThumbnail(WikiThumbnail thumbnail) { + this.thumbnail = thumbnail; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + @Override + public String toString() { + return "WikiPage{" + + "coordinates=" + coordinates + + ", index=" + index + + ", ns=" + ns + + ", pageId=" + pageId + + ", thumbnail=" + thumbnail + + ", title='" + title + '\'' + + '}'; + } +} diff --git a/app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/wiki/generator/WikiResponse.java b/app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/wiki/generator/WikiResponse.java new file mode 100644 index 0000000..b62e4e0 --- /dev/null +++ b/app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/wiki/generator/WikiResponse.java @@ -0,0 +1,37 @@ +package pl.tpolgrabia.urbanexplorer.dto.wiki.generator; + +import java.io.Serializable; +import java.util.List; + +/** + * Created by tpolgrabia on 28.08.16. + */ +public class WikiResponse implements Serializable { + private static final long serialVersionUID = 2208673089408151268L; + private Boolean batchComplete; + private List pages; + + public Boolean getBatchComplete() { + return batchComplete; + } + + public void setBatchComplete(Boolean batchComplete) { + this.batchComplete = batchComplete; + } + + public List getPages() { + return pages; + } + + public void setPages(List pages) { + this.pages = pages; + } + + @Override + public String toString() { + return "WikiResponse{" + + "batchComplete=" + batchComplete + + ", pages=" + pages + + '}'; + } +} diff --git a/app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/wiki/generator/WikiThumbnail.java b/app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/wiki/generator/WikiThumbnail.java new file mode 100644 index 0000000..a3f83b4 --- /dev/null +++ b/app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/wiki/generator/WikiThumbnail.java @@ -0,0 +1,43 @@ +package pl.tpolgrabia.urbanexplorer.dto.wiki.generator; + +/** + * Created by tpolgrabia on 28.08.16. + */ +public class WikiThumbnail { + private Long height; + private String source; + private Long width; + + public Long getHeight() { + return height; + } + + public void setHeight(Long height) { + this.height = height; + } + + public String getSource() { + return source; + } + + public void setSource(String source) { + this.source = source; + } + + public Long getWidth() { + return width; + } + + public void setWidth(Long width) { + this.width = width; + } + + @Override + public String toString() { + return "WikiThumbnail{" + + "height=" + height + + ", source='" + source + '\'' + + ", width=" + width + + '}'; + } +} diff --git a/app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/wiki/geosearch/WikiGeoObject.java b/app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/wiki/geosearch/WikiGeoObject.java new file mode 100644 index 0000000..4a9b299 --- /dev/null +++ b/app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/wiki/geosearch/WikiGeoObject.java @@ -0,0 +1,86 @@ +package pl.tpolgrabia.urbanexplorer.dto.wiki.geosearch; + +import java.io.Serializable; + +/** + * Created by tpolgrabia on 05.09.16. + */ +public class WikiGeoObject implements Serializable { + private static final long serialVersionUID = 4527861009683008530L; + private Long pageId; + private Long ns; + private String title; + private Double latitude; + private Double longitude; + private Double distance; + private String primary; + + public Long getPageId() { + return pageId; + } + + public void setPageId(Long pageId) { + this.pageId = pageId; + } + + public Long getNs() { + return ns; + } + + public void setNs(Long ns) { + this.ns = ns; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public Double getLatitude() { + return latitude; + } + + public void setLatitude(Double latitude) { + this.latitude = latitude; + } + + public Double getLongitude() { + return longitude; + } + + public void setLongitude(Double longitude) { + this.longitude = longitude; + } + + public Double getDistance() { + return distance; + } + + public void setDistance(Double distance) { + this.distance = distance; + } + + public String getPrimary() { + return primary; + } + + public void setPrimary(String primary) { + this.primary = primary; + } + + @Override + public String toString() { + return "WikiGeoObject{" + + "pageId=" + pageId + + ", ns=" + ns + + ", title='" + title + '\'' + + ", latitude=" + latitude + + ", longitude=" + longitude + + ", distance=" + distance + + ", primary='" + primary + '\'' + + '}'; + } +} diff --git a/app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/wiki/geosearch/WikiGeoResponse.java b/app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/wiki/geosearch/WikiGeoResponse.java new file mode 100644 index 0000000..c867538 --- /dev/null +++ b/app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/wiki/geosearch/WikiGeoResponse.java @@ -0,0 +1,35 @@ +package pl.tpolgrabia.urbanexplorer.dto.wiki.geosearch; + +import java.util.List; + +/** + * Created by tpolgrabia on 05.09.16. + */ +public class WikiGeoResponse { + private Boolean batchComplete; + private List query; + + public Boolean getBatchComplete() { + return batchComplete; + } + + public void setBatchComplete(Boolean batchComplete) { + this.batchComplete = batchComplete; + } + + public List getQuery() { + return query; + } + + public void setQuery(List query) { + this.query = query; + } + + @Override + public String toString() { + return "WikiGeoResponse{" + + "batchComplete=" + batchComplete + + ", query=" + query + + '}'; + } +} diff --git a/app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/wiki/geosearch/WikiGeoResponseCallback.java b/app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/wiki/geosearch/WikiGeoResponseCallback.java new file mode 100644 index 0000000..6a754a2 --- /dev/null +++ b/app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/wiki/geosearch/WikiGeoResponseCallback.java @@ -0,0 +1,10 @@ +package pl.tpolgrabia.urbanexplorer.dto.wiki.geosearch; + +import pl.tpolgrabia.urbanexplorer.callbacks.WikiStatus; + +/** + * Created by tpolgrabia on 05.09.16. + */ +public interface WikiGeoResponseCallback { + void callback(WikiStatus status, WikiGeoResponse response); +} diff --git a/app/src/main/java/pl/tpolgrabia/urbanexplorer/fragments/HomeFragment.java b/app/src/main/java/pl/tpolgrabia/urbanexplorer/fragments/HomeFragment.java index 5e3a47e..04ca298 100644 --- a/app/src/main/java/pl/tpolgrabia/urbanexplorer/fragments/HomeFragment.java +++ b/app/src/main/java/pl/tpolgrabia/urbanexplorer/fragments/HomeFragment.java @@ -1,16 +1,10 @@ package pl.tpolgrabia.urbanexplorer.fragments; - -import android.content.Intent; +import android.content.Context; import android.location.Location; -import android.location.LocationListener; import android.location.LocationManager; import android.os.Bundle; -import android.provider.Settings; import android.support.v4.app.Fragment; -import android.support.v4.widget.SwipeRefreshLayout; -import android.text.Editable; -import android.text.TextWatcher; import android.util.Log; import android.view.LayoutInflater; import android.view.View; @@ -21,35 +15,24 @@ import pl.tpolgrabia.urbanexplorer.MainActivity; import pl.tpolgrabia.urbanexplorer.R; import pl.tpolgrabia.urbanexplorer.callbacks.PanoramioResponseCallback; import pl.tpolgrabia.urbanexplorer.callbacks.PanoramioResponseStatus; -import pl.tpolgrabia.urbanexplorer.dto.PanoramioImageInfo; -import pl.tpolgrabia.urbanexplorer.utils.NumberUtils; +import pl.tpolgrabia.urbanexplorer.callbacks.StandardLocationListenerCallback; +import pl.tpolgrabia.urbanexplorer.dto.panoramio.PanoramioImageInfo; +import pl.tpolgrabia.urbanexplorer.utils.LocationUtils; import pl.tpolgrabia.urbanexplorer.utils.PanoramioUtils; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Semaphore; -import java.util.concurrent.atomic.AtomicBoolean; - -import static android.content.Context.LOCATION_SERVICE; /** * A simple {@link Fragment} subclass. */ -public class HomeFragment extends Fragment implements LocationListener { +public class HomeFragment extends Fragment { private static final String CLASS_TAG = HomeFragment.class.getSimpleName(); - private static final long MIN_TIME = 60000; - private static final float MIN_DISTANCE = 100; - private static final int LOCATION_SETTINGS_REQUEST_ID = 1; - private static final String LOCATIONS_LIST_IMAGE_SIZE = "medium"; - private static final String LOCATIONS_ORDER = "popularity"; + private static final int PANORAMIA_BULK_DATA_SIZE = 10; - private boolean gpsLocationEnabled; - private boolean networkLocationEnabled; - private boolean locationEnabled; private LocationManager locationService; - private String locationProvider; - private boolean locationServicesActivated = false; private AQuery aq; private boolean initialized = false; @@ -58,6 +41,8 @@ public class HomeFragment extends Fragment implements LocationListener { private Semaphore loading = new Semaphore(1, true); private List photos = new ArrayList<>(); private boolean photosInitialized = false; + private String locationProvider; + private boolean noMorePhotos = false; public HomeFragment() { // Required empty public constructor @@ -67,18 +52,21 @@ public class HomeFragment extends Fragment implements LocationListener { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); aq = new AQuery(getActivity()); - - locationService = (LocationManager) getActivity().getSystemService(LOCATION_SERVICE); - - checkLocationSourceAvailability(); - - if (!locationEnabled) { - Intent locationSettingsIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS); - startActivityForResult(locationSettingsIntent, LOCATION_SETTINGS_REQUEST_ID); - return; - } - - // loading.release(); + MainActivity mainActivity = ((MainActivity) getActivity()); + mainActivity.getLocationCallback() + .addCallback(new StandardLocationListenerCallback() { + @Override + public void callback(Location location) { + noMorePhotos = false; + photos = new ArrayList<>(); + updateLocationInfo(); + try { + fetchAdditionalPhotos(); + } catch (InterruptedException e) { + Log.e(CLASS_TAG, "Failed trying acquring lock to load photos", e); + } + } + }); } @@ -173,8 +161,6 @@ public class HomeFragment extends Fragment implements LocationListener { // } // ); - locations = (ListView)inflatedView.findViewById(R.id.locations); - initialized = true; // try { @@ -189,6 +175,11 @@ public class HomeFragment extends Fragment implements LocationListener { private void fetchAdditionalPhotos() throws InterruptedException { + if (noMorePhotos) { + Log.v(CLASS_TAG, "No more photos - last query was zero result"); + return; + } + if (!initialized) { Log.v(CLASS_TAG, "Fetching additional photos blocked till system is initialized"); return; @@ -245,6 +236,7 @@ public class HomeFragment extends Fragment implements LocationListener { ListView locations = (ListView) getView().findViewById(R.id.locations); ArrayAdapter adapter = (ArrayAdapter) locations.getAdapter(); photos.addAll(images); + noMorePhotos = images.isEmpty(); if (adapter == null) { locations.setAdapter(new PanoramioAdapter(getActivity(), R.id.list_item, images)); } else { @@ -270,7 +262,11 @@ public class HomeFragment extends Fragment implements LocationListener { private void fetchPanoramioLocations() { - final Location location = locationService.getLastKnownLocation(locationProvider); + fetchPanoramioPhotos(); + } + + private void fetchPanoramioPhotos() { + final Location location = locationService.getLastKnownLocation(LocationUtils.getDefaultLocation(getActivity())); Double radiusX = fetchRadiusX(); Double radiusY = fetchRadiusY(); PanoramioUtils.fetchPanoramioImages( @@ -312,89 +308,26 @@ public class HomeFragment extends Fragment implements LocationListener { return safeParseDouble(radiusyTextView.getText()); } - @Override - public void onLocationChanged(Location location) { - Log.i(CLASS_TAG, "Location provider changed: " + location); - double lat = location.getLatitude(); - double lng = location.getLongitude(); - TextView locationInfo = (TextView) getActivity().findViewById(R.id.locationInfo); - locationInfo.setText("Location: (" + lat + "," + lng + ")"); - if (!photosInitialized) { - try { - fetchAdditionalPhotos(); - } catch (InterruptedException e) { - Log.e(CLASS_TAG, "Failed acquirng loading lock", e); - } - } - } - - @Override - public void onStatusChanged(String provider, int status, Bundle extras) { - // Log.i(CLASS_TAG, "Location provider status changed") - } - - @Override - public void onProviderEnabled(String provider) { - Log.i(CLASS_TAG, "Provider " + provider + " enabled"); - } - - @Override - public void onProviderDisabled(String provider) { - Log.i(CLASS_TAG, "Provider " + provider + " disabled"); - } - @Override public void onResume() { super.onResume(); - - if (locationProvider != null) { - locationService.requestLocationUpdates(locationProvider, - MIN_TIME, - MIN_DISTANCE, - this); - locationServicesActivated = true; - Toast.makeText(getActivity(), "Location resumed", Toast.LENGTH_LONG).show(); - } + locationProvider = LocationUtils.getDefaultLocation(getActivity()); + updateLocationInfo(); } - @Override - public void onPause() { - super.onPause(); - if (locationServicesActivated) { - locationService.removeUpdates(this); - } - } - - private void checkLocationSourceAvailability() { - gpsLocationEnabled = locationService.isProviderEnabled(LocationManager.GPS_PROVIDER); - networkLocationEnabled = locationService.isProviderEnabled(LocationManager.NETWORK_PROVIDER); - locationEnabled = gpsLocationEnabled || networkLocationEnabled; - if (gpsLocationEnabled) { - locationProvider = LocationManager.GPS_PROVIDER; + public void updateLocationInfo() { + final View view = getView(); + if (view == null) { + Log.wtf(CLASS_TAG, "Fragment has no view"); return; } - - if (networkLocationEnabled) { - locationProvider = LocationManager.NETWORK_PROVIDER; - return; - } - } - - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - - switch (requestCode) { - case LOCATION_SETTINGS_REQUEST_ID: - checkLocationSourceAvailability(); - if (!locationEnabled) { - // sadly, nothing to do except from notifing user that program is not enable working - Toast.makeText(getActivity(), "Sorry location services are not working." + - " Program cannot work properly - check location settings to allow program working correctly", - Toast.LENGTH_LONG).show(); - } - break; - default: - super.onActivityResult(requestCode, resultCode, data); + TextView locationInfo = (TextView) view.findViewById(R.id.locationInfo); + locationService = (LocationManager)getActivity().getSystemService(Context.LOCATION_SERVICE); + Location currLocation = locationService.getLastKnownLocation(LocationUtils.getDefaultLocation(getActivity())); + Log.v(CLASS_TAG, "Current location: " + currLocation + ", locationInfo: " + locationInfo); + if (currLocation != null && locationInfo != null) { + // update home fragment's location info + locationInfo.setText("Location: " + currLocation.getLatitude() + "," + currLocation.getLongitude()); } } } diff --git a/app/src/main/java/pl/tpolgrabia/urbanexplorer/fragments/PanoramioAdapter.java b/app/src/main/java/pl/tpolgrabia/urbanexplorer/fragments/PanoramioAdapter.java index 1a80440..c242bcf 100644 --- a/app/src/main/java/pl/tpolgrabia/urbanexplorer/fragments/PanoramioAdapter.java +++ b/app/src/main/java/pl/tpolgrabia/urbanexplorer/fragments/PanoramioAdapter.java @@ -1,7 +1,6 @@ package pl.tpolgrabia.urbanexplorer.fragments; import android.content.Context; -import android.graphics.Bitmap; import android.support.v4.app.FragmentActivity; import android.view.LayoutInflater; import android.view.View; @@ -13,7 +12,7 @@ import com.androidquery.AQuery; import com.nostra13.universalimageloader.core.ImageLoader; import pl.tpolgrabia.urbanexplorer.MainActivity; import pl.tpolgrabia.urbanexplorer.R; -import pl.tpolgrabia.urbanexplorer.dto.PanoramioImageInfo; +import pl.tpolgrabia.urbanexplorer.dto.panoramio.PanoramioImageInfo; import java.util.List; diff --git a/app/src/main/java/pl/tpolgrabia/urbanexplorer/fragments/PanoramioShowerFragment.java b/app/src/main/java/pl/tpolgrabia/urbanexplorer/fragments/PanoramioShowerFragment.java index 425614c..02123f8 100644 --- a/app/src/main/java/pl/tpolgrabia/urbanexplorer/fragments/PanoramioShowerFragment.java +++ b/app/src/main/java/pl/tpolgrabia/urbanexplorer/fragments/PanoramioShowerFragment.java @@ -14,7 +14,7 @@ import android.widget.TextView; import com.nostra13.universalimageloader.core.ImageLoader; import pl.tpolgrabia.urbanexplorer.MainActivity; import pl.tpolgrabia.urbanexplorer.R; -import pl.tpolgrabia.urbanexplorer.dto.PanoramioImageInfo; +import pl.tpolgrabia.urbanexplorer.dto.panoramio.PanoramioImageInfo; /** * A simple {@link Fragment} subclass. diff --git a/app/src/main/java/pl/tpolgrabia/urbanexplorer/fragments/WikiLocationsFragment.java b/app/src/main/java/pl/tpolgrabia/urbanexplorer/fragments/WikiLocationsFragment.java index a79f3cd..4ef69f1 100644 --- a/app/src/main/java/pl/tpolgrabia/urbanexplorer/fragments/WikiLocationsFragment.java +++ b/app/src/main/java/pl/tpolgrabia/urbanexplorer/fragments/WikiLocationsFragment.java @@ -1,13 +1,37 @@ package pl.tpolgrabia.urbanexplorer.fragments; +import android.content.Intent; +import android.location.Location; +import android.location.LocationManager; +import android.net.Uri; import android.os.Bundle; import android.support.v4.app.Fragment; +import android.text.Editable; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; - +import android.widget.*; +import com.androidquery.AQuery; +import com.androidquery.callback.AjaxCallback; +import com.androidquery.callback.AjaxStatus; +import org.json.JSONException; +import org.json.JSONObject; +import pl.tpolgrabia.urbanexplorer.MainActivity; import pl.tpolgrabia.urbanexplorer.R; +import pl.tpolgrabia.urbanexplorer.adapters.WikiLocationsAdapter; +import pl.tpolgrabia.urbanexplorer.callbacks.StandardLocationListenerCallback; +import pl.tpolgrabia.urbanexplorer.callbacks.WikiStatus; +import pl.tpolgrabia.urbanexplorer.dto.wiki.app.WikiAppObject; +import pl.tpolgrabia.urbanexplorer.utils.LocationUtils; +import pl.tpolgrabia.urbanexplorer.utils.NumberUtils; +import pl.tpolgrabia.urbanexplorer.utils.WikiAppResponseCallback; +import pl.tpolgrabia.urbanexplorer.utils.WikiUtils; + +import java.util.List; + +import static android.content.Context.LOCATION_SERVICE; /** * A simple {@link Fragment} subclass. @@ -15,6 +39,11 @@ import pl.tpolgrabia.urbanexplorer.R; public class WikiLocationsFragment extends Fragment { + private static final String CLASS_TAG = WikiLocationsFragment.class.getSimpleName(); + private LocationManager locationService; + private TextView currentLocation; + private Button fetchPlaces; + public WikiLocationsFragment() { // Required empty public constructor } @@ -24,14 +53,123 @@ public class WikiLocationsFragment extends Fragment { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment - View inflatedView = inflater.inflate(R.layout.fragment_wiki_locations, container, false); - inflatedView.setOnClickListener(new View.OnClickListener() { + final View inflatedView = inflater.inflate(R.layout.fragment_wiki_locations, container, false); + + inflatedView.findViewById(R.id.wiki_fetch_places).setOnClickListener( + new View.OnClickListener() { + @Override + public void onClick(View v) { + // TODO replace this + Toast.makeText(getActivity(), "Fetch wiki objects", Toast.LENGTH_SHORT); + } + } + ); + + locationService = (LocationManager) getActivity().getSystemService(LOCATION_SERVICE); + currentLocation = (TextView) inflatedView.findViewById(R.id.wiki_current_location); + fetchPlaces = (Button)inflatedView.findViewById(R.id.wiki_fetch_places); + fetchPlaces.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - throw new RuntimeException("FAKE BUG 2"); + final Location location = locationService.getLastKnownLocation(LocationUtils.getDefaultLocation(getActivity())); + Editable search_limit = ((EditText) inflatedView.findViewById(R.id.wiki_search_limit)).getText(); + Editable radius_limit = ((EditText) inflatedView.findViewById(R.id.wiki_search_radius)).getText(); + + + WikiUtils.fetchAppData(getActivity(), + location.getLatitude(), + location.getLongitude(), + NumberUtils.safeParseDouble(search_limit != null ? search_limit.toString() : null), + NumberUtils.safeParseLong( + radius_limit != null ? radius_limit.toString() : null), + new WikiAppResponseCallback() { + @Override + public void callback(WikiStatus status, final List appObjects) { + // handling here wiki locations + if (status != WikiStatus.SUCCESS) { + Toast.makeText(getActivity(), "Sorry, currently we have problem with interfacing wiki" + + ": " + status + ". Try again later", Toast.LENGTH_SHORT).show(); + return; + } + + // TODO on success + + ListView locations = (ListView) inflatedView.findViewById(R.id.wiki_places); + locations.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { + @Override + public boolean onItemLongClick(AdapterView parent, View view, final int position, long id) { +// WikiPage item = response.getPages().get(position); +// Intent intent = new Intent(android.content.Intent.ACTION_VIEW, +// Uri.parse(item.get); +// startActivity(intent); + final WikiAppObject item = appObjects.get(position); + new AQuery(getActivity()).ajax( + "https://en.wikipedia.org/w/api.php?action=query&prop=info&pageids=" + + item.getPageId() + "&inprop=url&format=json", + JSONObject.class, + new AjaxCallback() { + @Override + public void callback(String url, JSONObject object, AjaxStatus status) { + if (status.getCode() != 200) { + Toast.makeText(getActivity(), + "Sorry, network error code: " + status.getCode(), + Toast.LENGTH_LONG) + .show(); + return; + } + + + try { + String wikiUrl = object.getJSONObject("query") + .getJSONObject("pages") + .getJSONObject(item.getPageId().toString()) + .getString("fullurl"); + Intent intent = new Intent(android.content.Intent.ACTION_VIEW, + Uri.parse(wikiUrl)); + startActivity(intent); + } catch (JSONException e) { + Log.e(CLASS_TAG, "Error", e); + } + } + } + ); + return false; + } + }); + locations.setAdapter(new WikiLocationsAdapter(getActivity(), appObjects)); + } + } + ); + } }); + + MainActivity mainActivity = (MainActivity) getActivity(); + mainActivity.getLocationCallback().addCallback(new StandardLocationListenerCallback() { + @Override + public void callback(Location location) { + updateLocationInfo(); + } + }); + return inflatedView; } + @Override + public void onResume() { + super.onResume(); + updateLocationInfo(); + } + + public void updateLocationInfo() { + final Location location = locationService.getLastKnownLocation(LocationUtils.getDefaultLocation(getActivity())); + if (location != null) { + currentLocation.setText("Location: " + location.getLatitude() + "," + location.getLongitude()); + } + } + + @Override + public void onPause() { + super.onPause(); + } } diff --git a/app/src/main/java/pl/tpolgrabia/urbanexplorer/utils/LocationUtils.java b/app/src/main/java/pl/tpolgrabia/urbanexplorer/utils/LocationUtils.java new file mode 100644 index 0000000..cb64bd3 --- /dev/null +++ b/app/src/main/java/pl/tpolgrabia/urbanexplorer/utils/LocationUtils.java @@ -0,0 +1,22 @@ +package pl.tpolgrabia.urbanexplorer.utils; + +import android.content.Context; +import android.location.LocationManager; + +/** + * Created by tpolgrabia on 28.08.16. + */ +public class LocationUtils { + public static String getDefaultLocation(Context ctx) { + LocationManager locationService = (LocationManager) ctx.getSystemService(Context.LOCATION_SERVICE); + if (locationService.isProviderEnabled(LocationManager.GPS_PROVIDER)) { + return LocationManager.GPS_PROVIDER; + } + + if (locationService.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) { + return LocationManager.NETWORK_PROVIDER; + } + + return null; + } +} diff --git a/app/src/main/java/pl/tpolgrabia/urbanexplorer/utils/NumberUtils.java b/app/src/main/java/pl/tpolgrabia/urbanexplorer/utils/NumberUtils.java index ca35248..2e4b74b 100644 --- a/app/src/main/java/pl/tpolgrabia/urbanexplorer/utils/NumberUtils.java +++ b/app/src/main/java/pl/tpolgrabia/urbanexplorer/utils/NumberUtils.java @@ -4,16 +4,32 @@ package pl.tpolgrabia.urbanexplorer.utils; * Created by tpolgrabia on 27.08.16. */ public class NumberUtils { - public static Long safeParseLong(CharSequence charSequence) { - if (charSequence == null) { - return 1L; + public static Long safeParseLong(String s) { + if (s == null || "".equals(s.trim())) { + return null; } + String trimmed = s.trim(); + try { - return Long.parseLong(charSequence.toString()); + return Long.parseLong(trimmed); } catch (NumberFormatException e) { - return 1L; + return null; } } + + public static Double safeParseDouble(String s) { + if (s == null || "".equals(s.trim())) { + return null; + } + + String trimmed = s.trim(); + + try { + return Double.parseDouble(trimmed); + } catch (NumberFormatException e) { + return null; + } + } } diff --git a/app/src/main/java/pl/tpolgrabia/urbanexplorer/utils/PanoramioUtils.java b/app/src/main/java/pl/tpolgrabia/urbanexplorer/utils/PanoramioUtils.java index 8aae3c7..9477411 100644 --- a/app/src/main/java/pl/tpolgrabia/urbanexplorer/utils/PanoramioUtils.java +++ b/app/src/main/java/pl/tpolgrabia/urbanexplorer/utils/PanoramioUtils.java @@ -2,25 +2,20 @@ package pl.tpolgrabia.urbanexplorer.utils; import android.content.Context; import android.util.Log; -import android.widget.ArrayAdapter; -import android.widget.TextView; import com.androidquery.AQuery; import com.androidquery.callback.AjaxCallback; import com.androidquery.callback.AjaxStatus; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; -import pl.tpolgrabia.urbanexplorer.R; import pl.tpolgrabia.urbanexplorer.callbacks.PanoramioResponseCallback; import pl.tpolgrabia.urbanexplorer.callbacks.PanoramioResponseStatus; -import pl.tpolgrabia.urbanexplorer.dto.PanoramioImageInfo; -import pl.tpolgrabia.urbanexplorer.dto.PanoramioMapLocation; -import pl.tpolgrabia.urbanexplorer.dto.PanoramioResponse; +import pl.tpolgrabia.urbanexplorer.dto.panoramio.PanoramioImageInfo; +import pl.tpolgrabia.urbanexplorer.dto.panoramio.PanoramioMapLocation; +import pl.tpolgrabia.urbanexplorer.dto.panoramio.PanoramioResponse; import pl.tpolgrabia.urbanexplorer.exceptions.PanoramioResponseNotExpected; -import pl.tpolgrabia.urbanexplorer.fragments.PanoramioAdapter; import java.text.ParseException; -import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.List; diff --git a/app/src/main/java/pl/tpolgrabia/urbanexplorer/utils/WikiAppResponseCallback.java b/app/src/main/java/pl/tpolgrabia/urbanexplorer/utils/WikiAppResponseCallback.java new file mode 100644 index 0000000..a254aac --- /dev/null +++ b/app/src/main/java/pl/tpolgrabia/urbanexplorer/utils/WikiAppResponseCallback.java @@ -0,0 +1,13 @@ +package pl.tpolgrabia.urbanexplorer.utils; + +import pl.tpolgrabia.urbanexplorer.callbacks.WikiStatus; +import pl.tpolgrabia.urbanexplorer.dto.wiki.app.WikiAppObject; + +import java.util.List; + +/** + * Created by tpolgrabia on 11.09.16. + */ +public interface WikiAppResponseCallback { + void callback(WikiStatus status, List appObjects); +} diff --git a/app/src/main/java/pl/tpolgrabia/urbanexplorer/utils/WikiUtils.java b/app/src/main/java/pl/tpolgrabia/urbanexplorer/utils/WikiUtils.java new file mode 100644 index 0000000..2e46640 --- /dev/null +++ b/app/src/main/java/pl/tpolgrabia/urbanexplorer/utils/WikiUtils.java @@ -0,0 +1,327 @@ +package pl.tpolgrabia.urbanexplorer.utils; + +import android.content.Context; +import android.util.Log; +import android.widget.Toast; +import com.androidquery.AQuery; +import com.androidquery.callback.AjaxCallback; +import com.androidquery.callback.AjaxStatus; +import org.apache.commons.lang3.StringUtils; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import pl.tpolgrabia.urbanexplorer.callbacks.WikiResponseCallback; +import pl.tpolgrabia.urbanexplorer.callbacks.WikiStatus; +import pl.tpolgrabia.urbanexplorer.dto.wiki.app.WikiAppObject; +import pl.tpolgrabia.urbanexplorer.dto.wiki.generator.WikiLocation; +import pl.tpolgrabia.urbanexplorer.dto.wiki.generator.WikiPage; +import pl.tpolgrabia.urbanexplorer.dto.wiki.generator.WikiResponse; +import pl.tpolgrabia.urbanexplorer.dto.wiki.generator.WikiThumbnail; +import pl.tpolgrabia.urbanexplorer.dto.wiki.geosearch.WikiGeoObject; +import pl.tpolgrabia.urbanexplorer.dto.wiki.geosearch.WikiGeoResponse; +import pl.tpolgrabia.urbanexplorer.dto.wiki.geosearch.WikiGeoResponseCallback; + +import java.util.*; + +/** + * Created by tpolgrabia on 28.08.16. + */ +public class WikiUtils { + private static final String CLASS_TAG = WikiUtils.class.getSimpleName(); + private static final String WIKI_FORMAT = "json"; + private static final long WIKI_MIN_RADIUS = 10L; + private static final Long WIKI_MAX_RESULTS_LIMIT = 500L; + private static final Long WIKI_MIN_RESULTS = 10L; + private static final Double WIKI_STD_RADIUS = 10000.0; + private static final Long WIKI_STD_LIMIT = 10L; + + public static void fetchNearPlaces(Context ctx, + final double latitude, + final double longitude, + final Long resultsLimit, + final Long radiusLimit, + final WikiResponseCallback callback) { + final AQuery aq = new AQuery(ctx); + aq.ajax("TODO", JSONObject.class, new AjaxCallback(){ + @Override + public void callback(String url, JSONObject object, AjaxStatus status) { + // TODO handle response + final String qurl = "https://en.wikipedia.org/w/api.php?" + + "action=query" + + "&prop=coordinates%7Cpageimages%7Cpageterms" + + "&colimit=50" + + "&piprop=thumbnail" + + "&pithumbsize=144" + + "&pilimit=50" + + "&wbptterms=description" + + "&generator=geosearch" + + "&ggscoord=" + latitude + "%7C" + longitude + + "&ggsradius=" + Math.max(WIKI_MIN_RADIUS, ifNullSet(radiusLimit, 10000L)) + + "&ggslimit=" + Math.min(WIKI_MIN_RESULTS, Math.max(WIKI_MAX_RESULTS_LIMIT, + checkIfNullLong(resultsLimit))) + + "&format=" + WIKI_FORMAT; + aq.ajax(qurl, JSONObject.class, new AjaxCallback() { + @Override + public void callback(String url, JSONObject object, AjaxStatus status) { + if (status.getCode() == 200) { + try { + callback.callback(WikiStatus.SUCCESS, fetchWikiResponse(object)); + } catch (JSONException e) { + Log.e(CLASS_TAG, "JSon error: " + object.toString(), e); + } + } else { + callback.callback(WikiStatus.NETWORK_ERROR, null); + } + } + }); + + } + }); + } + + private static T ifNullSet(T val, T def) { + return val == null ? def : val; + } + + private static Long checkIfNullLong(Long lval) { + return lval != null ? lval : 0L; + } + + public static WikiResponse fetchWikiResponse(JSONObject object) throws JSONException { + if (object == null) { + return null; + } + + WikiResponse wikiResponse = new WikiResponse(); + wikiResponse.setBatchComplete(Boolean.valueOf(object.getString("batchcomplete"))); + wikiResponse.setPages(fetchPages(object.getJSONObject("query").getJSONObject("pages"))); + return wikiResponse; + } + + public static List fetchPages(JSONObject jpages) throws JSONException { + List pages = new ArrayList<>(); + Iterator pagesIds = jpages.keys(); + while (pagesIds.hasNext()) { + String pageId = pagesIds.next(); + pages.add(fetchPage(jpages.getJSONObject(pageId))); + } + return pages; + } + + public static WikiPage fetchPage(JSONObject jpage) throws JSONException { + WikiPage wikiPage = new WikiPage(); + wikiPage.setCoordinates(fetchCoordinates(jpage.optJSONArray("coordinates"))); + wikiPage.setIndex(jpage.optLong("index")); + wikiPage.setNs(jpage.optLong("ns")); + wikiPage.setPageId(jpage.optLong("pageid")); + wikiPage.setThumbnail(fetchThumbnail(jpage.optJSONObject("thumbnail"))); + wikiPage.setTitle(jpage.optString("title")); + return wikiPage; + } + + public static WikiThumbnail fetchThumbnail(JSONObject jthumbnail) throws JSONException { + if (jthumbnail == null) { + return null; + } + WikiThumbnail wikiThumbnail = new WikiThumbnail(); + wikiThumbnail.setWidth(jthumbnail.getLong("width")); + wikiThumbnail.setHeight(jthumbnail.getLong("height")); + wikiThumbnail.setSource(jthumbnail.getString("source")); + return wikiThumbnail; + } + + public static List fetchCoordinates(JSONArray jcoordinates) throws JSONException { + if (jcoordinates == null) { + return null; + } + + List wikiLocations = new ArrayList(); + + int n = jcoordinates.length(); + for (int i = 0; i < n; i++) { + wikiLocations.add(fetchCoordinate(jcoordinates.getJSONObject(i))); + } + + return wikiLocations; + } + + public static WikiLocation fetchCoordinate(JSONObject jlocation) throws JSONException { + WikiLocation wikiLocation = new WikiLocation(); + wikiLocation.setLatitude(jlocation.getDouble("lat")); + wikiLocation.setLongitude(jlocation.getDouble("lon")); + wikiLocation.setPrimary(jlocation.getString("primary")); + wikiLocation.setGlobe(jlocation.getString("globe")); + return wikiLocation; + } + + public static void fetchGeoSearchWikiMetadata(Context ctx, + Double latitude, + Double longitude, + Double radius, + Long limit, + final WikiGeoResponseCallback callback) { + + if (radius == null) { + radius = WIKI_STD_RADIUS; + } + + if (limit == null) { + limit = WIKI_STD_LIMIT; + } + + AQuery aq = new AQuery(ctx); + aq.ajax("https://en.wikipedia.org/w/api.php?action=query&list=geosearch&gscoord=52.2181737%7C21.1530673&gsradius=10000&gslimit=10&format=json", JSONObject.class, new AjaxCallback() { + @Override + public void callback(String url, JSONObject object, AjaxStatus status) { + Log.v(CLASS_TAG, "Finished waiting for " + url + + " with status " + status.getCode() + ":" + status.getMessage() + + " and response: " + object); + if (status.getCode() == 200) { + try { + callback.callback(WikiStatus.SUCCESS, fetchWikiGeoResponse(object)); + } catch (Throwable t) { + Log.e(CLASS_TAG, "General error during fetching", t); + callback.callback(WikiStatus.GENERAL_ERROR, null); + } + } else { + Log.e(CLASS_TAG, "Couldn't fetch wiki metadata " + object + + ", status: " + status.getCode() + ": " + status.getMessage() + " from url: " + url); + callback.callback(WikiStatus.NETWORK_ERROR, null); + } + super.callback(url, object, status); + } + }); + + } + + public static WikiGeoResponse fetchWikiGeoResponse(JSONObject object) { + WikiGeoResponse response = new WikiGeoResponse(); + response.setBatchComplete(object.optBoolean("batch_complete")); + response.setQuery(fetchQueriesData(object.optJSONObject("query").optJSONArray("geosearch"))); + return response; + } + + public static List fetchQueriesData(JSONArray object) { + List geoObjects = new ArrayList<>(); + int n = object.length(); + int idx; + for (idx = 0; idx < n; idx++) { + JSONObject geoPage = object.optJSONObject(idx); + geoObjects.add(fetchWikiGeoObject(geoPage)); + } + return geoObjects; + } + + public static WikiGeoObject fetchWikiGeoObject(JSONObject geoPage) { + WikiGeoObject object = new WikiGeoObject(); + object.setPageId(geoPage.optLong("pageid")); + object.setNs(geoPage.optLong("ns")); + object.setTitle(geoPage.optString("title")); + object.setLatitude(geoPage.optDouble("lat")); + object.setLongitude(geoPage.optDouble("lon")); + object.setDistance(geoPage.optDouble("dist")); + object.setPrimary(geoPage.optString("primary")); + return object; + } + + public static void fetchAppData(final Context ctx, + final Double latitude, + final Double longitude, + final Double radius, + final Long limit, + final WikiAppResponseCallback callback) { + + fetchGeoSearchWikiMetadata(ctx, latitude, longitude, radius, limit, new WikiGeoResponseCallback() { + @Override + public void callback(WikiStatus status, WikiGeoResponse response) { + + Log.v(CLASS_TAG, "Fetching finished with status: " + status + " and values: " + response); + + if (status != WikiStatus.SUCCESS) { + Toast.makeText(ctx, "Sorry, couldn't fetch wiki metadata", Toast.LENGTH_SHORT).show(); + return; + } + + final List geoItems = response.getQuery(); + if (geoItems == null) { + return; + } + + List pageIds = new ArrayList(); + for (WikiGeoObject wikiGeoObject : geoItems) { + pageIds.add(wikiGeoObject.getPageId()); + } + + final Map geoItemsMap = new HashMap<>(); + for (WikiGeoObject geoItem : geoItems) { + geoItemsMap.put(geoItem.getPageId(), geoItem); + } + + + fetchPageInfos(ctx, + pageIds, + new WikiResponseCallback() { + @Override + public void callback(WikiStatus status, WikiResponse response) { + if (status != WikiStatus.SUCCESS) { + callback.callback(WikiStatus.NETWORK_ERROR, null); + return; + } + + List results = new ArrayList(); + List pages = response.getPages(); + for (WikiPage page : pages) { + WikiAppObject appObject = new WikiAppObject(); + appObject.setTitle(page.getTitle()); + appObject.setDistance(geoItemsMap.get(page.getPageId()).getDistance()); + appObject.setLatitude(page.getCoordinates().get(0).getLatitude()); + appObject.setLongitude(page.getCoordinates().get(0).getLongitude()); + final WikiThumbnail thumbonail = page.getThumbnail(); + final String thumSource = thumbonail != null ? thumbonail.getSource() : null; + appObject.setThumbnail(thumSource); + appObject.setUrl(thumSource); + appObject.setPageId(page.getPageId()); + results.add(appObject); + } + + // TODO here add callback invocation with result + + callback.callback(WikiStatus.SUCCESS, results); + + } + }); + } + }); + + } + + public static void fetchPageInfos(Context ctx, List pageIds, final WikiResponseCallback callback) { + AQuery aq = new AQuery(ctx); + aq.ajax("https://en.wikipedia.org/w/api.php" + + "?action=query" + + "&prop=coordinates%7Cpageimages%7Cpageterms" + + "&colimit=50" + + "&piprop=thumbnail" + + "&pithumbsize=144" + + "&pilimit=50" + + "&wbptterms=description" + + "&pageids=" + StringUtils.join(pageIds, "|") + + "&format=json", JSONObject.class, new AjaxCallback() { + @Override + public void callback(String url, JSONObject object, AjaxStatus status) { + if (status.getCode() == 200) { + try { + callback.callback(WikiStatus.SUCCESS, fetchWikiResponse(object)); + } catch (Throwable t) { + Log.e(CLASS_TAG, "General error", t); + callback.callback(WikiStatus.GENERAL_ERROR, null); + } + } else { + callback.callback(WikiStatus.NETWORK_ERROR, null); + } + } + }); + } + + +} diff --git a/app/src/main/res/layout/fragment_wiki_locations.xml b/app/src/main/res/layout/fragment_wiki_locations.xml index 2876d88..ec4a16b 100644 --- a/app/src/main/res/layout/fragment_wiki_locations.xml +++ b/app/src/main/res/layout/fragment_wiki_locations.xml @@ -1,19 +1,44 @@ + - - + + + + + + + + + + + + + +