mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 12:23:58 +01:00
Added Commons AccountManager (Authentication Provider!)
Also updated version of java-mwapi to support cookie based auth
This commit is contained in:
parent
d59b1700c8
commit
802e6aa9ed
8 changed files with 227 additions and 38 deletions
|
|
@ -8,6 +8,9 @@
|
|||
android:targetSdkVersion="15" />
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"/>
|
||||
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
|
||||
<uses-permission android:name="android.permission.ACCOUNT_MANAGER"/>
|
||||
|
||||
<application
|
||||
android:name=".CommonsApplication"
|
||||
|
|
@ -15,7 +18,7 @@
|
|||
android:label="@string/app_name"
|
||||
android:theme="@style/Theme.Commons" >
|
||||
<activity
|
||||
android:name=".LoginActivity"
|
||||
android:name=".auth.LoginActivity"
|
||||
android:label="@string/title_activity_login"
|
||||
android:theme="@style/NoTitle" >
|
||||
</activity>
|
||||
|
|
@ -24,11 +27,27 @@
|
|||
android:label="@string/title_activity_share" >
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
|
||||
<data android:mimeType="image/*" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<service android:name="UploadService"></service>
|
||||
|
||||
<service android:name="UploadService" >
|
||||
</service>
|
||||
<service
|
||||
android:name=".auth.WikiAccountAuthenticatorService"
|
||||
android:exported="true"
|
||||
android:process=":auth" >
|
||||
<intent-filter>
|
||||
<action android:name="android.accounts.AccountAuthenticator" />
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="android.accounts.AccountAuthenticator"
|
||||
android:resource="@xml/authenticator" />
|
||||
</service>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
Binary file not shown.
|
|
@ -10,11 +10,9 @@ import org.apache.http.params.CoreProtocolPNames;
|
|||
public class CommonsApplication extends Application {
|
||||
|
||||
private MWApi api;
|
||||
public static final String API_URL = "http://test.wikipedia.org/w/api.php";
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
// TODO Auto-generated method stub
|
||||
super.onCreate();
|
||||
public static MWApi createMWApi() {
|
||||
DefaultHttpClient client = new DefaultHttpClient();
|
||||
// Because WMF servers support only HTTP/1.0. Biggest difference that
|
||||
// this makes is support for Chunked Transfer Encoding.
|
||||
|
|
@ -22,7 +20,14 @@ public class CommonsApplication extends Application {
|
|||
// throws up.
|
||||
client.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION,
|
||||
HttpVersion.HTTP_1_0);
|
||||
api = new MWApi("http://test.wikipedia.org/w/api.php", client);
|
||||
return new MWApi(API_URL, client);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
// TODO Auto-generated method stub
|
||||
super.onCreate();
|
||||
api = createMWApi();
|
||||
}
|
||||
|
||||
public MWApi getApi() {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import java.io.*;
|
|||
|
||||
import org.mediawiki.api.ApiResult;
|
||||
import org.mediawiki.api.MWApi;
|
||||
import org.wikimedia.commons.auth.LoginActivity;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import android.content.*;
|
|||
import android.os.*;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.RemoteViews;
|
||||
import android.widget.Toast;
|
||||
import android.net.*;
|
||||
|
|
@ -83,10 +84,6 @@ public class UploadService extends IntentService {
|
|||
length = this.getContentResolver().openAssetFileDescriptor(mediaUri, "r").getLength();
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IOException e) {
|
||||
//I'm hoping there are no streams that can be opened and read only once.
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
notificationView = new RemoteViews(getPackageName(), R.layout.layout_upload_progress);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,20 @@
|
|||
package org.wikimedia.commons;
|
||||
package org.wikimedia.commons.auth;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.wikimedia.commons.CommonsApplication;
|
||||
import org.wikimedia.commons.R;
|
||||
import org.wikimedia.commons.R.id;
|
||||
import org.wikimedia.commons.R.layout;
|
||||
import org.wikimedia.commons.R.menu;
|
||||
import org.wikimedia.commons.R.string;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountAuthenticatorActivity;
|
||||
import android.accounts.AccountAuthenticatorResponse;
|
||||
import android.accounts.AccountManager;
|
||||
import android.app.Activity;
|
||||
import android.app.ProgressDialog;
|
||||
import android.view.*;
|
||||
|
|
@ -12,7 +23,9 @@ import android.widget.EditText;
|
|||
import android.widget.Toast;
|
||||
import android.support.v4.app.NavUtils;
|
||||
|
||||
public class LoginActivity extends Activity {
|
||||
public class LoginActivity extends AccountAuthenticatorActivity {
|
||||
|
||||
public static final String PARAM_USERNAME = "org.wikimedia.commons.login.username";
|
||||
|
||||
private CommonsApplication app;
|
||||
|
||||
|
|
@ -24,13 +37,29 @@ public class LoginActivity extends Activity {
|
|||
|
||||
Activity context;
|
||||
ProgressDialog dialog;
|
||||
String username;
|
||||
String password;
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(String result) {
|
||||
super.onPostExecute(result);
|
||||
if(result.equals("Success")) {
|
||||
if (result.equals("Success")) {
|
||||
dialog.cancel();
|
||||
Toast successToast = Toast.makeText(context, R.string.login_success, Toast.LENGTH_SHORT);
|
||||
successToast.show();
|
||||
Account account = new Account(username, WikiAccountAuthenticator.COMMONS_ACCOUNT_TYPE);
|
||||
boolean accountCreated = AccountManager.get(context).addAccountExplicitly(account, password, null);
|
||||
|
||||
Bundle extras = context.getIntent().getExtras();
|
||||
if (extras != null) {
|
||||
if (accountCreated) { // Pass the new account back to the account manager
|
||||
AccountAuthenticatorResponse response = extras.getParcelable(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE);
|
||||
Bundle authResult = new Bundle();
|
||||
authResult.putString(AccountManager.KEY_ACCOUNT_NAME, username);
|
||||
authResult.putString(AccountManager.KEY_ACCOUNT_TYPE, WikiAccountAuthenticator.COMMONS_ACCOUNT_TYPE);
|
||||
response.onResult(authResult);
|
||||
}
|
||||
}
|
||||
context.finish();
|
||||
} else {
|
||||
Toast failureToast = Toast.makeText(context, R.string.login_failed, Toast.LENGTH_LONG);
|
||||
|
|
@ -55,8 +84,8 @@ public class LoginActivity extends Activity {
|
|||
|
||||
@Override
|
||||
protected String doInBackground(String... params) {
|
||||
String username = params[0];
|
||||
String password = params[1];
|
||||
username = params[0];
|
||||
password = params[1];
|
||||
try {
|
||||
return app.getApi().login(username, password);
|
||||
} catch (IOException e) {
|
||||
|
|
@ -70,11 +99,11 @@ public class LoginActivity extends Activity {
|
|||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
app = (CommonsApplication)this.getApplicationContext();
|
||||
app = (CommonsApplication) this.getApplicationContext();
|
||||
setContentView(R.layout.activity_login);
|
||||
loginButton = (Button)findViewById(R.id.loginButton);
|
||||
usernameEdit = (EditText)findViewById(R.id.loginUsername);
|
||||
passwordEdit = (EditText)findViewById(R.id.loginPassword);
|
||||
loginButton = (Button) findViewById(R.id.loginButton);
|
||||
usernameEdit = (EditText) findViewById(R.id.loginUsername);
|
||||
passwordEdit = (EditText) findViewById(R.id.loginPassword);
|
||||
final Activity that = this;
|
||||
loginButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
|
|
@ -94,7 +123,6 @@ public class LoginActivity extends Activity {
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
|
|
@ -105,7 +133,4 @@ public class LoginActivity extends Activity {
|
|||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
119
src/org/wikimedia/commons/auth/WikiAccountAuthenticator.java
Normal file
119
src/org/wikimedia/commons/auth/WikiAccountAuthenticator.java
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
package org.wikimedia.commons.auth;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.mediawiki.api.ApiResult;
|
||||
import org.mediawiki.api.MWApi;
|
||||
import org.wikimedia.commons.CommonsApplication;
|
||||
|
||||
import android.accounts.AbstractAccountAuthenticator;
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountAuthenticatorResponse;
|
||||
import android.accounts.AccountManager;
|
||||
import android.accounts.NetworkErrorException;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
public class WikiAccountAuthenticator extends AbstractAccountAuthenticator {
|
||||
|
||||
public static final String COMMONS_ACCOUNT_TYPE = "org.wikimedia.commons";
|
||||
private Context context;
|
||||
public WikiAccountAuthenticator(Context context) {
|
||||
super(context);
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle addAccount(AccountAuthenticatorResponse response, String accountType, String authTokenType, String[] requiredFeatures, Bundle options) throws NetworkErrorException {
|
||||
// TODO Auto-generated method stub
|
||||
final Intent intent = new Intent(context, LoginActivity.class);
|
||||
intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
|
||||
final Bundle bundle = new Bundle();
|
||||
bundle.putParcelable(AccountManager.KEY_INTENT, intent);
|
||||
return bundle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account, Bundle options) throws NetworkErrorException {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
private String getAuthCookie(String username, String password) throws IOException {
|
||||
MWApi api = ((CommonsApplication)context.getApplicationContext()).createMWApi();
|
||||
String result = api.login(username, password);
|
||||
if(result.equals("Success")) {
|
||||
return api.getAuthCookie();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException {
|
||||
// If the caller requested an authToken type we don't support, then
|
||||
// return an error
|
||||
if (!authTokenType.equals(COMMONS_ACCOUNT_TYPE)) {
|
||||
final Bundle result = new Bundle();
|
||||
result.putString(AccountManager.KEY_ERROR_MESSAGE, "invalid authTokenType");
|
||||
return result;
|
||||
}
|
||||
|
||||
// Extract the username and password from the Account Manager, and ask
|
||||
// the server for an appropriate AuthToken.
|
||||
final AccountManager am = AccountManager.get(context);
|
||||
final String password = am.getPassword(account);
|
||||
if (password != null) {
|
||||
String authCookie;
|
||||
try {
|
||||
authCookie = getAuthCookie(account.name, password);
|
||||
} catch (IOException e) {
|
||||
// Network error!
|
||||
throw new NetworkErrorException(e);
|
||||
}
|
||||
if (authCookie != null) {
|
||||
final Bundle result = new Bundle();
|
||||
result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
|
||||
result.putString(AccountManager.KEY_ACCOUNT_TYPE, COMMONS_ACCOUNT_TYPE);
|
||||
result.putString(AccountManager.KEY_AUTHTOKEN, authCookie);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// If we get here, then we couldn't access the user's password - so we
|
||||
// need to re-prompt them for their credentials. We do that by creating
|
||||
// an intent to display our AuthenticatorActivity panel.
|
||||
final Intent intent = new Intent(context, LoginActivity.class);
|
||||
intent.putExtra(LoginActivity.PARAM_USERNAME, account.name);
|
||||
intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
|
||||
final Bundle bundle = new Bundle();
|
||||
bundle.putParcelable(AccountManager.KEY_INTENT, intent);
|
||||
return bundle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthTokenLabel(String authTokenType) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle hasFeatures(AccountAuthenticatorResponse response, Account account, String[] features) throws NetworkErrorException {
|
||||
final Bundle result = new Bundle();
|
||||
result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, false);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package org.wikimedia.commons.auth;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
|
||||
public class WikiAccountAuthenticatorService extends Service{
|
||||
|
||||
private static WikiAccountAuthenticator wikiAccountAuthenticator = null;
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
if (!intent.getAction().equals(android.accounts.AccountManager.ACTION_AUTHENTICATOR_INTENT)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if(wikiAccountAuthenticator == null) {
|
||||
wikiAccountAuthenticator = new WikiAccountAuthenticator(this);
|
||||
}
|
||||
return wikiAccountAuthenticator.getIBinder();
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue