/*------------------------------------------------------------------------------ ** Ident: Delivery Center Java ** Author: rene ** Copyright: (c) Jul 9, 2011 Sogeti Nederland B.V. All Rights Reserved. **------------------------------------------------------------------------------ ** Sogeti Nederland B.V. | No part of this file may be reproduced ** Distributed Software Engineering | or transmitted in any form or by any ** Lange Dreef 17 | means, electronic or mechanical, for the ** 4131 NJ Vianen | purpose, without the express written ** The Netherlands | permission of the copyright holder. *------------------------------------------------------------------------------ * * This file is part of OpenGPSTracker. * * OpenGPSTracker is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * OpenGPSTracker is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenGPSTracker. If not, see <http://www.gnu.org/licenses/>. * */ package nl.sogeti.android.gpstracker.actions.tasks; import java.io.File; import java.io.IOException; import java.io.InputStream; import nl.sogeti.android.gpstracker.R; import nl.sogeti.android.gpstracker.actions.ShareTrack; import nl.sogeti.android.gpstracker.actions.utils.ProgressListener; import nl.sogeti.android.gpstracker.db.GPStracking; import nl.sogeti.android.gpstracker.db.GPStracking.Media; import nl.sogeti.android.gpstracker.db.GPStracking.MetaData; import nl.sogeti.android.gpstracker.oauth.PrepareRequestTokenActivity; import nl.sogeti.android.gpstracker.util.Constants; import nl.sogeti.android.gpstracker.viewer.LoggerMap; import oauth.signpost.commonshttp.CommonsHttpOAuthConsumer; import oauth.signpost.exception.OAuthCommunicationException; import oauth.signpost.exception.OAuthExpectationFailedException; import oauth.signpost.exception.OAuthMessageSignerException; import org.apache.ogt.http.HttpEntity; import org.apache.ogt.http.HttpException; import org.apache.ogt.http.HttpResponse; import org.apache.ogt.http.client.methods.HttpPost; import org.apache.ogt.http.entity.mime.HttpMultipartMode; import org.apache.ogt.http.entity.mime.MultipartEntity; import org.apache.ogt.http.entity.mime.content.FileBody; import org.apache.ogt.http.entity.mime.content.StringBody; import org.apache.ogt.http.impl.client.DefaultHttpClient; import org.apache.ogt.http.util.EntityUtils; import android.app.Activity; import android.content.ContentResolver; import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.database.Cursor; import android.net.Uri; import android.preference.PreferenceManager; import android.util.Log; import android.widget.Toast; /** * ???? * * @version $Id:$ * @author rene (c) Jul 9, 2011, Sogeti B.V. */ public class OsmSharing extends GpxCreator { public static final String OAUTH_TOKEN = "openstreetmap_oauth_token"; public static final String OAUTH_TOKEN_SECRET = "openstreetmap_oauth_secret"; private static final String TAG = "OGT.OsmSharing"; public static final String OSM_FILENAME = "OSM_Trace"; private String responseText; private Uri mFileUri; public OsmSharing(Activity context, Uri trackUri, boolean attachments, ProgressListener listener) { super(context, trackUri, OSM_FILENAME, attachments, listener); } public void resumeOsmSharing(Uri fileUri, Uri trackUri) { mFileUri = fileUri; mTrackUri = trackUri; execute(); } @Override protected Uri doInBackground(Void... params) { if( mFileUri == null ) { mFileUri = super.doInBackground(params); } sendToOsm(mFileUri, mTrackUri); return mFileUri; } @Override protected void onPostExecute(Uri resultFilename) { super.onPostExecute(resultFilename); CharSequence text = mContext.getString(R.string.osm_success) + responseText; Toast toast = Toast.makeText(mContext, text, Toast.LENGTH_LONG); toast.show(); } /** * POST a (GPX) file to the 0.6 API of the OpenStreetMap.org website * publishing this track to the public. * * @param fileUri * @param contentType */ private void sendToOsm(final Uri fileUri, final Uri trackUri) { CommonsHttpOAuthConsumer consumer = osmConnectionSetup(); if( consumer == null ) { requestOpenstreetmapOauthToken(); handleError(mContext.getString(R.string.osm_task), null, mContext.getString(R.string.osmauth_message)); } String visibility = PreferenceManager.getDefaultSharedPreferences(mContext).getString(Constants.OSM_VISIBILITY, "trackable"); File gpxFile = new File(fileUri.getEncodedPath()); String url = mContext.getString(R.string.osm_post_url); DefaultHttpClient httpclient = new DefaultHttpClient(); HttpResponse response = null; int statusCode = 0; Cursor metaData = null; String sources = null; HttpEntity responseEntity = null; try { metaData = mContext.getContentResolver().query(Uri.withAppendedPath(trackUri, "metadata"), new String[] { MetaData.VALUE }, MetaData.KEY + " = ? ", new String[] { Constants.DATASOURCES_KEY }, null); if (metaData.moveToFirst()) { sources = metaData.getString(0); } if (sources != null && sources.contains(LoggerMap.GOOGLE_PROVIDER)) { throw new IOException("Unable to upload track with materials derived from Google Maps."); } // The POST to the create node HttpPost method = new HttpPost(url); String tags = mContext.getString(R.string.osm_tag) + " " +queryForNotes(); // Build the multipart body with the upload data MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE); entity.addPart("file", new FileBody(gpxFile)); entity.addPart("description", new StringBody( ShareTrack.queryForTrackName(mContext.getContentResolver(), mTrackUri))); entity.addPart("tags", new StringBody(tags)); entity.addPart("visibility", new StringBody(visibility)); method.setEntity(entity); // Execute the POST to OpenStreetMap consumer.sign(method); response = httpclient.execute(method); // Read the response statusCode = response.getStatusLine().getStatusCode(); responseEntity = response.getEntity(); InputStream stream = responseEntity.getContent(); responseText = XmlCreator.convertStreamToString(stream); } catch (OAuthMessageSignerException e) { Editor editor = PreferenceManager.getDefaultSharedPreferences(mContext).edit(); editor.remove(OAUTH_TOKEN); editor.remove(OAUTH_TOKEN_SECRET); editor.commit(); responseText = mContext.getString(R.string.osm_failed) + e.getLocalizedMessage(); handleError(mContext.getString(R.string.osm_task), e, responseText); } catch (OAuthExpectationFailedException e) { Editor editor = PreferenceManager.getDefaultSharedPreferences(mContext).edit(); editor.remove(OAUTH_TOKEN); editor.remove(OAUTH_TOKEN_SECRET); editor.commit(); responseText = mContext.getString(R.string.osm_failed) + e.getLocalizedMessage(); handleError(mContext.getString(R.string.osm_task), e, responseText); } catch (OAuthCommunicationException e) { Editor editor = PreferenceManager.getDefaultSharedPreferences(mContext).edit(); editor.remove(OAUTH_TOKEN); editor.remove(OAUTH_TOKEN_SECRET); editor.commit(); responseText = mContext.getString(R.string.osm_failed) + e.getLocalizedMessage(); handleError(mContext.getString(R.string.osm_task), e, responseText); } catch (IOException e) { responseText = mContext.getString(R.string.osm_failed) + e.getLocalizedMessage(); handleError(mContext.getString(R.string.osm_task), e, responseText); } finally { if (responseEntity != null) { try { EntityUtils.consume(responseEntity); } catch (IOException e) { Log.e(TAG, "Failed to close the content stream", e); } } if (metaData != null) { metaData.close(); } } if (statusCode != 200) { Log.e(TAG, "Failed to upload to error code " + statusCode + " " + responseText); String text = mContext.getString(R.string.osm_failed) + responseText; if( statusCode == 401 ) { Editor editor = PreferenceManager.getDefaultSharedPreferences(mContext).edit(); editor.remove(OAUTH_TOKEN); editor.remove(OAUTH_TOKEN_SECRET); editor.commit(); } handleError(mContext.getString(R.string.osm_task), new HttpException("Unexpected status reported by OSM"), text); } } private CommonsHttpOAuthConsumer osmConnectionSetup() { final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext); String token = prefs.getString(OAUTH_TOKEN, ""); String secret = prefs.getString(OAUTH_TOKEN_SECRET, ""); boolean mAuthorized = !"".equals(token) && !"".equals(secret); CommonsHttpOAuthConsumer consumer = null; if (mAuthorized) { consumer = new CommonsHttpOAuthConsumer(mContext.getString(R.string.OSM_CONSUMER_KEY), mContext.getString(R.string.OSM_CONSUMER_SECRET)); consumer.setTokenWithSecret(token, secret); } return consumer; } private String queryForNotes() { StringBuilder tags = new StringBuilder(); ContentResolver resolver = mContext.getContentResolver(); Cursor mediaCursor = null; Uri mediaUri = Uri.withAppendedPath(mTrackUri, "media"); try { mediaCursor = resolver.query(mediaUri, new String[] { Media.URI }, null, null, null); if (mediaCursor.moveToFirst()) { do { Uri noteUri = Uri.parse(mediaCursor.getString(0)); if (noteUri.getScheme().equals("content") && noteUri.getAuthority().equals(GPStracking.AUTHORITY + ".string")) { String tag = noteUri.getLastPathSegment().trim(); if (!tag.contains(" ")) { if (tags.length() > 0) { tags.append(" "); } tags.append(tag); } } } while (mediaCursor.moveToNext()); } } finally { if (mediaCursor != null) { mediaCursor.close(); } } return tags.toString(); } public void requestOpenstreetmapOauthToken() { Intent intent = new Intent(mContext.getApplicationContext(), PrepareRequestTokenActivity.class); intent.putExtra(PrepareRequestTokenActivity.OAUTH_TOKEN_PREF, OAUTH_TOKEN); intent.putExtra(PrepareRequestTokenActivity.OAUTH_TOKEN_SECRET_PREF, OAUTH_TOKEN_SECRET); intent.putExtra(PrepareRequestTokenActivity.CONSUMER_KEY, mContext.getString(R.string.OSM_CONSUMER_KEY)); intent.putExtra(PrepareRequestTokenActivity.CONSUMER_SECRET, mContext.getString(R.string.OSM_CONSUMER_SECRET)); intent.putExtra(PrepareRequestTokenActivity.REQUEST_URL, Constants.OSM_REQUEST_URL); intent.putExtra(PrepareRequestTokenActivity.ACCESS_URL, Constants.OSM_ACCESS_URL); intent.putExtra(PrepareRequestTokenActivity.AUTHORIZE_URL, Constants.OSM_AUTHORIZE_URL); mContext.startActivity(intent); } }