package me.guillaumin.android.osmtracker.activity;
import me.guillaumin.android.osmtracker.OSMTracker;
import me.guillaumin.android.osmtracker.R;
import me.guillaumin.android.osmtracker.db.TrackContentProvider;
import me.guillaumin.android.osmtracker.db.TrackContentProvider.Schema;
import me.guillaumin.android.osmtracker.db.model.Track;
import me.guillaumin.android.osmtracker.db.model.Track.OSMVisibility;
import me.guillaumin.android.osmtracker.gpx.ExportToTempFileTask;
import me.guillaumin.android.osmtracker.osm.OpenStreetMapConstants;
import me.guillaumin.android.osmtracker.osm.RetrieveAccessTokenTask;
import me.guillaumin.android.osmtracker.osm.RetrieveRequestTokenTask;
import me.guillaumin.android.osmtracker.osm.UploadToOpenStreetMapTask;
import oauth.signpost.OAuth;
import oauth.signpost.commonshttp.CommonsHttpOAuthConsumer;
import oauth.signpost.commonshttp.CommonsHttpOAuthProvider;
import android.content.ContentUris;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.Toast;
/**
* <p>Uploads a track on OSM using the API and
* OAuth authentication.</p>
*
* <p>This activity may be called twice during a single
* upload cycle: First to start the upload, then a second
* time when the user has authenticated using the browser.</p>
*
* @author Nicolas Guillaumin
*/
public class OpenStreetMapUpload extends TrackDetailEditor {
private static final String TAG = OpenStreetMapUpload.class.getSimpleName();
/** URL that the browser will call once the user is authenticated */
private static final String OAUTH_CALLBACK_URL = "osmtracker://osm-upload/oath-completed/?"+Schema.COL_TRACK_ID+"=";
private static final CommonsHttpOAuthProvider oAuthProvider = new CommonsHttpOAuthProvider(
OpenStreetMapConstants.OAuth.Urls.REQUEST_TOKEN_URL,
OpenStreetMapConstants.OAuth.Urls.ACCESS_TOKEN_URL,
OpenStreetMapConstants.OAuth.Urls.AUTHORIZE_TOKEN_URL);
private static final CommonsHttpOAuthConsumer oAuthConsumer = new CommonsHttpOAuthConsumer(
OpenStreetMapConstants.OAuth.CONSUMER_KEY,
OpenStreetMapConstants.OAuth.CONSUMER_SECRET);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState, R.layout.osm_upload, getTrackId());
fieldsMandatory = true;
final Button btnOk = (Button) findViewById(R.id.osm_upload_btn_ok);
btnOk.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (save()) {
startUpload();
}
}
});
final Button btnCancel = (Button) findViewById(R.id.osm_upload_btn_cancel);
btnCancel.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
// Do not show soft keyboard by default
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
}
/**
* Gets the track ID we were called with, either from the
* intent extras if we were started by OSMTracker, or in the
* URI if we are returning from the browser.
* @return
*/
private long getTrackId() {
if (getIntent().getExtras() != null && getIntent().getExtras().containsKey(Schema.COL_TRACK_ID)) {
return getIntent().getExtras().getLong(Schema.COL_TRACK_ID);
} else if (getIntent().getData().toString().startsWith(OAUTH_CALLBACK_URL)) {
return Long.parseLong(getIntent().getData().getQueryParameter(Schema.COL_TRACK_ID));
} else {
throw new IllegalArgumentException("Missing Track ID");
}
}
/**
* Will be called as well when we come back from the browser
* after user authentication.
*/
@Override
protected void onResume() {
super.onResume();
Cursor cursor = managedQuery(
ContentUris.withAppendedId(TrackContentProvider.CONTENT_URI_TRACK, trackId),
null, null, null, null);
if (! cursor.moveToFirst()) {
// This shouldn't occur, it's here just in case.
// So, don't make each language translate/localize it.
Toast.makeText(this, "Track ID not found.", Toast.LENGTH_SHORT).show();
finish();
return; // <--- Early return ---
}
bindTrack(Track.build(trackId, cursor, getContentResolver(), false));
Uri uri = getIntent().getData();
Log.d(TAG, "URI: " + uri);
if (uri != null && uri.toString().startsWith(OAUTH_CALLBACK_URL)) {
// User is returning from authentication
String verifier = uri.getQueryParameter(OAuth.OAUTH_VERIFIER);
new RetrieveAccessTokenTask(this, oAuthProvider, oAuthConsumer, verifier).execute();
}
}
/**
* Either starts uploading directly if we are authenticated against OpenStreetMap,
* or ask the user to authenticate via the browser.
*/
private void startUpload() {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
if ( prefs.contains(OSMTracker.Preferences.KEY_OSM_OAUTH_TOKEN)
&& prefs.contains(OSMTracker.Preferences.KEY_OSM_OAUTH_SECRET)) {
// Re-use saved token
oAuthConsumer.setTokenWithSecret(
prefs.getString(OSMTracker.Preferences.KEY_OSM_OAUTH_TOKEN, ""),
prefs.getString(OSMTracker.Preferences.KEY_OSM_OAUTH_SECRET, ""));
uploadToOsm();
} else {
// Open browser and request token
new RetrieveRequestTokenTask(this, oAuthProvider, oAuthConsumer, OAUTH_CALLBACK_URL+trackId).execute();
}
}
/**
* Exports track on disk then upload to OSM.
*/
public void uploadToOsm() {
new ExportToTempFileTask(this, trackId) {
@Override
protected void executionCompleted() {
new UploadToOpenStreetMapTask(OpenStreetMapUpload.this, trackId, oAuthConsumer, this.getTmpFile(),
this.getFilename(), etDescription.getText().toString(), etTags.getText().toString(),
OSMVisibility.fromPosition(OpenStreetMapUpload.this.spVisibility.getSelectedItemPosition()))
.execute();
}
}.execute();
}
}