commit
049bc9dbbc
@ -8,9 +8,11 @@
|
|||||||
android:minSdkVersion="14"
|
android:minSdkVersion="14"
|
||||||
android:targetSdkVersion="17" />
|
android:targetSdkVersion="17" />
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
|
||||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
|
||||||
|
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
|
6
mobile/res/layout/dialog_progressbar.xml
Normal file
6
mobile/res/layout/dialog_progressbar.xml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<ProgressBar xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/progressBarLoading"
|
||||||
|
style="?android:attr/progressBarStyleLarge"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"/>
|
@ -55,4 +55,6 @@
|
|||||||
<string name="menu_faction">Faction</string>
|
<string name="menu_faction">Faction</string>
|
||||||
<string name="menu_info">Info</string>
|
<string name="menu_info">Info</string>
|
||||||
<string name="menu_debug">Debug</string>
|
<string name="menu_debug">Debug</string>
|
||||||
|
<string name="choose_account_to_login">Choose account to login</string>
|
||||||
|
<string name="login_failed">Login failed.</string>
|
||||||
</resources>
|
</resources>
|
189
mobile/src/com/cradle/iitc_mobile/IITC_DeviceAccountLogin.java
Normal file
189
mobile/src/com/cradle/iitc_mobile/IITC_DeviceAccountLogin.java
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
package com.cradle.iitc_mobile;
|
||||||
|
|
||||||
|
import android.accounts.Account;
|
||||||
|
import android.accounts.AccountManager;
|
||||||
|
import android.accounts.AccountManagerCallback;
|
||||||
|
import android.accounts.AccountManagerFuture;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.webkit.WebView;
|
||||||
|
import android.webkit.WebViewClient;
|
||||||
|
import android.widget.BaseAdapter;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this class manages automatic login using the Google account stored on the device
|
||||||
|
*/
|
||||||
|
public class IITC_DeviceAccountLogin implements AccountManagerCallback<Bundle> {
|
||||||
|
/**
|
||||||
|
* Adapter to show available accounts in a ListView. Accounts are read from mAccounts
|
||||||
|
*/
|
||||||
|
private class AccountAdapter extends BaseAdapter {
|
||||||
|
@Override
|
||||||
|
public int getCount() {
|
||||||
|
return mAccounts.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Account getItem(int position) {
|
||||||
|
return mAccounts[position];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getItemId(int position) {
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View getView(int position, View convertView, ViewGroup parent) {
|
||||||
|
LayoutInflater inflater = mActivity.getLayoutInflater();
|
||||||
|
View v = inflater.inflate(android.R.layout.simple_list_item_1, parent, false);
|
||||||
|
|
||||||
|
TextView tv = (TextView) v.findViewById(android.R.id.text1);
|
||||||
|
tv.setText(mAccounts[position].name);
|
||||||
|
|
||||||
|
return tv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Account mAccount;
|
||||||
|
private AccountAdapter mAccountAdapter;
|
||||||
|
private AccountManager mAccountManager;
|
||||||
|
private Account[] mAccounts;
|
||||||
|
private IITC_Mobile mActivity;
|
||||||
|
private String mAuthToken;
|
||||||
|
private AlertDialog mProgressbar;
|
||||||
|
private WebView mWebView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This listener is invoked when an item in the account list is selected. (It is also used when the 'cancel' button
|
||||||
|
* is clicked, (in which case `index` is <0)
|
||||||
|
*/
|
||||||
|
private DialogInterface.OnClickListener onClickListener = new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int index) {
|
||||||
|
if (index >= 0 && index < mAccounts.length) {
|
||||||
|
mAccount = mAccounts[index];
|
||||||
|
startAuthentication();
|
||||||
|
}
|
||||||
|
dialog.cancel();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public IITC_DeviceAccountLogin(IITC_Mobile activity, WebView webView, WebViewClient webViewClient) {
|
||||||
|
mActivity = activity;
|
||||||
|
mWebView = webView;
|
||||||
|
mAccountManager = AccountManager.get(activity);
|
||||||
|
mAccountAdapter = new AccountAdapter();
|
||||||
|
|
||||||
|
// dialog that serves as a progress bar overlay
|
||||||
|
mProgressbar = new AlertDialog.Builder(mActivity)
|
||||||
|
.setCancelable(false)
|
||||||
|
.setView(mActivity.getLayoutInflater().inflate(R.layout.dialog_progressbar, null))
|
||||||
|
.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* display all available accounts to the user
|
||||||
|
*/
|
||||||
|
private void displayAccountList() {
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(mActivity)
|
||||||
|
.setTitle(R.string.choose_account_to_login)
|
||||||
|
.setSingleChoiceItems(mAccountAdapter, 0, onClickListener)
|
||||||
|
.setNegativeButton(android.R.string.cancel, onClickListener);
|
||||||
|
|
||||||
|
AlertDialog dialog = builder.create();
|
||||||
|
dialog.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* called when something failed. Shows a toast message. Classic login is still available
|
||||||
|
*/
|
||||||
|
private void onLoginFailed() {
|
||||||
|
Toast.makeText(mActivity, R.string.login_failed, Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* called to start authenticating using AccountManager.
|
||||||
|
*
|
||||||
|
* After a token is created, AccountManager will call the run() method.
|
||||||
|
*/
|
||||||
|
private void startAuthentication() {
|
||||||
|
mProgressbar.show();
|
||||||
|
|
||||||
|
mAccountManager.getAuthToken(mAccount, mAuthToken, null, mActivity, this, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* called by IITC_Mobile when the authentication activity has finished.
|
||||||
|
*/
|
||||||
|
public void onActivityResult(int resultCode, Intent data) {
|
||||||
|
if (resultCode == Activity.RESULT_OK)
|
||||||
|
// authentication activity succeeded, request token again
|
||||||
|
startAuthentication();
|
||||||
|
else
|
||||||
|
onLoginFailed();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* called by AccountManager
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void run(AccountManagerFuture<Bundle> value) {
|
||||||
|
mProgressbar.hide();
|
||||||
|
|
||||||
|
try {
|
||||||
|
Intent launch = (Intent) value.getResult().get(AccountManager.KEY_INTENT);
|
||||||
|
if (launch != null) {
|
||||||
|
// There is a reason we need to start the given activity if we want an authentication token.
|
||||||
|
// (Could be user confirmation or something else. Whatever, we have to start it)
|
||||||
|
// IITC_Mobile will call it using startActivityForResult
|
||||||
|
mActivity.startLoginActivity(launch);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String result = value.getResult().getString(AccountManager.KEY_AUTHTOKEN);
|
||||||
|
if (result != null) {
|
||||||
|
// authentication succeded, we can load the given url, which will redirect back to the intel map
|
||||||
|
mWebView.loadUrl(result);
|
||||||
|
mActivity.loginSucceded();
|
||||||
|
} else {
|
||||||
|
onLoginFailed();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
onLoginFailed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* start authentication
|
||||||
|
*
|
||||||
|
* if we already have a username (e.g. because the existing login has timed out), we can directly start
|
||||||
|
* authentication if an account with that username is found.
|
||||||
|
*/
|
||||||
|
public void startLogin(String realm, String accountName, String args) {
|
||||||
|
mAccounts = mAccountManager.getAccountsByType(realm);
|
||||||
|
mAccountAdapter.notifyDataSetChanged();
|
||||||
|
mAuthToken = "weblogin:" + args;
|
||||||
|
|
||||||
|
if (mAccounts.length == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Account account : mAccounts) {
|
||||||
|
if (account.name.equals(accountName)) {
|
||||||
|
mAccountManager.getAuthToken(account, mAuthToken, null, mActivity, this, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
displayAccountList();
|
||||||
|
}
|
||||||
|
}
|
@ -2,7 +2,13 @@ package com.cradle.iitc_mobile;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import com.cradle.iitc_mobile.R;
|
import android.app.ActionBar;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||||
|
import android.content.res.Configuration;
|
||||||
import android.location.Location;
|
import android.location.Location;
|
||||||
import android.location.LocationListener;
|
import android.location.LocationListener;
|
||||||
import android.location.LocationManager;
|
import android.location.LocationManager;
|
||||||
@ -13,21 +19,18 @@ import android.os.Bundle;
|
|||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.StrictMode;
|
import android.os.StrictMode;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.app.ActionBar;
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
|
||||||
import android.content.res.Configuration;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
|
import android.view.Window;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
|
import android.webkit.WebView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
public class IITC_Mobile extends Activity {
|
public class IITC_Mobile extends Activity {
|
||||||
|
|
||||||
|
private static final int REQUEST_LOGIN = 1;
|
||||||
|
|
||||||
private IITC_WebView iitc_view;
|
private IITC_WebView iitc_view;
|
||||||
private boolean back_button_pressed = false;
|
private boolean back_button_pressed = false;
|
||||||
private OnSharedPreferenceChangeListener listener;
|
private OnSharedPreferenceChangeListener listener;
|
||||||
@ -38,11 +41,15 @@ public class IITC_Mobile extends Activity {
|
|||||||
private boolean fullscreen_mode = false;
|
private boolean fullscreen_mode = false;
|
||||||
private boolean fullscreen_actionbar = false;
|
private boolean fullscreen_actionbar = false;
|
||||||
private ActionBar actionBar;
|
private ActionBar actionBar;
|
||||||
|
private IITC_DeviceAccountLogin mLogin;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
// enable progress bar above action bar
|
||||||
|
requestWindowFeature(Window.FEATURE_PROGRESS);
|
||||||
|
|
||||||
// TODO build an async task for url.openStream() in IITC_WebViewClient
|
// TODO build an async task for url.openStream() in IITC_WebViewClient
|
||||||
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
|
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
|
||||||
.permitAll().build();
|
.permitAll().build();
|
||||||
@ -354,4 +361,42 @@ public class IITC_Mobile extends Activity {
|
|||||||
public IITC_WebView getWebView() {
|
public IITC_WebView getWebView() {
|
||||||
return this.iitc_view;
|
return this.iitc_view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* It can occur that in order to authenticate, an external activity has to be launched. (This could for example be a
|
||||||
|
* confirmation dialog.)
|
||||||
|
*/
|
||||||
|
public void startLoginActivity(Intent launch) {
|
||||||
|
startActivityForResult(launch, REQUEST_LOGIN); // REQUEST_LOGIN is to recognize the result
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
|
switch (requestCode) {
|
||||||
|
case REQUEST_LOGIN :
|
||||||
|
// authentication activity has returned. mLogin will continue authentication
|
||||||
|
mLogin.onActivityResult(resultCode, data);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default :
|
||||||
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* called by IITC_WebViewClient when the Google login form is opened.
|
||||||
|
*/
|
||||||
|
public void onReceivedLoginRequest(IITC_WebViewClient client, WebView view,
|
||||||
|
String realm, String account, String args) {
|
||||||
|
mLogin = new IITC_DeviceAccountLogin(this, view, client);
|
||||||
|
mLogin.startLogin(realm, account, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* called after successful login
|
||||||
|
*/
|
||||||
|
public void loginSucceded() {
|
||||||
|
// garbage collection
|
||||||
|
mLogin = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package com.cradle.iitc_mobile;
|
|||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.annotation.TargetApi;
|
import android.annotation.TargetApi;
|
||||||
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
@ -39,14 +40,29 @@ public class IITC_WebView extends WebView {
|
|||||||
this.js_interface = new IITC_JSInterface(c);
|
this.js_interface = new IITC_JSInterface(c);
|
||||||
this.addJavascriptInterface(js_interface, "android");
|
this.addJavascriptInterface(js_interface, "android");
|
||||||
|
|
||||||
// our webchromeclient should share geolocation with the iitc script
|
|
||||||
// allow access by default
|
|
||||||
this.setWebChromeClient(new WebChromeClient() {
|
this.setWebChromeClient(new WebChromeClient() {
|
||||||
|
/**
|
||||||
|
* our webchromeclient should share geolocation with the iitc script
|
||||||
|
*
|
||||||
|
* allow access by default
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onGeolocationPermissionsShowPrompt(String origin,
|
public void onGeolocationPermissionsShowPrompt(String origin,
|
||||||
GeolocationPermissions.Callback callback) {
|
GeolocationPermissions.Callback callback) {
|
||||||
callback.invoke(origin, true, false);
|
callback.invoke(origin, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* display progress bar in activity
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onProgressChanged(WebView view, int newProgress) {
|
||||||
|
super.onProgressChanged(view, newProgress);
|
||||||
|
|
||||||
|
// maximum for newProgress is 100
|
||||||
|
// maximum for setProgress is 10,000
|
||||||
|
((Activity) getContext()).setProgress(newProgress * 100);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
webclient = new IITC_WebViewClient(c);
|
webclient = new IITC_WebViewClient(c);
|
||||||
|
@ -133,6 +133,14 @@ public class IITC_WebViewClient extends WebViewClient {
|
|||||||
handler.proceed();
|
handler.proceed();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this method is called automatically when the Google login form is opened.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onReceivedLoginRequest(WebView view, String realm, String account, String args) {
|
||||||
|
((IITC_Mobile) context).onReceivedLoginRequest(this, view, realm, account, args);
|
||||||
|
}
|
||||||
|
|
||||||
// plugins should be loaded after the main script is injected
|
// plugins should be loaded after the main script is injected
|
||||||
@Override
|
@Override
|
||||||
public void onPageFinished(WebView view, String url) {
|
public void onPageFinished(WebView view, String url) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user