diff --git a/.gitignore b/.gitignore index b9d6bd9..fdc5554 100644 --- a/.gitignore +++ b/.gitignore @@ -1,215 +1,33 @@ -################# -## Eclipse -################# +# built application files +*.apk +*.ap_ -*.pydevproject -.project -.metadata -bin/ -tmp/ -*.tmp -*.bak -*.swp -*~.nib -local.properties -.classpath -.settings/ -.loadpath - -# External tool builders -.externalToolBuilders/ - -# Locally stored "Eclipse launch configurations" -*.launch - -# CDT-specific -.cproject - -# PDT-specific -.buildpath - - -################# -## Visual Studio -################# - -## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. - -# User-specific files -*.suo -*.user -*.sln.docstates - -# Build results - -[Dd]ebug/ -[Rr]elease/ -x64/ -build/ -[Bb]in/ -[Oo]bj/ - -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -*_i.c -*_p.c -*.ilk -*.meta -*.obj -*.pch -*.pdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj -*.log -*.vspscc -*.vssscc -.builds -*.pidb -*.log -*.scc - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opensdf -*.sdf -*.cachefile - -# Visual Studio profiler -*.psess -*.vsp -*.vspx - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper - -# TeamCity is a build add-in -_TeamCity* - -# DotCover is a Code Coverage Tool -*.dotCover +# files for the dex VM +*.dex -# NCrunch -*.ncrunch* -.*crunch*.local.xml +# Java class files +*.class -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# Click-Once directory -publish/ - -# Publish Web Output -*.Publish.xml -*.pubxml - -# NuGet Packages Directory -## TODO: If you have NuGet Package Restore enabled, uncomment the next line -#packages/ - -# Windows Azure Build Output -csx -*.build.csdef - -# Windows Store app package directory -AppPackages/ - -# Others -sql/ -*.Cache -ClientBin/ -[Ss]tyle[Cc]op.* -~$* -*~ -*.dbmdl -*.[Pp]ublish.xml -*.pfx -*.publishsettings - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file to a newer -# Visual Studio version. Backup files are not needed, because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm - -# SQL Server files -App_Data/*.mdf -App_Data/*.ldf - -############# -## Windows detritus -############# - -# Windows image file caches -Thumbs.db -ehthumbs.db - -# Folder config file -Desktop.ini - -# Recycle Bin used on file shares -$RECYCLE.BIN/ - -# Mac crap -.DS_Store - - -############# -## Python -############# - -*.py[co] +# generated files +bin/ +gen/ -# Packages -*.egg -*.egg-info -dist/ -build/ -eggs/ -parts/ -var/ -sdist/ -develop-eggs/ -.installed.cfg +# Local configuration file (sdk path, etc) +local.properties -# Installer logs -pip-log.txt +# Eclipse project files +.classpath +.project -# Unit test / coverage reports -.coverage -.tox +# Proguard folder generated by Eclipse +proguard/ -#Translations -*.mo +# Intellij project files +*.iml +*.ipr +*.iws +.idea/ -#Mr Developer -.mr.developer.cfg +tmp +.gradle +build diff --git a/.idea/misc.xml b/.idea/misc.xml index 5ca368d..43172d3 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,10 +1,155 @@ + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + localhost + 5050 + + + + + + + + + JDK + + + + + + diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 275077f..2be99f4 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -2,6 +2,8 @@ + + diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 4ca49f3..9176fc8 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -7,11 +7,7 @@ - - - - - + @@ -75,30 +71,62 @@ - - + + - + - - + + - + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + - + @@ -114,20 +142,384 @@ + + + + + + - - + @@ -148,12 +540,12 @@ - - + + - + @@ -185,6 +577,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - + - - - + + + + - - - - - + - + - + + + @@ -242,7 +700,11 @@ + + + + - - + + + + + + + + + + + + + + + + + + - + @@ -409,25 +965,29 @@ + + + - + + + + - + + - - - @@ -449,67 +1009,268 @@ + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + + + + + + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/AndroidManifest.xml b/AndroidManifest.xml deleted file mode 100644 index aa7b13e..0000000 --- a/AndroidManifest.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/LocationUpdates.iml b/LocationUpdates.iml deleted file mode 100644 index 5d6f489..0000000 --- a/LocationUpdates.iml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/README.md b/README.md new file mode 100644 index 0000000..e5c48c5 --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# Taken from the Google example +It's clear that Google made a real effort to write a clear, +well crafted and commented example. +## Main changes from the repo on github +* Converted to gradle build diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..3678522 --- /dev/null +++ b/build.gradle @@ -0,0 +1,44 @@ +apply plugin: 'android' + +buildscript { + repositories { + mavenCentral() + } + dependencies { + classpath 'com.android.tools.build:gradle:+' + } +} + +repositories { + def server = 'nexus-server' + def URL = "http://${server}:8081/nexus/content" + maven { + url "${URL}/groups/public" + } + maven { + url "${URL}/repositories/android/" + } + maven { + url "${URL}/repositories/android-snapshots/" + } + maven { + url "${URL}/repositories/snapshots/" + } +} + +dependencies { + compile 'com.android.support:support-v4:19.+' + compile 'com.google.android.gms:play-services:+@aar' + compile 'org.roboguice:roboguice:2.+' +} + +android { + compileSdkVersion 19 + buildToolsVersion '17' +} + +if (hasProperty("xlint")) { + tasks.withType(Compile) { + options.compilerArgs << "-Xlint" + } +} diff --git a/gen/com/example/android/location/BuildConfig.java b/gen/com/example/android/location/BuildConfig.java deleted file mode 100644 index 03872cf..0000000 --- a/gen/com/example/android/location/BuildConfig.java +++ /dev/null @@ -1,8 +0,0 @@ -/*___Generated_by_IDEA___*/ - -package com.example.android.location; - -/* This stub is only used by the IDE. It is NOT the BuildConfig class actually packed into the APK */ -public final class BuildConfig { - public final static boolean DEBUG = Boolean.parseBoolean(null); -} \ No newline at end of file diff --git a/gen/com/example/android/location/Manifest.java b/gen/com/example/android/location/Manifest.java deleted file mode 100644 index 36c1eb5..0000000 --- a/gen/com/example/android/location/Manifest.java +++ /dev/null @@ -1,7 +0,0 @@ -/*___Generated_by_IDEA___*/ - -package com.example.android.location; - -/* This stub is only used by the IDE. It is NOT the Manifest class actually packed into the APK */ -public final class Manifest { -} \ No newline at end of file diff --git a/gen/com/example/android/location/R.java b/gen/com/example/android/location/R.java deleted file mode 100644 index 32a7574..0000000 --- a/gen/com/example/android/location/R.java +++ /dev/null @@ -1,7 +0,0 @@ -/*___Generated_by_IDEA___*/ - -package com.example.android.location; - -/* This stub is only used by the IDE. It is NOT the R class actually packed into the APK */ -public final class R { -} \ No newline at end of file diff --git a/src/com/example/android/location/LocationUtils.java b/src/com/example/android/location/LocationUtils.java deleted file mode 100644 index e12e555..0000000 --- a/src/com/example/android/location/LocationUtils.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.example.android.location; - -import android.content.Context; -import android.location.Location; - -import com.example.android.location.R; - -/** - * Defines app-wide constants and utilities - */ -public final class LocationUtils { - - // Debugging tag for the application - public static final String APPTAG = "LocationSample"; - - // Name of shared preferences repository that stores persistent state - public static final String SHARED_PREFERENCES = - "com.example.android.location.SHARED_PREFERENCES"; - - // Key for storing the "updates requested" flag in shared preferences - public static final String KEY_UPDATES_REQUESTED = - "com.example.android.location.KEY_UPDATES_REQUESTED"; - - /* - * Define a request code to send to Google Play services - * This code is returned in Activity.onActivityResult - */ - public final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000; - - /* - * Constants for location update parameters - */ - // Milliseconds per second - public static final int MILLISECONDS_PER_SECOND = 1000; - - // The update interval - public static final int UPDATE_INTERVAL_IN_SECONDS = 5; - - // A fast interval ceiling - public static final int FAST_CEILING_IN_SECONDS = 1; - - // Update interval in milliseconds - public static final long UPDATE_INTERVAL_IN_MILLISECONDS = - MILLISECONDS_PER_SECOND * UPDATE_INTERVAL_IN_SECONDS; - - // A fast ceiling of update intervals, used when the app is visible - public static final long FAST_INTERVAL_CEILING_IN_MILLISECONDS = - MILLISECONDS_PER_SECOND * FAST_CEILING_IN_SECONDS; - - // Create an empty string for initializing strings - public static final String EMPTY_STRING = new String(); - - /** - * Get the latitude and longitude from the Location object returned by - * Location Services. - * - * @param currentLocation A Location object containing the current location - * @return The latitude and longitude of the current location, or null if no - * location is available. - */ - public static String getLatLng(Context context, Location currentLocation) { - // If the location is valid - if (currentLocation != null) { - - // Return the latitude and longitude as strings - return context.getString( - R.string.latitude_longitude, - currentLocation.getLatitude(), - currentLocation.getLongitude()); - } else { - - // Otherwise, return the empty string - return EMPTY_STRING; - } - } -} diff --git a/src/com/example/android/location/MainActivity.java b/src/com/example/android/location/MainActivity.java deleted file mode 100644 index 6cf6500..0000000 --- a/src/com/example/android/location/MainActivity.java +++ /dev/null @@ -1,650 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.example.android.location; - - -import com.google.android.gms.common.ConnectionResult; -import com.google.android.gms.common.GooglePlayServicesClient; -import com.google.android.gms.common.GooglePlayServicesUtil; -import com.google.android.gms.location.LocationClient; -import com.google.android.gms.location.LocationListener; -import com.google.android.gms.location.LocationRequest; - -import android.content.IntentSender; -import android.location.Address; -import android.location.Geocoder; -import android.location.Location; -import android.os.AsyncTask; -import android.os.Build; -import android.os.Bundle; -import android.annotation.SuppressLint; -import android.app.Activity; -import android.app.Dialog; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.support.v4.app.DialogFragment; -import android.support.v4.app.FragmentActivity; -import android.util.Log; -import android.view.View; -import android.widget.ProgressBar; -import android.widget.TextView; -import android.widget.Toast; - -import java.io.IOException; -import java.util.List; -import java.util.Locale; - -/** - * This the app's main Activity. It provides buttons for requesting the various features of the - * app, displays the current location, the current address, and the status of the location client - * and updating services. - * - * {@link #getLocation} gets the current location using the Location Services getLastLocation() - * function. {@link #getAddress} calls geocoding to get a street address for the current location. - * {@link #startUpdates} sends a request to Location Services to send periodic location updates to - * the Activity. - * {@link #stopUpdates} cancels previous periodic update requests. - * - * The update interval is hard-coded to be 5 seconds. - */ -public class MainActivity extends FragmentActivity implements - LocationListener, - GooglePlayServicesClient.ConnectionCallbacks, - GooglePlayServicesClient.OnConnectionFailedListener { - - // A request to connect to Location Services - private LocationRequest mLocationRequest; - - // Stores the current instantiation of the location client in this object - private LocationClient mLocationClient; - - // Handles to UI widgets - private TextView mLatLng; - private TextView mAddress; - private ProgressBar mActivityIndicator; - private TextView mConnectionState; - private TextView mConnectionStatus; - - // Handle to SharedPreferences for this app - SharedPreferences mPrefs; - - // Handle to a SharedPreferences editor - SharedPreferences.Editor mEditor; - - /* - * Note if updates have been turned on. Starts out as "false"; is set to "true" in the - * method handleRequestSuccess of LocationUpdateReceiver. - * - */ - boolean mUpdatesRequested = false; - - /* - * Initialize the Activity - */ - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - - // Get handles to the UI view objects - mLatLng = (TextView) findViewById(R.id.lat_lng); - mAddress = (TextView) findViewById(R.id.address); - mActivityIndicator = (ProgressBar) findViewById(R.id.address_progress); - mConnectionState = (TextView) findViewById(R.id.text_connection_state); - mConnectionStatus = (TextView) findViewById(R.id.text_connection_status); - - // Create a new global location parameters object - mLocationRequest = LocationRequest.create(); - - /* - * Set the update interval - */ - mLocationRequest.setInterval(LocationUtils.UPDATE_INTERVAL_IN_MILLISECONDS); - - // Use high accuracy - mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); - - // Set the interval ceiling to one minute - mLocationRequest.setFastestInterval(LocationUtils.FAST_INTERVAL_CEILING_IN_MILLISECONDS); - - // Note that location updates are off until the user turns them on - mUpdatesRequested = false; - - // Open Shared Preferences - mPrefs = getSharedPreferences(LocationUtils.SHARED_PREFERENCES, Context.MODE_PRIVATE); - - // Get an editor - mEditor = mPrefs.edit(); - - /* - * Create a new location client, using the enclosing class to - * handle callbacks. - */ - mLocationClient = new LocationClient(this, this, this); - - } - - /* - * Called when the Activity is no longer visible at all. - * Stop updates and disconnect. - */ - @Override - public void onStop() { - - // If the client is connected - if (mLocationClient.isConnected()) { - stopPeriodicUpdates(); - } - - // After disconnect() is called, the client is considered "dead". - mLocationClient.disconnect(); - - super.onStop(); - } - /* - * Called when the Activity is going into the background. - * Parts of the UI may be visible, but the Activity is inactive. - */ - @Override - public void onPause() { - - // Save the current setting for updates - mEditor.putBoolean(LocationUtils.KEY_UPDATES_REQUESTED, mUpdatesRequested); - mEditor.commit(); - - super.onPause(); - } - - /* - * Called when the Activity is restarted, even before it becomes visible. - */ - @Override - public void onStart() { - - super.onStart(); - - /* - * Connect the client. Don't re-start any requests here; - * instead, wait for onResume() - */ - mLocationClient.connect(); - - } - /* - * Called when the system detects that this Activity is now visible. - */ - @Override - public void onResume() { - super.onResume(); - - // If the app already has a setting for getting location updates, get it - if (mPrefs.contains(LocationUtils.KEY_UPDATES_REQUESTED)) { - mUpdatesRequested = mPrefs.getBoolean(LocationUtils.KEY_UPDATES_REQUESTED, false); - - // Otherwise, turn off location updates until requested - } else { - mEditor.putBoolean(LocationUtils.KEY_UPDATES_REQUESTED, false); - mEditor.commit(); - } - - } - - /* - * Handle results returned to this Activity by other Activities started with - * startActivityForResult(). In particular, the method onConnectionFailed() in - * LocationUpdateRemover and LocationUpdateRequester may call startResolutionForResult() to - * start an Activity that handles Google Play services problems. The result of this - * call returns here, to onActivityResult. - */ - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent intent) { - - // Choose what to do based on the request code - switch (requestCode) { - - // If the request code matches the code sent in onConnectionFailed - case LocationUtils.CONNECTION_FAILURE_RESOLUTION_REQUEST : - - switch (resultCode) { - // If Google Play services resolved the problem - case Activity.RESULT_OK: - - // Log the result - Log.d(LocationUtils.APPTAG, getString(R.string.resolved)); - - // Display the result - mConnectionState.setText(R.string.connected); - mConnectionStatus.setText(R.string.resolved); - break; - - // If any other result was returned by Google Play services - default: - // Log the result - Log.d(LocationUtils.APPTAG, getString(R.string.no_resolution)); - - // Display the result - mConnectionState.setText(R.string.disconnected); - mConnectionStatus.setText(R.string.no_resolution); - - break; - } - - // If any other request code was received - default: - // Report that this Activity received an unknown requestCode - Log.d(LocationUtils.APPTAG, - getString(R.string.unknown_activity_request_code, requestCode)); - - break; - } - } - - /** - * Verify that Google Play services is available before making a request. - * - * @return true if Google Play services is available, otherwise false - */ - private boolean servicesConnected() { - - // Check that Google Play services is available - int resultCode = - GooglePlayServicesUtil.isGooglePlayServicesAvailable(this); - - // If Google Play services is available - if (ConnectionResult.SUCCESS == resultCode) { - // In debug mode, log the status - Log.d(LocationUtils.APPTAG, getString(R.string.play_services_available)); - - // Continue - return true; - // Google Play services was not available for some reason - } else { - // Display an error dialog - Dialog dialog = GooglePlayServicesUtil.getErrorDialog(resultCode, this, 0); - if (dialog != null) { - ErrorDialogFragment errorFragment = new ErrorDialogFragment(); - errorFragment.setDialog(dialog); - errorFragment.show(getSupportFragmentManager(), LocationUtils.APPTAG); - } - return false; - } - } - - /** - * Invoked by the "Get Location" button. - * - * Calls getLastLocation() to get the current location - * - * @param v The view object associated with this method, in this case a Button. - */ - public void getLocation(View v) { - - // If Google Play Services is available - if (servicesConnected()) { - - // Get the current location - Location currentLocation = mLocationClient.getLastLocation(); - - // Display the current location in the UI - mLatLng.setText(LocationUtils.getLatLng(this, currentLocation)); - } - } - - /** - * Invoked by the "Get Address" button. - * Get the address of the current location, using reverse geocoding. This only works if - * a geocoding service is available. - * - * @param v The view object associated with this method, in this case a Button. - */ - // For Eclipse with ADT, suppress warnings about Geocoder.isPresent() - @SuppressLint("NewApi") - public void getAddress(View v) { - - // In Gingerbread and later, use Geocoder.isPresent() to see if a geocoder is available. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD && !Geocoder.isPresent()) { - // No geocoder is present. Issue an error message - Toast.makeText(this, R.string.no_geocoder_available, Toast.LENGTH_LONG).show(); - return; - } - - if (servicesConnected()) { - - // Get the current location - Location currentLocation = mLocationClient.getLastLocation(); - - // Turn the indefinite activity indicator on - mActivityIndicator.setVisibility(View.VISIBLE); - - // Start the background task - (new MainActivity.GetAddressTask(this)).execute(currentLocation); - } - } - - /** - * Invoked by the "Start Updates" button - * Sends a request to start location updates - * - * @param v The view object associated with this method, in this case a Button. - */ - public void startUpdates(View v) { - mUpdatesRequested = true; - - if (servicesConnected()) { - startPeriodicUpdates(); - } - } - - /** - * Invoked by the "Stop Updates" button - * Sends a request to remove location updates - * request them. - * - * @param v The view object associated with this method, in this case a Button. - */ - public void stopUpdates(View v) { - mUpdatesRequested = false; - - if (servicesConnected()) { - stopPeriodicUpdates(); - } - } - - /* - * Called by Location Services when the request to connect the - * client finishes successfully. At this point, you can - * request the current location or start periodic updates - */ - @Override - public void onConnected(Bundle bundle) { - mConnectionStatus.setText(R.string.connected); - - if (mUpdatesRequested) { - startPeriodicUpdates(); - } - } - - /* - * Called by Location Services if the connection to the - * location client drops because of an error. - */ - @Override - public void onDisconnected() { - mConnectionStatus.setText(R.string.disconnected); - } - - /* - * Called by Location Services if the attempt to - * Location Services fails. - */ - @Override - public void onConnectionFailed(ConnectionResult connectionResult) { - - /* - * Google Play services can resolve some errors it detects. - * If the error has a resolution, try sending an Intent to - * start a Google Play services activity that can resolve - * error. - */ - if (connectionResult.hasResolution()) { - try { - - // Start an Activity that tries to resolve the error - connectionResult.startResolutionForResult( - this, - LocationUtils.CONNECTION_FAILURE_RESOLUTION_REQUEST); - - /* - * Thrown if Google Play services canceled the original - * PendingIntent - */ - - } catch (IntentSender.SendIntentException e) { - - // Log the error - e.printStackTrace(); - } - } else { - - // If no resolution is available, display a dialog to the user with the error. - showErrorDialog(connectionResult.getErrorCode()); - } - } - - /** - * Report location updates to the UI. - * - * @param location The updated location. - */ - @Override - public void onLocationChanged(Location location) { - - // Report to the UI that the location was updated - mConnectionStatus.setText(R.string.location_updated); - - // In the UI, set the latitude and longitude to the value received - mLatLng.setText(LocationUtils.getLatLng(this, location)); - } - - /** - * In response to a request to start updates, send a request - * to Location Services - */ - private void startPeriodicUpdates() { - - mLocationClient.requestLocationUpdates(mLocationRequest, this); - mConnectionState.setText(R.string.location_requested); - } - - /** - * In response to a request to stop updates, send a request to - * Location Services - */ - private void stopPeriodicUpdates() { - mLocationClient.removeLocationUpdates(this); - mConnectionState.setText(R.string.location_updates_stopped); - } - - /** - * An AsyncTask that calls getFromLocation() in the background. - * The class uses the following generic types: - * Location - A {@link android.location.Location} object containing the current location, - * passed as the input parameter to doInBackground() - * Void - indicates that progress units are not used by this subclass - * String - An address passed to onPostExecute() - */ - protected class GetAddressTask extends AsyncTask { - - // Store the context passed to the AsyncTask when the system instantiates it. - Context localContext; - - // Constructor called by the system to instantiate the task - public GetAddressTask(Context context) { - - // Required by the semantics of AsyncTask - super(); - - // Set a Context for the background task - localContext = context; - } - - /** - * Get a geocoding service instance, pass latitude and longitude to it, format the returned - * address, and return the address to the UI thread. - */ - @Override - protected String doInBackground(Location... params) { - /* - * Get a new geocoding service instance, set for localized addresses. This example uses - * android.location.Geocoder, but other geocoders that conform to address standards - * can also be used. - */ - Geocoder geocoder = new Geocoder(localContext, Locale.getDefault()); - - // Get the current location from the input parameter list - Location location = params[0]; - - // Create a list to contain the result address - List
addresses = null; - - // Try to get an address for the current location. Catch IO or network problems. - try { - - /* - * Call the synchronous getFromLocation() method with the latitude and - * longitude of the current location. Return at most 1 address. - */ - addresses = geocoder.getFromLocation(location.getLatitude(), - location.getLongitude(), 1 - ); - - // Catch network or other I/O problems. - } catch (IOException exception1) { - - // Log an error and return an error message - Log.e(LocationUtils.APPTAG, getString(R.string.IO_Exception_getFromLocation)); - - // print the stack trace - exception1.printStackTrace(); - - // Return an error message - return (getString(R.string.IO_Exception_getFromLocation)); - - // Catch incorrect latitude or longitude values - } catch (IllegalArgumentException exception2) { - - // Construct a message containing the invalid arguments - String errorString = getString( - R.string.illegal_argument_exception, - location.getLatitude(), - location.getLongitude() - ); - // Log the error and print the stack trace - Log.e(LocationUtils.APPTAG, errorString); - exception2.printStackTrace(); - - // - return errorString; - } - // If the reverse geocode returned an address - if (addresses != null && addresses.size() > 0) { - - // Get the first address - Address address = addresses.get(0); - - // Format the first line of address - String addressText = getString(R.string.address_output_string, - - // If there's a street address, add it - address.getMaxAddressLineIndex() > 0 ? - address.getAddressLine(0) : "", - - // Locality is usually a city - address.getLocality(), - - // The country of the address - address.getCountryName() - ); - - // Return the text - return addressText; - - // If there aren't any addresses, post a message - } else { - return getString(R.string.no_address_found); - } - } - - /** - * A method that's called once doInBackground() completes. Set the text of the - * UI element that displays the address. This method runs on the UI thread. - */ - @Override - protected void onPostExecute(String address) { - - // Turn off the progress bar - mActivityIndicator.setVisibility(View.GONE); - - // Set the address in the UI - mAddress.setText(address); - } - } - - /** - * Show a dialog returned by Google Play services for the - * connection error code - * - * @param errorCode An error code returned from onConnectionFailed - */ - private void showErrorDialog(int errorCode) { - - // Get the error dialog from Google Play services - Dialog errorDialog = GooglePlayServicesUtil.getErrorDialog( - errorCode, - this, - LocationUtils.CONNECTION_FAILURE_RESOLUTION_REQUEST); - - // If Google Play services can provide an error dialog - if (errorDialog != null) { - - // Create a new DialogFragment in which to show the error dialog - ErrorDialogFragment errorFragment = new ErrorDialogFragment(); - - // Set the dialog in the DialogFragment - errorFragment.setDialog(errorDialog); - - // Show the error dialog in the DialogFragment - errorFragment.show(getSupportFragmentManager(), LocationUtils.APPTAG); - } - } - - /** - * Define a DialogFragment to display the error dialog generated in - * showErrorDialog. - */ - public static class ErrorDialogFragment extends DialogFragment { - - // Global field to contain the error dialog - private Dialog mDialog; - - /** - * Default constructor. Sets the dialog field to null - */ - public ErrorDialogFragment() { - super(); - mDialog = null; - } - - /** - * Set the dialog to display - * - * @param dialog An error dialog - */ - public void setDialog(Dialog dialog) { - mDialog = dialog; - } - - /* - * This method must return a Dialog to the DialogFragment. - */ - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - return mDialog; - } - } -} diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f742204 --- /dev/null +++ b/src/main/AndroidManifest.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + diff --git a/src/com/example/android/location/LocationServiceErrorMessages.java b/src/main/java/com/example/android/location/LocationServiceErrorMessages.java similarity index 100% rename from src/com/example/android/location/LocationServiceErrorMessages.java rename to src/main/java/com/example/android/location/LocationServiceErrorMessages.java diff --git a/src/main/java/com/example/android/location/LocationUtils.java b/src/main/java/com/example/android/location/LocationUtils.java new file mode 100644 index 0000000..6179c9a --- /dev/null +++ b/src/main/java/com/example/android/location/LocationUtils.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.android.location; + +import android.content.Context; +import android.location.Location; + +/** + * Defines app-wide constants and utilities + */ +public final class LocationUtils { + + // Name of shared preferences repository that stores persistent state + public static final String SHARED_PREFERENCES = "com.example.android.location.SHARED_PREFERENCES"; + + // Key for storing the "updates requested" flag in shared preferences + public static final String KEY_UPDATES_REQUESTED = "com.example.android.location.KEY_UPDATES_REQUESTED"; + + /* + * Define a request code to send to Google Play services + * This code is returned in Activity.onActivityResult + */ + public final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000; + + // The update interval + public static final int UPDATE_INTERVAL_IN_SECONDS = 5; + + // A fast interval ceiling + public static final int FAST_CEILING_IN_SECONDS = 1; + + // Update interval in milliseconds + public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 1000 * UPDATE_INTERVAL_IN_SECONDS; + + // A fast ceiling of update intervals, used when the app is visible + public static final long FAST_INTERVAL_CEILING_IN_MILLISECONDS = 1000 * FAST_CEILING_IN_SECONDS; + + // Create an empty string for initializing strings + private static final String EMPTY_STRING = ""; + + /** + * Get the latitude and longitude from the Location object returned by Location Services. + * + * @param currentLocation A Location object containing the current location + * @return The latitude and longitude of the current location, or null if no location is available. + */ + public static String getLatLng(Context context, Location currentLocation) { + if (currentLocation != null) { + return context.getString( + R.string.latitude_longitude, + currentLocation.getLatitude(), + currentLocation.getLongitude()); + } else { + return EMPTY_STRING; + } + } +} diff --git a/src/main/java/com/example/android/location/MainActivity.java b/src/main/java/com/example/android/location/MainActivity.java new file mode 100644 index 0000000..b0d74f8 --- /dev/null +++ b/src/main/java/com/example/android/location/MainActivity.java @@ -0,0 +1,643 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.android.location; + + +import android.annotation.SuppressLint; +import android.app.Activity; +import android.app.Dialog; +import android.content.Context; +import android.content.Intent; +import android.content.IntentSender; +import android.content.SharedPreferences; +import android.location.Address; +import android.location.Geocoder; +import android.location.Location; +import android.os.AsyncTask; +import android.os.Build; +import android.os.Bundle; +import android.support.v4.app.DialogFragment; +import android.support.v4.app.FragmentActivity; +import android.util.Log; +import android.view.View; +import android.widget.ProgressBar; +import android.widget.TextView; +import android.widget.Toast; + +import com.google.android.gms.common.ConnectionResult; +import com.google.android.gms.common.GooglePlayServicesClient; +import com.google.android.gms.common.GooglePlayServicesUtil; +import com.google.android.gms.location.LocationClient; +import com.google.android.gms.location.LocationListener; +import com.google.android.gms.location.LocationRequest; + +import java.io.IOException; +import java.util.List; +import java.util.Locale; + +/** + * This the app's main Activity. It provides buttons for requesting the various features of the app, displays the + * current location, the current address, and the status of the location client and updating services. + *

+ * {@link #getLocation} gets the current location using the Location Services getLastLocation() function. {@link + * #getAddress} calls geocoding to get a street address for the current location. {@link #startUpdates} sends a request + * to Location Services to send periodic location updates to the Activity. {@link #stopUpdates} cancels previous + * periodic update requests. + *

+ * The update interval is hard-coded to be 5 seconds. + */ +public class MainActivity extends FragmentActivity implements + LocationListener, + GooglePlayServicesClient.ConnectionCallbacks, + GooglePlayServicesClient.OnConnectionFailedListener { + + private static final String TAG = "LocationSample"; + + // A request to connect to Location Services + private LocationRequest mLocationRequest; + + // Stores the current instantiation of the location client in this object + private LocationClient mLocationClient; + + // Handles to UI widgets + private TextView mLatLng; + private TextView mAddress; + private ProgressBar mActivityIndicator; + private TextView mConnectionState; + private TextView mConnectionStatus; + + // Handle to SharedPreferences for this app + SharedPreferences mPrefs; + + // Handle to a SharedPreferences editor + SharedPreferences.Editor mEditor; + + /* + * Note if updates have been turned on. Starts out as "false"; is set to "true" in the + * method handleRequestSuccess of LocationUpdateReceiver. + * + */ + boolean mUpdatesRequested = false; + + /* + * Initialize the Activity + */ + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + // Get handles to the UI view objects + mLatLng = (TextView) findViewById(R.id.lat_lng); + mAddress = (TextView) findViewById(R.id.address); + mActivityIndicator = (ProgressBar) findViewById(R.id.address_progress); + mConnectionState = (TextView) findViewById(R.id.text_connection_state); + mConnectionStatus = (TextView) findViewById(R.id.text_connection_status); + + // Create a new global location parameters object + mLocationRequest = LocationRequest.create(); + + /* + * Set the update interval + */ + mLocationRequest.setInterval(LocationUtils.UPDATE_INTERVAL_IN_MILLISECONDS); + + // Use high accuracy + mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); + + // Set the interval ceiling to one minute + mLocationRequest.setFastestInterval(LocationUtils.FAST_INTERVAL_CEILING_IN_MILLISECONDS); + + // Note that location updates are off until the user turns them on + mUpdatesRequested = false; + + // Open Shared Preferences + mPrefs = getSharedPreferences(LocationUtils.SHARED_PREFERENCES, Context.MODE_PRIVATE); + + // Get an editor + mEditor = mPrefs.edit(); + + /* + * Create a new location client, using the enclosing class to + * handle callbacks. + */ + mLocationClient = new LocationClient(this, this, this); + + } + + /* + * Called when the Activity is no longer visible at all. + * Stop updates and disconnect. + */ + @Override + public void onStop() { + + // If the client is connected + if (mLocationClient.isConnected()) { + stopPeriodicUpdates(); + } + + // After disconnect() is called, the client is considered "dead". + mLocationClient.disconnect(); + + super.onStop(); + } + + /* + * Called when the Activity is going into the background. + * Parts of the UI may be visible, but the Activity is inactive. + */ + @Override + public void onPause() { + + // Save the current setting for updates + mEditor.putBoolean(LocationUtils.KEY_UPDATES_REQUESTED, mUpdatesRequested); + mEditor.commit(); + + super.onPause(); + } + + /* + * Called when the Activity is restarted, even before it becomes visible. + */ + @Override + public void onStart() { + + super.onStart(); + + /* + * Connect the client. Don't re-start any requests here; + * instead, wait for onResume() + */ + mLocationClient.connect(); + + } + + /* + * Called when the system detects that this Activity is now visible. + */ + @Override + public void onResume() { + super.onResume(); + + // If the app already has a setting for getting location updates, get it + if (mPrefs.contains(LocationUtils.KEY_UPDATES_REQUESTED)) { + mUpdatesRequested = mPrefs.getBoolean(LocationUtils.KEY_UPDATES_REQUESTED, false); + + // Otherwise, turn off location updates until requested + } else { + mEditor.putBoolean(LocationUtils.KEY_UPDATES_REQUESTED, false); + mEditor.commit(); + } + + } + + /* + * Handle results returned to this Activity by other Activities started with + * startActivityForResult(). In particular, the method onConnectionFailed() in + * LocationUpdateRemover and LocationUpdateRequester may call startResolutionForResult() to + * start an Activity that handles Google Play services problems. The result of this + * call returns here, to onActivityResult. + */ + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent intent) { + + // Choose what to do based on the request code + switch (requestCode) { + + // If the request code matches the code sent in onConnectionFailed + case LocationUtils.CONNECTION_FAILURE_RESOLUTION_REQUEST: + + switch (resultCode) { + // If Google Play services resolved the problem + case Activity.RESULT_OK: + + // Log the result + Log.d(TAG, getString(R.string.resolved)); + + // Display the result + mConnectionState.setText(R.string.connected); + mConnectionStatus.setText(R.string.resolved); + break; + + // If any other result was returned by Google Play services + default: + // Log the result + Log.d(TAG, getString(R.string.no_resolution)); + + // Display the result + mConnectionState.setText(R.string.disconnected); + mConnectionStatus.setText(R.string.no_resolution); + + break; + } + + // If any other request code was received + default: + // Report that this Activity received an unknown requestCode + Log.d(TAG, + getString(R.string.unknown_activity_request_code, requestCode)); + + break; + } + } + + /** + * Verify that Google Play services is available before making a request. + * + * @return true if Google Play services is available, otherwise false + */ + private boolean servicesConnected() { + + // Check that Google Play services is available + int resultCode = + GooglePlayServicesUtil.isGooglePlayServicesAvailable(this); + + // If Google Play services is available + if (ConnectionResult.SUCCESS == resultCode) { + // In debug mode, log the status + Log.d(TAG, getString(R.string.play_services_available)); + + // Continue + return true; + // Google Play services was not available for some reason + } else { + // Display an error dialog + Dialog dialog = GooglePlayServicesUtil.getErrorDialog(resultCode, this, 0); + if (dialog != null) { + ErrorDialogFragment errorFragment = new ErrorDialogFragment(); + errorFragment.setDialog(dialog); + errorFragment.show(getSupportFragmentManager(), TAG); + } + return false; + } + } + + /** + * Invoked by the "Get Location" button. + *

+ * Calls getLastLocation() to get the current location + * + * @param v The view object associated with this method, in this case a Button. + */ + public void getLocation(View v) { + + // If Google Play Services is available + if (servicesConnected()) { + + // Get the current location + Location currentLocation = mLocationClient.getLastLocation(); + + // Display the current location in the UI + mLatLng.setText(LocationUtils.getLatLng(this, currentLocation)); + } + } + + /** + * Invoked by the "Get Address" button. Get the address of the current location, using reverse geocoding. This only + * works if a geocoding service is available. + * + * @param v The view object associated with this method, in this case a Button. + */ + // For Eclipse with ADT, suppress warnings about Geocoder.isPresent() + @SuppressLint("NewApi") + public void getAddress(View v) { + + // In Gingerbread and later, use Geocoder.isPresent() to see if a geocoder is available. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD && !Geocoder.isPresent()) { + // No geocoder is present. Issue an error message + Toast.makeText(this, R.string.no_geocoder_available, Toast.LENGTH_LONG).show(); + return; + } + + if (servicesConnected()) { + + // Get the current location + Location currentLocation = mLocationClient.getLastLocation(); + + // Turn the indefinite activity indicator on + mActivityIndicator.setVisibility(View.VISIBLE); + + // Start the background task + (new MainActivity.GetAddressTask(this)).execute(currentLocation); + } + } + + /** + * Invoked by the "Start Updates" button Sends a request to start location updates + * + * @param v The view object associated with this method, in this case a Button. + */ + public void startUpdates(View v) { + mUpdatesRequested = true; + + if (servicesConnected()) { + startPeriodicUpdates(); + } + } + + /** + * Invoked by the "Stop Updates" button Sends a request to remove location updates request them. + * + * @param v The view object associated with this method, in this case a Button. + */ + public void stopUpdates(View v) { + mUpdatesRequested = false; + + if (servicesConnected()) { + stopPeriodicUpdates(); + } + } + + /* + * Called by Location Services when the request to connect the + * client finishes successfully. At this point, you can + * request the current location or start periodic updates + */ + @Override + public void onConnected(Bundle bundle) { + mConnectionStatus.setText(R.string.connected); + + if (mUpdatesRequested) { + startPeriodicUpdates(); + } + } + + /* + * Called by Location Services if the connection to the + * location client drops because of an error. + */ + @Override + public void onDisconnected() { + mConnectionStatus.setText(R.string.disconnected); + } + + /* + * Called by Location Services if the attempt to + * Location Services fails. + */ + @Override + public void onConnectionFailed(ConnectionResult connectionResult) { + + /* + * Google Play services can resolve some errors it detects. + * If the error has a resolution, try sending an Intent to + * start a Google Play services activity that can resolve + * error. + */ + if (connectionResult.hasResolution()) { + try { + + // Start an Activity that tries to resolve the error + connectionResult.startResolutionForResult( + this, + LocationUtils.CONNECTION_FAILURE_RESOLUTION_REQUEST); + + /* + * Thrown if Google Play services canceled the original + * PendingIntent + */ + + } catch (IntentSender.SendIntentException e) { + + // Log the error + e.printStackTrace(); + } + } else { + + // If no resolution is available, display a dialog to the user with the error. + showErrorDialog(connectionResult.getErrorCode()); + } + } + + /** + * Report location updates to the UI. + * + * @param location The updated location. + */ + @Override + public void onLocationChanged(Location location) { + + // Report to the UI that the location was updated + mConnectionStatus.setText(R.string.location_updated); + + // In the UI, set the latitude and longitude to the value received + mLatLng.setText(LocationUtils.getLatLng(this, location)); + } + + /** + * In response to a request to start updates, send a request to Location Services + */ + private void startPeriodicUpdates() { + + mLocationClient.requestLocationUpdates(mLocationRequest, this); + mConnectionState.setText(R.string.location_requested); + } + + /** + * In response to a request to stop updates, send a request to Location Services + */ + private void stopPeriodicUpdates() { + mLocationClient.removeLocationUpdates(this); + mConnectionState.setText(R.string.location_updates_stopped); + } + + /** + * An AsyncTask that calls getFromLocation() in the background. The class uses the following generic types: + * Location + * - A {@link android.location.Location} object containing the current location, passed as the input parameter to + * doInBackground() Void - indicates that progress units are not used by this subclass String - An address + * passed to onPostExecute() + */ + protected class GetAddressTask extends AsyncTask { + + // Store the context passed to the AsyncTask when the system instantiates it. + Context localContext; + + // Constructor called by the system to instantiate the task + public GetAddressTask(Context context) { + + // Required by the semantics of AsyncTask + super(); + + // Set a Context for the background task + localContext = context; + } + + /** + * Get a geocoding service instance, pass latitude and longitude to it, format the returned address, and return + * the address to the UI thread. + */ + @Override + protected String doInBackground(Location... params) { + /* + * Get a new geocoding service instance, set for localized addresses. This example uses + * android.location.Geocoder, but other geocoders that conform to address standards + * can also be used. + */ + Geocoder geocoder = new Geocoder(localContext, Locale.getDefault()); + + // Get the current location from the input parameter list + Location location = params[0]; + + // Create a list to contain the result address + List

addresses = null; + + // Try to get an address for the current location. Catch IO or network problems. + try { + + /* + * Call the synchronous getFromLocation() method with the latitude and + * longitude of the current location. Return at most 1 address. + */ + addresses = geocoder.getFromLocation(location.getLatitude(), + location.getLongitude(), 1 + ); + + // Catch network or other I/O problems. + } catch (IOException exception1) { + + // Log an error and return an error message + Log.e(TAG, getString(R.string.IO_Exception_getFromLocation)); + + // print the stack trace + exception1.printStackTrace(); + + // Return an error message + return (getString(R.string.IO_Exception_getFromLocation)); + + // Catch incorrect latitude or longitude values + } catch (IllegalArgumentException exception2) { + + // Construct a message containing the invalid arguments + String errorString = getString( + R.string.illegal_argument_exception, + location.getLatitude(), + location.getLongitude() + ); + // Log the error and print the stack trace + Log.e(TAG, errorString); + exception2.printStackTrace(); + + // + return errorString; + } + // If the reverse geocode returned an address + if (addresses != null && addresses.size() > 0) { + + // Get the first address + Address address = addresses.get(0); + + // Format the first line of address + String addressText = getString(R.string.address_output_string, + + // If there's a street address, add it + address.getMaxAddressLineIndex() > 0 ? + address.getAddressLine(0) : "", + + // Locality is usually a city + address.getLocality(), + + // The country of the address + address.getCountryName() + ); + + // Return the text + return addressText; + + // If there aren't any addresses, post a message + } else { + return getString(R.string.no_address_found); + } + } + + /** + * A method that's called once doInBackground() completes. Set the text of the UI element that displays the + * address. This method runs on the UI thread. + */ + @Override + protected void onPostExecute(String address) { + + // Turn off the progress bar + mActivityIndicator.setVisibility(View.GONE); + + // Set the address in the UI + mAddress.setText(address); + } + } + + /** + * Show a dialog returned by Google Play services for the connection error code + * + * @param errorCode An error code returned from onConnectionFailed + */ + private void showErrorDialog(int errorCode) { + + // Get the error dialog from Google Play services + Dialog errorDialog = GooglePlayServicesUtil.getErrorDialog( + errorCode, + this, + LocationUtils.CONNECTION_FAILURE_RESOLUTION_REQUEST); + + // If Google Play services can provide an error dialog + if (errorDialog != null) { + + // Create a new DialogFragment in which to show the error dialog + ErrorDialogFragment errorFragment = new ErrorDialogFragment(); + + // Set the dialog in the DialogFragment + errorFragment.setDialog(errorDialog); + + // Show the error dialog in the DialogFragment + errorFragment.show(getSupportFragmentManager(), TAG); + } + } + + /** + * Define a DialogFragment to display the error dialog generated in showErrorDialog. + */ + public static class ErrorDialogFragment extends DialogFragment { + + // Global field to contain the error dialog + private Dialog mDialog; + + /** + * Default constructor. Sets the dialog field to null + */ + public ErrorDialogFragment() { + super(); + mDialog = null; + } + + /** + * Set the dialog to display + * + * @param dialog An error dialog + */ + public void setDialog(Dialog dialog) { + mDialog = dialog; + } + + /* + * This method must return a Dialog to the DialogFragment. + */ + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + return mDialog; + } + } +} diff --git a/res/drawable-hdpi/ic_launcher.png b/src/main/res/drawable-hdpi/ic_launcher.png similarity index 100% rename from res/drawable-hdpi/ic_launcher.png rename to src/main/res/drawable-hdpi/ic_launcher.png diff --git a/res/drawable-mdpi/ic_launcher.png b/src/main/res/drawable-mdpi/ic_launcher.png similarity index 100% rename from res/drawable-mdpi/ic_launcher.png rename to src/main/res/drawable-mdpi/ic_launcher.png diff --git a/res/drawable-xhdpi/ic_launcher.png b/src/main/res/drawable-xhdpi/ic_launcher.png similarity index 100% rename from res/drawable-xhdpi/ic_launcher.png rename to src/main/res/drawable-xhdpi/ic_launcher.png diff --git a/res/drawable-xxhdpi/ic_launcher.png b/src/main/res/drawable-xxhdpi/ic_launcher.png similarity index 100% rename from res/drawable-xxhdpi/ic_launcher.png rename to src/main/res/drawable-xxhdpi/ic_launcher.png diff --git a/res/layout/activity_main.xml b/src/main/res/layout/activity_main.xml similarity index 100% rename from res/layout/activity_main.xml rename to src/main/res/layout/activity_main.xml diff --git a/res/values-sw600dp/dimens.xml b/src/main/res/values-sw600dp/dimens.xml similarity index 100% rename from res/values-sw600dp/dimens.xml rename to src/main/res/values-sw600dp/dimens.xml diff --git a/res/values-sw720dp-land/dimens.xml b/src/main/res/values-sw720dp-land/dimens.xml similarity index 100% rename from res/values-sw720dp-land/dimens.xml rename to src/main/res/values-sw720dp-land/dimens.xml diff --git a/res/values-v11/styles.xml b/src/main/res/values-v11/styles.xml similarity index 100% rename from res/values-v11/styles.xml rename to src/main/res/values-v11/styles.xml diff --git a/res/values-v14/styles.xml b/src/main/res/values-v14/styles.xml similarity index 100% rename from res/values-v14/styles.xml rename to src/main/res/values-v14/styles.xml diff --git a/res/values/dimens.xml b/src/main/res/values/dimens.xml similarity index 100% rename from res/values/dimens.xml rename to src/main/res/values/dimens.xml diff --git a/res/values/lib_strings.xml b/src/main/res/values/lib_strings.xml similarity index 100% rename from res/values/lib_strings.xml rename to src/main/res/values/lib_strings.xml diff --git a/res/values/strings.xml b/src/main/res/values/strings.xml similarity index 100% rename from res/values/strings.xml rename to src/main/res/values/strings.xml diff --git a/res/values/styles.xml b/src/main/res/values/styles.xml similarity index 100% rename from res/values/styles.xml rename to src/main/res/values/styles.xml