Skip to content

Commit c184fea

Browse files
Implemented notes upload using osmapi
1 parent 0da828d commit c184fea

File tree

4 files changed

+386
-0
lines changed

4 files changed

+386
-0
lines changed

app/build.gradle

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,11 @@ dependencies {
9595
implementation 'androidx.constraintlayout:constraintlayout:2.2.0'
9696
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
9797
implementation 'androidx.appcompat:appcompat:1.7.0'
98+
implementation ('de.westnordost:osmapi-notes:3.1'){
99+
// Already included in Android
100+
exclude group: 'net.sf.kxml', module: 'kxml2'
101+
exclude group: 'xmlpull', module: 'xmlpull'
102+
}
98103

99104
// Required -- JUnit 4 framework
100105
testImplementation 'junit:junit:4.13.2'

app/src/main/AndroidManifest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@
108108
</intent-filter>
109109
</activity>
110110
<activity android:name=".activity.AvailableLayouts" />
111+
<activity android:name=".activity.OpenStreetMapNotesUpload"/>
111112

112113
<service
113114
android:name=".service.gps.GPSLogger"
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
package net.osmtracker.activity;
2+
3+
import android.Manifest;
4+
import android.app.Activity;
5+
import android.content.ContentUris;
6+
import android.content.Context;
7+
import android.content.Intent;
8+
import android.content.SharedPreferences;
9+
import android.content.pm.PackageManager;
10+
import android.database.Cursor;
11+
import android.location.Location;
12+
import android.location.LocationManager;
13+
import android.net.Uri;
14+
import android.os.Bundle;
15+
import android.preference.PreferenceManager;
16+
import android.util.Log;
17+
import android.view.LayoutInflater;
18+
import android.view.View;
19+
import android.view.View.OnClickListener;
20+
import android.view.WindowManager;
21+
import android.widget.Button;
22+
import android.widget.EditText;
23+
import android.widget.TextView;
24+
import android.widget.Toast;
25+
26+
import androidx.core.app.ActivityCompat;
27+
28+
import net.openid.appauth.AuthorizationException;
29+
import net.openid.appauth.AuthorizationRequest;
30+
import net.openid.appauth.AuthorizationResponse;
31+
import net.openid.appauth.AuthorizationService;
32+
import net.openid.appauth.AuthorizationServiceConfiguration;
33+
import net.openid.appauth.ResponseTypeValues;
34+
import net.openid.appauth.TokenResponse;
35+
import net.osmtracker.OSMTracker;
36+
import net.osmtracker.R;
37+
import net.osmtracker.db.TrackContentProvider;
38+
import net.osmtracker.db.model.Track;
39+
import net.osmtracker.gpx.ExportToTempFileTask;
40+
import net.osmtracker.osm.OpenStreetMapConstants;
41+
import net.osmtracker.osm.UploadToOpenStreetMapNotesTask;
42+
import net.osmtracker.osm.UploadToOpenStreetMapTask;
43+
44+
/**
45+
* <p>Uploads a note on OSM using the API and
46+
* OAuth authentication.</p>
47+
*
48+
* <p>This activity may be called twice during a single
49+
* upload cycle: First to start the upload, then a second
50+
* time when the user has authenticated using the browser.</p>
51+
*
52+
* @author Most of the code was made by Nicolas Guillaumin, adapted by Jose Andrés Vargas Serrano
53+
*/
54+
public class OpenStreetMapNotesUpload extends Activity {
55+
56+
private static final String TAG = OpenStreetMapNotesUpload.class.getSimpleName();
57+
58+
/** URL that the browser will call once the user is authenticated */
59+
public final static String OAUTH2_CALLBACK_URL = "osmtracker://osm-upload/oath2-completed/";
60+
public final static int RC_AUTH = 7;
61+
62+
private AuthorizationService authService;
63+
64+
@Override
65+
protected void onCreate(Bundle savedInstanceState) {
66+
super.onCreate(savedInstanceState);
67+
LayoutInflater inflater = this.getLayoutInflater();
68+
69+
// Inflate the note upload layout
70+
final View uploatNoteView = inflater.inflate(R.layout.osm_note_upload, null);
71+
final TextView noteContent = uploatNoteView.findViewById(R.id.wplist_item_name);
72+
73+
// Getting the text passed from the setting it to the UI
74+
String noteText = OpenStreetMapNotesUpload.this.getIntent().getStringExtra("noteContent");
75+
noteContent.setText(noteText);
76+
77+
setContentView(uploatNoteView);
78+
setTitle(R.string.osm_note_upload);
79+
final Button btnOk = (Button) findViewById(R.id.osm_note_upload_button_ok);
80+
btnOk.setOnClickListener(new OnClickListener() {
81+
@Override
82+
public void onClick(View v) {
83+
startUpload();
84+
}
85+
});
86+
final Button btnCancel = (Button) findViewById(R.id.osm_note_upload_button_cancel);
87+
btnCancel.setOnClickListener(new OnClickListener() {
88+
@Override
89+
public void onClick(View v) {
90+
finish();
91+
}
92+
});
93+
94+
}
95+
96+
97+
/**
98+
* Either starts uploading directly if we are authenticated against OpenStreetMap,
99+
* or ask the user to authenticate via the browser.
100+
*/
101+
private void startUpload() {
102+
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
103+
if ( prefs.contains(OSMTracker.Preferences.KEY_OSM_OAUTH2_ACCESSTOKEN) ) {
104+
// Re-use saved token
105+
uploadToOsm(prefs.getString(OSMTracker.Preferences.KEY_OSM_OAUTH2_ACCESSTOKEN, ""));
106+
} else {
107+
// Open browser and request token
108+
requestOsmAuth();
109+
}
110+
}
111+
/*
112+
* Init Authorization request workflow.
113+
*/
114+
public void requestOsmAuth() {
115+
// Authorization service configuration
116+
AuthorizationServiceConfiguration serviceConfig =
117+
new AuthorizationServiceConfiguration(
118+
Uri.parse(OpenStreetMapConstants.OAuth2.Urls.AUTHORIZATION_ENDPOINT),
119+
Uri.parse(OpenStreetMapConstants.OAuth2.Urls.TOKEN_ENDPOINT));
120+
121+
// Obtaining an authorization code
122+
Uri redirectURI = Uri.parse(OAUTH2_CALLBACK_URL);
123+
AuthorizationRequest.Builder authRequestBuilder =
124+
new AuthorizationRequest.Builder(
125+
serviceConfig, OpenStreetMapConstants.OAuth2.CLIENT_ID,
126+
ResponseTypeValues.CODE, redirectURI);
127+
AuthorizationRequest authRequest = authRequestBuilder
128+
.setScope(OpenStreetMapConstants.OAuth2.SCOPE)
129+
.build();
130+
131+
// Start activity.
132+
authService = new AuthorizationService(this);
133+
Intent authIntent = authService.getAuthorizationRequestIntent(authRequest);
134+
startActivityForResult(authIntent, RC_AUTH); //when done onActivityResult will be called.
135+
}
136+
137+
138+
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
139+
super.onActivityResult(requestCode, resultCode, data);
140+
// User is returning from authentication
141+
if (requestCode == RC_AUTH) {
142+
// Handling the authorization response
143+
AuthorizationResponse resp = AuthorizationResponse.fromIntent(data);
144+
AuthorizationException ex = AuthorizationException.fromIntent(data);
145+
// ... process the response or exception ...
146+
if (ex != null) {
147+
Log.e(TAG, "Authorization Error. Exception received from server.");
148+
Log.e(TAG, ex.getMessage());
149+
} else if (resp == null) {
150+
Log.e(TAG, "Authorization Error. Null response from server.");
151+
} else {
152+
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
153+
154+
//Exchanging the authorization code
155+
authService.performTokenRequest(
156+
resp.createTokenExchangeRequest(),
157+
new AuthorizationService.TokenResponseCallback() {
158+
@Override public void onTokenRequestCompleted(
159+
TokenResponse resp, AuthorizationException ex) {
160+
if (resp != null) {
161+
// exchange succeeded
162+
SharedPreferences.Editor editor = prefs.edit();
163+
editor.putString(OSMTracker.Preferences.KEY_OSM_OAUTH2_ACCESSTOKEN, resp.accessToken);
164+
editor.apply();
165+
//continue with the note Upload.
166+
uploadToOsm(resp.accessToken);
167+
} else {
168+
// authorization failed, check ex for more details
169+
Log.e(TAG, "OAuth failed.");
170+
}
171+
}
172+
});
173+
}
174+
} else {
175+
Log.e(TAG, "Unexpected requestCode:" + requestCode + ".");
176+
}
177+
}
178+
179+
/**
180+
* Uploads notes to OSM.
181+
*/
182+
public void uploadToOsm(String accessToken) {
183+
Bundle bundle = OpenStreetMapNotesUpload.this.getIntent().getExtras();
184+
if (bundle != null){
185+
String noteContent = bundle.getString("noteContent");
186+
double latitude = bundle.getDouble("latitude");
187+
double longitude = bundle.getDouble("longitude");
188+
new UploadToOpenStreetMapNotesTask(OpenStreetMapNotesUpload.this, accessToken, noteContent,
189+
latitude, longitude).execute();
190+
}
191+
}
192+
193+
194+
}

0 commit comments

Comments
 (0)