diff --git a/app/.classpath b/app/.classpath index a0c1af6..f54935b 100644 --- a/app/.classpath +++ b/app/.classpath @@ -7,5 +7,7 @@ + + diff --git a/app/libs/signpost-commonshttp4-1.2.1.1.jar b/app/libs/signpost-commonshttp4-1.2.1.1.jar new file mode 100644 index 0000000..50e9838 Binary files /dev/null and b/app/libs/signpost-commonshttp4-1.2.1.1.jar differ diff --git a/app/libs/signpost-core-1.2.1.1.jar b/app/libs/signpost-core-1.2.1.1.jar new file mode 100644 index 0000000..59e7537 Binary files /dev/null and b/app/libs/signpost-core-1.2.1.1.jar differ diff --git a/app/res/values/settings.xml b/app/res/values/settings.xml index 0a40460..99b2438 100644 --- a/app/res/values/settings.xml +++ b/app/res/values/settings.xml @@ -12,6 +12,12 @@ setting_loggedin Log out Log in + setting_loggedin + + setting_oauth_consumer_key + setting_oauth_consumer_secret + setting_oauth_token + setting_oauth_token_secret Edit account Change profile picture @@ -22,4 +28,5 @@ setting_autoupload_tag autoupload + diff --git a/app/src/me/openphoto/android/app/GalleryActivity.java b/app/src/me/openphoto/android/app/GalleryActivity.java index 9cacfb3..9c1a1b9 100644 --- a/app/src/me/openphoto/android/app/GalleryActivity.java +++ b/app/src/me/openphoto/android/app/GalleryActivity.java @@ -9,7 +9,6 @@ import java.util.List; import me.openphoto.android.app.model.Photo; import me.openphoto.android.app.net.IOpenPhotoApi; -import me.openphoto.android.app.net.OpenPhotoApi; import me.openphoto.android.app.net.Paging; import me.openphoto.android.app.net.PhotosResponse; import me.openphoto.android.app.net.ReturnSize; @@ -82,8 +81,7 @@ public class GalleryActivity extends Activity implements OnItemClickListener { public PhotosEndlessAdapter(String tagFilter) { super(); - mOpenPhotoApi = OpenPhotoApi - .createInstance(Preferences.getServer(GalleryActivity.this)); + mOpenPhotoApi = Preferences.getApi(GalleryActivity.this); mTagFilter = new ArrayList(1); if (tagFilter != null) { mTagFilter.add(tagFilter); diff --git a/app/src/me/openphoto/android/app/MainActivity.java b/app/src/me/openphoto/android/app/MainActivity.java index ff062de..9d80242 100644 --- a/app/src/me/openphoto/android/app/MainActivity.java +++ b/app/src/me/openphoto/android/app/MainActivity.java @@ -8,7 +8,6 @@ import java.net.URL; import me.openphoto.android.app.model.Photo; import me.openphoto.android.app.net.IOpenPhotoApi; -import me.openphoto.android.app.net.OpenPhotoApi; import me.openphoto.android.app.net.Paging; import me.openphoto.android.app.net.ReturnSize; import me.openphoto.android.app.ui.widget.ActionBar; @@ -52,7 +51,7 @@ public class MainActivity extends Activity implements OnClickListener { mActionBar = (ActionBar) findViewById(R.id.actionbar); new LoadImageTask().execute(); - // Get refereneces to navigation buttons + // Get references to navigation buttons searchBtn = (ImageButton) findViewById(R.id.main_search_btn); cameraBtn = (ImageButton) findViewById(R.id.main_camera_btn); galleryBtn = (ImageButton) findViewById(R.id.main_gallery_btn); @@ -73,8 +72,7 @@ public class MainActivity extends Activity implements OnClickListener { @Override protected Bitmap doInBackground(Void... params) { - IOpenPhotoApi api = OpenPhotoApi - .createInstance(Preferences.getServer(MainActivity.this)); + IOpenPhotoApi api = Preferences.getApi(MainActivity.this); try { Photo photo = api.getPhotos(new ReturnSize(600, 600), null, new Paging(1, 1)) .getPhotos().get(0); diff --git a/app/src/me/openphoto/android/app/OAuthActivity.java b/app/src/me/openphoto/android/app/OAuthActivity.java index 8d63508..62fa769 100644 --- a/app/src/me/openphoto/android/app/OAuthActivity.java +++ b/app/src/me/openphoto/android/app/OAuthActivity.java @@ -1,28 +1,21 @@ package me.openphoto.android.app; -import java.net.URL; - -import me.openphoto.android.app.model.Photo; import me.openphoto.android.app.net.IOpenPhotoApi; -import me.openphoto.android.app.net.OpenPhotoApi; -import me.openphoto.android.app.net.Paging; -import me.openphoto.android.app.net.ReturnSize; import me.openphoto.android.app.ui.widget.ActionBar; +import oauth.signpost.OAuthConsumer; +import oauth.signpost.OAuthProvider; +import oauth.signpost.basic.DefaultOAuthConsumer; import android.app.Activity; import android.graphics.Bitmap; -import android.graphics.BitmapFactory; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.util.Log; -import android.view.View; -import android.webkit.CookieManager; import android.webkit.WebChromeClient; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; -import android.widget.ImageView; import android.widget.Toast; /** @@ -51,49 +44,59 @@ public class OAuthActivity extends Activity { setContentView(R.layout.oauth); mActionBar = (ActionBar) findViewById(R.id.actionbar); + // CookieSyncManager.createInstance(this); + // CookieSyncManager.getInstance().startSync(); + // CookieManager cookieManager = CookieManager.getInstance(); + // cookieManager.setAcceptCookie(true); + mWebView = (WebView) findViewById(R.id.webview); WebSettings webSettings = mWebView.getSettings(); - webSettings.setSavePassword(false); webSettings.setJavaScriptEnabled(true); + // webSettings.setSupportMultipleWindows(true); + // webSettings.setDatabaseEnabled(true); + // String databasePath = getApplicationContext().getDir("database", + // Context.MODE_PRIVATE) + // .getPath(); + // webSettings.setDatabasePath(databasePath); mWebView.setWebChromeClient(mWebChromeClient); mWebView.setWebViewClient(mWebViewClient); - CookieManager cookieManager = CookieManager.getInstance(); - cookieManager.setAcceptCookie(false); - - mOpenPhoto = OpenPhotoApi.createInstance(Preferences.getServer(this)); + mOpenPhoto = Preferences.getApi(this); String url = mOpenPhoto.getOAuthUrl(CALLBACK); mWebView.loadUrl(url); } private final WebChromeClient mWebChromeClient = new WebChromeClient() { - private boolean mIsLoading = false; @Override - public void onProgressChanged(WebView view, int newProgress) { - super.onProgressChanged(view, newProgress); - if (newProgress < 100) { - if (!mIsLoading) { - mIsLoading = true; - mActionBar.startLoading(); - } - } else if (mIsLoading) { - mActionBar.stopLoading(); - mIsLoading = false; - } + public void onConsoleMessage(String message, int lineNumber, String sourceID) { + Log.e(TAG, "Error: " + message); + super.onConsoleMessage(message, lineNumber, sourceID); } }; private final WebViewClient mWebViewClient = new WebViewClient() { + @Override + public void onPageFinished(WebView view, String url) { + super.onPageFinished(view, url); + mActionBar.stopLoading(); + } + + @Override + public void onPageStarted(WebView view, String url, Bitmap favicon) { + super.onPageStarted(view, url, favicon); + mActionBar.startLoading(); + } + @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { boolean result = true; if ((url != null) && (url.startsWith(CALLBACK))) { Uri uri = Uri.parse(url); - if (uri.getQueryParameter("token") != null) { - new PostTask().execute(); + if (uri.getQueryParameter("oauth_token") != null) { + new PostTask(uri).execute(); } else { Toast.makeText(OAuthActivity.this, "Error: " + uri.getQueryParameter("error"), Toast.LENGTH_LONG).show(); @@ -104,10 +107,15 @@ public class OAuthActivity extends Activity { } return result; } - }; - private class PostTask extends AsyncTask { + private class PostTask extends AsyncTask { + private final Uri mUri; + private OAuthConsumer mUsedConsumer; + + public PostTask(Uri uri) { + mUri = uri; + } @Override protected void onPreExecute() { @@ -116,34 +124,33 @@ public class OAuthActivity extends Activity { } @Override - protected Bitmap doInBackground(Void... params) { - IOpenPhotoApi api = OpenPhotoApi - .createInstance(Preferences.getServer(OAuthActivity.this)); + protected Boolean doInBackground(Void... params) { try { - Photo photo = api.getPhotos(new ReturnSize(600, 600), null, new Paging(1, 1)) - .getPhotos().get(0); - // TODO do not use base, make getPhotos actually use a - // returnSize parameter that should be used then. - return BitmapFactory.decodeStream(new URL(photo - .getUrl("600x600")).openStream()); + String oAuthConsumerKey = mUri.getQueryParameter("oauth_consumer_key"); + String oAuthConsumerSecret = mUri.getQueryParameter("oauth_consumer_secret"); + String oAuthToken = mUri.getQueryParameter("oauth_token"); + String oAuthTokenSecret = mUri.getQueryParameter("oauth_token_secret"); + String oAuthVerifier = mUri.getQueryParameter("oauth_verifier"); + + mUsedConsumer = new DefaultOAuthConsumer(oAuthConsumerKey, + oAuthConsumerSecret); + mUsedConsumer.setTokenWithSecret(oAuthToken, oAuthTokenSecret); + + OAuthProvider provider = Preferences.getOAuthProvider(OAuthActivity.this); + provider.retrieveAccessToken(mUsedConsumer, oAuthVerifier); + return true; } catch (Exception e) { - Log.w(TAG, "Error while getting image", e); - return null; + return false; } } @Override - protected void onPostExecute(Bitmap result) { + protected void onPostExecute(Boolean result) { mActionBar.stopLoading(); - if (result != null) { - ImageView image = (ImageView) findViewById(R.id.image); - image.setImageBitmap(result); - image.setVisibility(View.VISIBLE); - } else { - Toast.makeText(OAuthActivity.this, "Could not download image", - Toast.LENGTH_LONG).show(); + if (result.booleanValue()) { + Preferences.setLoginInformation(OAuthActivity.this, mUsedConsumer); + finish(); } } - } } diff --git a/app/src/me/openphoto/android/app/Preferences.java b/app/src/me/openphoto/android/app/Preferences.java index fbf24cd..184867e 100644 --- a/app/src/me/openphoto/android/app/Preferences.java +++ b/app/src/me/openphoto/android/app/Preferences.java @@ -1,7 +1,14 @@ package me.openphoto.android.app; +import me.openphoto.android.app.net.IOpenPhotoApi; +import me.openphoto.android.app.net.OpenPhotoApi; +import oauth.signpost.OAuthConsumer; +import oauth.signpost.OAuthProvider; +import oauth.signpost.basic.DefaultOAuthProvider; +import oauth.signpost.commonshttp.CommonsHttpOAuthConsumer; import android.content.Context; +import android.content.SharedPreferences; import android.preference.PreferenceManager; public class Preferences { @@ -31,10 +38,65 @@ public class Preferences { .getBoolean(context.getString(R.string.setting_account_loggedin_key), false); } - public static void setLoggedIn(Context context, boolean loggedIn) { + public static void logout(Context context) { PreferenceManager.getDefaultSharedPreferences(context) .edit() - .putBoolean(context.getString(R.string.setting_account_loggedin_key), loggedIn) + .putBoolean(context.getString(R.string.setting_account_loggedin_key), false) + .commit(); + context.getSharedPreferences("oauth", Context.MODE_PRIVATE) + .edit() + .clear() .commit(); } + + public static void setLoginInformation(Context context, OAuthConsumer consumer) { + PreferenceManager.getDefaultSharedPreferences(context) + .edit() + .putBoolean(context.getString(R.string.setting_account_loggedin_key), true) + .commit(); + context.getSharedPreferences("oauth", Context.MODE_PRIVATE) + .edit() + .putString(context.getString(R.string.setting_oauth_consumer_key), + consumer.getConsumerKey()) + .putString(context.getString(R.string.setting_oauth_consumer_secret), + consumer.getConsumerSecret()) + .putString(context.getString(R.string.setting_oauth_token), + consumer.getToken()) + .putString(context.getString(R.string.setting_oauth_token_secret), + consumer.getTokenSecret()) + .commit(); + } + + public static OAuthProvider getOAuthProvider(Context context) { + String serverUrl = getServer(context); + OAuthProvider provider = new DefaultOAuthProvider( + serverUrl + "/v1/oauth/token/request", + serverUrl + "/v1/oauth/token/access", + serverUrl + "/v1/oauth/authorize"); + provider.setOAuth10a(true); + return provider; + } + + public static IOpenPhotoApi getApi(Context context) { + IOpenPhotoApi api = OpenPhotoApi.createInstance(getServer(context)); + if (isLoggedIn(context)) { + api.setOAuthConsumer(getOAuthConsumer(context)); + } + return api; + } + + private static OAuthConsumer getOAuthConsumer(Context context) { + if (!isLoggedIn(context)) { + throw new IllegalAccessError("User is not logged in, so can not call this method!"); + } + + SharedPreferences prefs = context.getSharedPreferences("oauth", Context.MODE_PRIVATE); + OAuthConsumer consumer = new CommonsHttpOAuthConsumer( + prefs.getString(context.getString(R.string.setting_oauth_consumer_key), null), + prefs.getString(context.getString(R.string.setting_oauth_consumer_secret), null)); + consumer.setTokenWithSecret( + prefs.getString(context.getString(R.string.setting_oauth_token), null), + prefs.getString(context.getString(R.string.setting_oauth_token_secret), null)); + return consumer; + } } diff --git a/app/src/me/openphoto/android/app/SearchActivity.java b/app/src/me/openphoto/android/app/SearchActivity.java index d6f0eaa..c79d390 100644 --- a/app/src/me/openphoto/android/app/SearchActivity.java +++ b/app/src/me/openphoto/android/app/SearchActivity.java @@ -6,7 +6,6 @@ package me.openphoto.android.app; import me.openphoto.android.app.model.Tag; import me.openphoto.android.app.net.IOpenPhotoApi; -import me.openphoto.android.app.net.OpenPhotoApi; import me.openphoto.android.app.net.TagsResponse; import me.openphoto.android.app.ui.adapter.EndlessAdapter; import me.openphoto.android.app.ui.widget.ActionBar; @@ -88,8 +87,7 @@ public class SearchActivity extends Activity implements OnItemClickListener { public TagsAdapter() { super(); - mOpenPhotoApi = OpenPhotoApi - .createInstance(Preferences.getServer(SearchActivity.this)); + mOpenPhotoApi = Preferences.getApi(SearchActivity.this); } @Override diff --git a/app/src/me/openphoto/android/app/SettingsActivity.java b/app/src/me/openphoto/android/app/SettingsActivity.java index bcbab62..3c18b26 100644 --- a/app/src/me/openphoto/android/app/SettingsActivity.java +++ b/app/src/me/openphoto/android/app/SettingsActivity.java @@ -36,15 +36,23 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference @Override protected void onResume() { super.onResume(); + refreshLoginPreferenceTitle(); + } + + private void refreshLoginPreferenceTitle() { mLoginPreference.setTitle(Preferences.isLoggedIn(this) ? R.string.setting_account_loggedin_logout : R.string.setting_account_loggedin_login); } + // TODO when server is changed it should delete the login information + @Override public boolean onPreferenceClick(Preference preference) { if (getString(R.string.setting_account_loggedin_key).equals(preference.getKey())) { if (Preferences.isLoggedIn(this)) { - + // TODO show logout confirmation dialog + Preferences.logout(this); + refreshLoginPreferenceTitle(); } else { startActivity(new Intent(this, OAuthActivity.class)); } diff --git a/app/src/me/openphoto/android/app/UploadActivity.java b/app/src/me/openphoto/android/app/UploadActivity.java index aac1b26..ca0fba8 100644 --- a/app/src/me/openphoto/android/app/UploadActivity.java +++ b/app/src/me/openphoto/android/app/UploadActivity.java @@ -5,7 +5,6 @@ import java.io.File; import java.io.IOException; import java.util.Date; -import me.openphoto.android.app.net.OpenPhotoApi; import me.openphoto.android.app.net.UploadMetaData; import me.openphoto.android.app.net.UploadResponse; import me.openphoto.android.app.util.FileUtils; @@ -188,8 +187,7 @@ public class UploadActivity extends Activity implements OnClickListener { // TODO add private and effects aviary try { - return OpenPhotoApi.createInstance(Preferences.getServer(UploadActivity.this)) - .uploadPhoto(params[0], metaData); + return Preferences.getApi(UploadActivity.this).uploadPhoto(params[0], metaData); } catch (Exception e) { Log.e(TAG, "Error while uploading", e); } diff --git a/app/src/me/openphoto/android/app/ViewPhotoActivity.java b/app/src/me/openphoto/android/app/ViewPhotoActivity.java index 5b6657a..775df24 100644 --- a/app/src/me/openphoto/android/app/ViewPhotoActivity.java +++ b/app/src/me/openphoto/android/app/ViewPhotoActivity.java @@ -5,7 +5,6 @@ package me.openphoto.android.app; import me.openphoto.android.app.model.Photo; -import me.openphoto.android.app.net.OpenPhotoApi; import me.openphoto.android.app.net.PhotoResponse; import me.openphoto.android.app.net.ReturnSize; import me.openphoto.android.app.ui.lib.ImageStorage; @@ -86,9 +85,8 @@ public class ViewPhotoActivity extends Activity implements OnClickListener { @Override protected Photo doInBackground(Void... params) { try { - PhotoResponse response = OpenPhotoApi.createInstance( - Preferences.getServer(ViewPhotoActivity.this)).getPhoto(mPhoto.getId(), - new ReturnSize(1024, 1024)); + PhotoResponse response = Preferences.getApi(ViewPhotoActivity.this) + .getPhoto(mPhoto.getId(), new ReturnSize(1024, 1024)); return response.getPhoto(); } catch (Exception e) { return null; diff --git a/app/src/me/openphoto/android/app/net/ApiBase.java b/app/src/me/openphoto/android/app/net/ApiBase.java index a990628..a0c1e73 100644 --- a/app/src/me/openphoto/android/app/net/ApiBase.java +++ b/app/src/me/openphoto/android/app/net/ApiBase.java @@ -7,6 +7,7 @@ import java.io.UnsupportedEncodingException; import java.util.List; import me.openphoto.android.app.net.ApiRequest.Parameter; +import oauth.signpost.OAuthConsumer; import org.apache.http.HttpVersion; import org.apache.http.NameValuePair; @@ -33,6 +34,7 @@ import org.apache.http.protocol.HTTP; */ public class ApiBase { private final String mBaseUrl; + private OAuthConsumer mOAuthConsumer; /** * Instantiates a new ApiBase object. @@ -46,6 +48,16 @@ public class ApiBase { mBaseUrl = baseUrl; } + /** + * Sets the OAuthConsumer when the calls with the server need to be + * authenticated. + * + * @param oAuthConsumer + */ + public void setOAuthConsumer(OAuthConsumer oAuthConsumer) { + mOAuthConsumer = oAuthConsumer; + } + /** * Gets the base url of the used API. * @@ -70,7 +82,14 @@ public class ApiBase { HttpUriRequest httpRequest = createHttpRequest(request); httpRequest.getParams().setBooleanParameter("http.protocol.expect-continue", false); - + if (mOAuthConsumer != null) { + try { + mOAuthConsumer.sign(httpRequest); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } return new ApiResponse(httpClient.execute(httpRequest)); } diff --git a/app/src/me/openphoto/android/app/net/IOpenPhotoApi.java b/app/src/me/openphoto/android/app/net/IOpenPhotoApi.java index 1dc4c56..41758b2 100644 --- a/app/src/me/openphoto/android/app/net/IOpenPhotoApi.java +++ b/app/src/me/openphoto/android/app/net/IOpenPhotoApi.java @@ -5,11 +5,21 @@ import java.io.File; import java.io.IOException; import java.util.Collection; +import oauth.signpost.OAuthConsumer; + import org.apache.http.client.ClientProtocolException; import org.json.JSONException; public interface IOpenPhotoApi { + /** + * Sets the OAuthConsumer when the calls with the server need to be + * authenticated. + * + * @param oAuthConsumer + */ + void setOAuthConsumer(OAuthConsumer oAuthConsumer); + /** * @return tags which are used on the server * @throws ClientProtocolException diff --git a/app/src/me/openphoto/android/app/net/OpenPhotoApi.java b/app/src/me/openphoto/android/app/net/OpenPhotoApi.java index 6c56050..af39835 100644 --- a/app/src/me/openphoto/android/app/net/OpenPhotoApi.java +++ b/app/src/me/openphoto/android/app/net/OpenPhotoApi.java @@ -6,6 +6,8 @@ import java.io.IOException; import java.util.Collection; import java.util.Iterator; +import oauth.signpost.OAuthConsumer; + import org.apache.http.client.ClientProtocolException; import org.json.JSONException; import org.json.JSONObject; @@ -36,6 +38,21 @@ public class OpenPhotoApi extends ApiBase implements IOpenPhotoApi { } } + /* + * (non-Javadoc) + * @see + * me.openphoto.android.app.net.IOpenPhotoApi#setOAuthConsumer(oauth.signpost + * .OAuthConsumer) + */ + @Override + public void setOAuthConsumer(OAuthConsumer oAuthConsumer) { + super.setOAuthConsumer(oAuthConsumer); + } + + /* + * (non-Javadoc) + * @see me.openphoto.android.app.net.IOpenPhotoApi#getTags() + */ @Override public TagsResponse getTags() throws ClientProtocolException, IOException, IllegalStateException, JSONException { @@ -68,7 +85,7 @@ public class OpenPhotoApi extends ApiBase implements IOpenPhotoApi { */ @Override public String getOAuthUrl(String callback) { - return getBaseUrl() + "/v1/oauth/authorize"; + return getBaseUrl() + "/v1/oauth/authorize?mobile=1&oauth_callback=" + callback; } /* diff --git a/app/src/me/openphoto/android/app/service/UploaderService.java b/app/src/me/openphoto/android/app/service/UploaderService.java index cd866ed..16c1c6d 100644 --- a/app/src/me/openphoto/android/app/service/UploaderService.java +++ b/app/src/me/openphoto/android/app/service/UploaderService.java @@ -6,7 +6,6 @@ import java.util.Calendar; import me.openphoto.android.app.Preferences; import me.openphoto.android.app.net.IOpenPhotoApi; -import me.openphoto.android.app.net.OpenPhotoApi; import me.openphoto.android.app.net.UploadMetaData; import me.openphoto.android.app.provider.UploadsProvider; import me.openphoto.android.app.util.ImageUtils; @@ -31,7 +30,7 @@ public class UploaderService extends IntentService { @Override public void onCreate() { super.onCreate(); - mApi = OpenPhotoApi.createInstance(Preferences.getServer(this)); + mApi = Preferences.getApi(this); } @Override