Rework the account wizard using fragments.
--- a/AndroidManifest.xml Fri Aug 10 05:53:51 2012 +0200
+++ b/AndroidManifest.xml Sat Sep 22 03:21:58 2012 +0200
@@ -41,8 +41,8 @@
android:windowSoftInputMode="stateHidden" />
<activity android:name=".ui.AddContact" android:label="@string/AddCActTitle" />
<activity android:name=".ui.Subscription" android:label="@string/app_name" />
- <activity android:name=".ui.CreateAccount" android:label="@string/create_account_name" />
-
+ <activity android:name=".ui.wizard.CreateAccountActivity" android:label="@string/create_account_name" />
+
<activity android:name=".ui.ContactList" android:label="@string/contact_list_name"
android:launchMode="singleTask" />
--- a/project.properties Fri Aug 10 05:53:51 2012 +0200
+++ b/project.properties Sat Sep 22 03:21:58 2012 +0200
@@ -8,4 +8,4 @@
# project structure.
# Project target.
-target=android-8
+target=android-16
--- a/res/layout/create_account.xml Fri Aug 10 05:53:51 2012 +0200
+++ b/res/layout/create_account.xml Sat Sep 22 03:21:58 2012 +0200
@@ -1,11 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
-<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent"
- android:orientation="vertical">
- <LinearLayout android:orientation="vertical"
- android:layout_width="fill_parent" android:layout_height="fill_parent"
- android:padding="10dip">
- <TextView android:id="@+id/create_account_label_username"
+ android:orientation="vertical" >
+
+ <ScrollView android:layout_width="fill_parent" android:layout_height="0dip"
+ android:layout_weight="1" >
+ <LinearLayout android:layout_height="wrap_content" android:layout_width="fill_parent"
+ android:orientation="vertical" >
+ <ImageView android:id="@+id/logo"
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:layout_marginTop="15dp"
+ android:layout_marginBottom="30dp"
+ android:src="@drawable/logo"/>
+
+ <TextView
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:text="@string/create_account_username" style="@style/Label" />
<EditText android:id="@+id/create_account_username"
@@ -14,31 +22,42 @@
android:singleLine="true"
android:hint="beem@beem-project.com "
android:contentDescription="@string/create_account_username"/>
- <TextView android:id="@+id/create_account_label_password"
+ <TextView
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:text="@string/create_account_password" style="@style/Label" />
<EditText android:id="@+id/create_account_password"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:inputType="textPassword" android:imeOptions="actionNext"
- android:password="true" android:singleLine="true"
+ android:singleLine="true"
android:contentDescription="@string/create_account_password"/>
- <TextView android:id="@+id/create_account_label_confirm_password"
+ <TextView
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:text="@string/create_account_confirm_password" style="@style/Label" />
<EditText android:id="@+id/create_account_confirm_password"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:inputType="textPassword" android:imeOptions="actionNext"
- android:password="true" android:singleLine="true"
+ android:singleLine="true"
android:contentDescription="@string/create_account_confirm_password"/>
- <View android:layout_width="fill_parent" android:layout_height="wrap_content"
- android:layout_weight="1" android:layout_marginBottom="18dp" />
- <Button android:id="@+id/create_account_button"
- android:layout_width="fill_parent" android:layout_height="wrap_content"
- android:text="@string/button_create_account"
- android:layout_gravity="bottom" />
- <Button android:id="@+id/create_account_login_button"
- android:layout_width="fill_parent" android:layout_height="wrap_content"
- android:text="@string/button_create_login_account"
- android:layout_gravity="bottom" />
+
</LinearLayout>
-</ScrollView>
+ </ScrollView>
+
+ <RelativeLayout
+ android:gravity="right|center_vertical"
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent"
+ android:background="@drawable/bottombar" >
+ <Button
+ android:id="@+id/next"
+ android:text="@string/Continue"
+ android:minWidth="100dp"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:drawableRight="@drawable/button_indicator_next"
+ android:layout_alignParentRight="true"
+ android:layout_centerVertical="true"
+ android:enabled="false"
+ />
+ </RelativeLayout>
+
+</LinearLayout>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/res/layout/progress_dialog.xml Sat Sep 22 03:21:58 2012 +0200
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ >
+ <TextView android:id="@+id/title"
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"
+ android:text="TITLE" />
+ <View android:id="@+id/separator" android:layout_width="match_parent" android:layout_height="4dp"/>
+
+ <ProgressBar android:id="@+id/progress"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:layout_below="@+id/separator"
+ android:layout_alignParentLeft="true"
+ android:indeterminateOnly="true" android:indeterminate="true" android:indeterminateBehavior="repeat"/>
+ <TextView android:id="@+id/message"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:layout_below="@+id/separator"
+ android:layout_toRightOf="@id/progress"
+ android:text="TITLECONTENT"/>
+</RelativeLayout>
--- a/res/layout/wizard_account.xml Fri Aug 10 05:53:51 2012 +0200
+++ b/res/layout/wizard_account.xml Sat Sep 22 03:21:58 2012 +0200
@@ -1,52 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="fill_parent" android:layout_width="fill_parent"
android:orientation="vertical"
>
- <ScrollView android:layout_height="fill_parent" android:layout_width="fill_parent"
- android:layout_weight="1">
- <LinearLayout android:layout_height="wrap_content" android:layout_width="fill_parent"
+ <LinearLayout android:layout_height="fill_parent" android:layout_width="fill_parent"
android:orientation="vertical" >
<ImageView android:id="@+id/logo"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:layout_marginBottom="30dp"
android:src="@drawable/logo"/>
- <TextView
- android:layout_width="fill_parent" android:layout_height="wrap_content"
- android:text="@string/account_wizard_text1"
- android:textSize="18sp"
- android:paddingBottom="10dip"
- android:focusable="true" />
- <RadioGroup android:id="@+id/configure_group"
- android:layout_width="fill_parent" android:layout_height="wrap_content" >
- <RadioButton android:id="@+id/configure_account"
- android:layout_width="fill_parent" android:layout_height="wrap_content"
- android:text="@string/account_wizard_configure_account"/>
- <RadioButton android:id="@+id/create_account"
- android:layout_width="fill_parent" android:layout_height="wrap_content"
- android:text="@string/account_wizard_create_account"/>
- </RadioGroup>
+ <FrameLayout
+ android:layout_width="fill_parent" android:layout_height="fill_parent"
+ android:id="@+id/main_content" />
+
</LinearLayout>
- </ScrollView>
-
- <RelativeLayout
- android:layout_alignParentBottom="true"
- android:gravity="right|center_vertical"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent"
- android:background="@drawable/bottombar" >
- <Button
- android:id="@+id/next"
- android:text="@string/Continue"
- android:minWidth="100dp"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:drawableRight="@drawable/button_indicator_next"
- android:layout_alignParentRight="true"
- android:layout_centerVertical="true"
- android:enabled="false"
- />
- </RelativeLayout>
-
-</LinearLayout>
+</ScrollView>
--- a/res/layout/wizard_account_configure.xml Fri Aug 10 05:53:51 2012 +0200
+++ b/res/layout/wizard_account_configure.xml Sat Sep 22 03:21:58 2012 +0200
@@ -11,10 +11,31 @@
android:layout_marginTop="15dp"
android:layout_marginBottom="30dp"
android:src="@drawable/logo"/>
+ <LinearLayout android:id="@+id/account_layout"
+ android:layout_height="wrap_content" android:layout_width="fill_parent"
+ android:orientation="vertical" >
+ <TextView
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:text="@string/account_wizard_configure_text_1"
+ android:textSize="18sp"
+ android:paddingBottom="10dip" />
+ <Button
+ android:id="@+id/select_account_btn"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:text="@string/account_wizard_select_account_btn"
+ android:minWidth="100dp"
+ />
+ <TextView
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:text="@string/account_wizard_configure_text_2"
+ android:textSize="18sp"
+ android:paddingBottom="10dip" />
+ </LinearLayout>
<TextView
android:layout_width="fill_parent" android:layout_height="wrap_content"
- android:layout_alignParentTop="true"
- android:text="@string/account_wizard_configure_text"
+ android:text="@string/account_wizard_configure_text_3"
android:textSize="18sp"
android:paddingBottom="10dip" />
<TextView
@@ -34,6 +55,11 @@
android:inputType="textPassword" android:imeOptions="actionNext"
android:password="true" android:singleLine="true"
android:contentDescription="@string/Password"/>
+ <TextView android:id="@+id/error_label"
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:text="@string/account_wizard_connection_failed" style="@style/Label"
+ android:textColor="@color/red"
+ android:visibility="invisible" />
</LinearLayout>
</ScrollView>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/res/layout/wizard_account_main_fragment.xml Sat Sep 22 03:21:58 2012 +0200
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_height="fill_parent" android:layout_width="fill_parent"
+ android:orientation="vertical"
+ >
+ <ScrollView android:layout_height="0dip" android:layout_width="fill_parent"
+ android:layout_weight="1">
+ <LinearLayout android:layout_height="wrap_content" android:layout_width="fill_parent"
+ android:orientation="vertical" >
+ <ImageView android:id="@+id/logo"
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:layout_marginTop="15dp"
+ android:layout_marginBottom="30dp"
+ android:src="@drawable/logo"/>
+ <TextView
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:text="@string/account_wizard_text1"
+ android:textSize="18sp"
+ android:paddingBottom="10dip"
+ android:focusable="true" />
+ <RadioGroup android:id="@+id/configure_group"
+ android:layout_width="fill_parent" android:layout_height="wrap_content" >
+ <RadioButton android:id="@+id/configure_account"
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:text="@string/account_wizard_configure_account"/>
+ <RadioButton android:id="@+id/create_account"
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:text="@string/account_wizard_create_account"/>
+ </RadioGroup>
+ </LinearLayout>
+ </ScrollView>
+
+ <RelativeLayout
+ android:gravity="right|center_vertical"
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent"
+ android:background="@drawable/bottombar" >
+ <Button
+ android:id="@+id/next"
+ android:text="@string/Continue"
+ android:minWidth="100dp"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:drawableRight="@drawable/button_indicator_next"
+ android:layout_alignParentRight="true"
+ android:layout_centerVertical="true"
+ android:enabled="false"
+ />
+ </RelativeLayout>
+
+</LinearLayout>
--- a/res/values/strings.xml Fri Aug 10 05:53:51 2012 +0200
+++ b/res/values/strings.xml Sat Sep 22 03:21:58 2012 +0200
@@ -229,8 +229,13 @@
<!-- wizard activities -->
<string name="account_wizard_text1"><b>Welcome on BEEM.</b>\n\nYou have not configured an XMPP (Jabber) account yet.\nChoose one of the following options :</string>
- <string name="account_wizard_configure_text"><b>Please fill in the data for your existing account</b></string>
- <string name="account_wizard_configure_account">I already have an account I want to use</string>
+ <string name="account_wizard_configure_text_1">Use an account store on the device</string>
+ <string name="account_wizard_configure_text_2"><b>or</b></string>
+ <string name="account_wizard_configure_text_3">Please fill in the data for your existing account</string>
+ <string name="account_wizard_connection_failed"><b>Unable to authenticate your account. Please verify your credentials</b></string>
+ <string name="account_wizard_select_account_btn">Choose an account</string>
+
+ <string name="account_wizard_configure_account">I already have an account I want to use</string>
<string name="account_wizard_create_account">I want to register for a new account</string>
<!-- Create an account Activity -->
--- a/res/values/styles.xml Fri Aug 10 05:53:51 2012 +0200
+++ b/res/values/styles.xml Sat Sep 22 03:21:58 2012 +0200
@@ -1,10 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
-<resources>
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="Label">
<item name="android:textAppearance">?android:attr/textAppearanceMedium</item>
<item name="android:textStyle">bold</item>
<item name="android:capitalize">characters</item>
<item name="android:focusable">false</item>
+ <item name="android:inputType">textNoSuggestions</item>
</style>
<style name="CheckBoxLabel" parent="@style/Label">
<item name="android:enabled">true</item>
--- a/src/com/beem/project/beem/ui/CreateAccount.java Fri Aug 10 05:53:51 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,332 +0,0 @@
-/*
- BEEM is a videoconference application on the Android Platform.
-
- Copyright (C) 2009 by Frederic-Charles Barthelery,
- Jean-Manuel Da Silva,
- Nikita Kozlov,
- Philippe Lago,
- Jean Baptiste Vergely,
- Vincent Veronis.
-
- This file is part of BEEM.
-
- BEEM is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- BEEM is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with BEEM. If not, see <http://www.gnu.org/licenses/>.
-
- Please send bug reports with examples or suggestions to
- contact@beem-project.com or http://dev.beem-project.com/
-
- Epitech, hereby disclaims all copyright interest in the program "Beem"
- written by Frederic-Charles Barthelery,
- Jean-Manuel Da Silva,
- Nikita Kozlov,
- Philippe Lago,
- Jean Baptiste Vergely,
- Vincent Veronis.
-
- Nicolas Sadirac, November 26, 2009
- President of Epitech.
-
- Flavien Astraud, November 26, 2009
- Head of the EIP Laboratory.
-
-*/
-package com.beem.project.beem.ui;
-
-import java.util.regex.Pattern;
-
-import org.jivesoftware.smack.AccountManager;
-import org.jivesoftware.smack.ConnectionConfiguration;
-import org.jivesoftware.smack.XMPPConnection;
-import org.jivesoftware.smack.XMPPException;
-import org.jivesoftware.smack.proxy.ProxyInfo;
-import org.jivesoftware.smack.util.StringUtils;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.content.DialogInterface;
-import android.content.SharedPreferences;
-import android.os.Bundle;
-import android.preference.PreferenceManager;
-import android.view.View;
-import android.widget.Button;
-import android.widget.EditText;
-import android.widget.TextView;
-import android.widget.Toast;
-
-import com.beem.project.beem.BeemApplication;
-import com.beem.project.beem.R;
-
-/**
- * This class represents an activity which allows the user to create an account on the XMPP server saved in settings.
- * @author Jean-Manuel Da Silva <dasilvj at beem-project dot com>
- */
-public class CreateAccount extends Activity {
-
- private static final boolean DEFAULT_BOOLEAN_VALUE = false;
- private static final String DEFAULT_STRING_VALUE = "";
- private static final int DEFAULT_XMPP_PORT = 5222;
-
- private static final int NOTIFICATION_DURATION = Toast.LENGTH_SHORT;
-
- private SharedPreferences mSettings;
- private Button mCreateAccountButton;
-
- /**
- * Constructor.
- */
- public CreateAccount() {
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.create_account);
- initCreateAccountButton();
- mSettings = PreferenceManager.getDefaultSharedPreferences(this);
- }
-
- /**
- * Create an account on the XMPP server specified in settings.
- * @param username the username of the account.
- * @param password the password of the account.
- * @return true if the account was created successfully.
- */
- private boolean createAccount(String username, String password) {
- XMPPConnection xmppConnection = null;
- ConnectionConfiguration connectionConfiguration = null;
- ProxyInfo pi = getRegisteredProxy();
- if (pi != null) {
- connectionConfiguration = new ConnectionConfiguration(getXMPPServer(), getXMPPPort(), pi);
- } else {
- connectionConfiguration = new ConnectionConfiguration(getXMPPServer(), getXMPPPort());
- }
- if (getRegisteredXMPPTLSUse())
- connectionConfiguration.setSecurityMode(ConnectionConfiguration.SecurityMode.required);
-
- xmppConnection = new XMPPConnection(connectionConfiguration);
- try {
- xmppConnection.connect();
- AccountManager accountManager = new AccountManager(xmppConnection);
- accountManager.createAccount(username, password);
- Toast toast = Toast.makeText(getApplicationContext(), String.format(
- getString(R.string.create_account_successfull_after), username), NOTIFICATION_DURATION);
- toast.show();
- } catch (XMPPException e) {
- createErrorDialog(e.getMessage());
- return false;
- }
- xmppConnection.disconnect();
- return true;
- }
-
- /**
- * Create a dialog containing an error message.
- * @param errMsg the error message
- */
- private void createErrorDialog(String errMsg) {
- AlertDialog.Builder builder = new AlertDialog.Builder(this);
- builder.setTitle(R.string.create_account_err_dialog_title)
- .setMessage(errMsg)
- .setCancelable(false)
- .setIcon(android.R.drawable.ic_dialog_alert);
- builder.setNeutralButton(R.string.create_account_close_dialog_button, new DialogInterface.OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- dialog.cancel();
- }
- });
- AlertDialog settingsErrDialog = builder.create();
- settingsErrDialog.show();
- }
-
- /**
- * Retrive proxy informations from the preferences.
- * @return Registered proxy informations
- */
- private ProxyInfo getRegisteredProxy() {
- if (getRegisteredProxyUse()) {
- ProxyInfo proxyInfo = new ProxyInfo(getRegisteredProxyType(), getRegisteredProxyServer(),
- getRegisteredProxyPort(), getRegisteredProxyUsername(), getRegisteredProxyPassword());
- return proxyInfo;
- }
- return null;
- }
-
- /**
- * Retrieve proxy password from the preferences.
- * @return Registered proxy password
- */
- private String getRegisteredProxyPassword() {
- return mSettings.getString(BeemApplication.PROXY_PASSWORD_KEY, DEFAULT_STRING_VALUE);
- }
-
- /**
- * Retrieve proxy port from the preferences.
- * @return Registered proxy port
- */
- private int getRegisteredProxyPort() {
- return Integer.parseInt(mSettings.getString(BeemApplication.PROXY_PORT_KEY, DEFAULT_STRING_VALUE));
- }
-
- /**
- * Retrieve proxy server from the preferences.
- * @return Registered proxy server
- */
- private String getRegisteredProxyServer() {
- return mSettings.getString(BeemApplication.PROXY_SERVER_KEY, DEFAULT_STRING_VALUE);
- }
-
- /**
- * Retrieve proxy type from the preferences.
- * @return Registered proxy type
- */
- private ProxyInfo.ProxyType getRegisteredProxyType() {
- ProxyInfo.ProxyType result = ProxyInfo.ProxyType.NONE;
- if (mSettings.getBoolean(BeemApplication.PROXY_USE_KEY, false)) {
- String type = mSettings.getString(BeemApplication.PROXY_TYPE_KEY, "none");
- if ("HTTP".equals(type))
- result = ProxyInfo.ProxyType.HTTP;
- else if ("SOCKS4".equals(type))
- result = ProxyInfo.ProxyType.SOCKS4;
- else if ("SOCKS5".equals(type))
- result = ProxyInfo.ProxyType.SOCKS5;
- else
- result = ProxyInfo.ProxyType.NONE;
- }
- return result;
- }
-
- /**
- * Retrieve proxy use from the preferences.
- * @return Registered proxy use
- */
- private boolean getRegisteredProxyUse() {
- return mSettings.getBoolean(BeemApplication.PROXY_USE_KEY, DEFAULT_BOOLEAN_VALUE);
- }
-
- /**
- * Retrieve proxy username from the preferences.
- * @return Registered proxy username
- */
- private String getRegisteredProxyUsername() {
- return mSettings.getString(BeemApplication.PROXY_USERNAME_KEY, DEFAULT_STRING_VALUE);
- }
-
- /**
- * Retrieve xmpp port from the preferences.
- * @return Registered xmpp port
- */
- private int getXMPPPort() {
- int port = DEFAULT_XMPP_PORT;
- if (mSettings.getBoolean("settings_key_specific_server", false))
- port = Integer.parseInt(mSettings.getString("settings_key_xmpp_port", "5222"));
- return port;
- }
-
- /**
- * Retrieve xmpp server from the preferences.
- * @return Registered xmpp server
- */
- private String getXMPPServer() {
- TextView xmppServerTextView = (TextView) findViewById(R.id.create_account_username);
- String xmppServer = "";
- if (mSettings.getBoolean("settings_key_specific_server", false))
- xmppServer = mSettings.getString("settings_key_xmpp_server", "");
- else
- xmppServer = StringUtils.parseServer(xmppServerTextView.getText().toString());
- return xmppServer;
- }
-
- /**
- * Retrieve TLS use from the preferences.
- * @return Registered TLS use
- */
- private boolean getRegisteredXMPPTLSUse() {
- return mSettings.getBoolean("settings_key_xmpp_tls_use", DEFAULT_BOOLEAN_VALUE);
- }
-
- /**
- * Check if the fields password and confirm password match.
- * @return return true if password & confirm password fields match, else false
- */
- private boolean checkPasswords() {
- final String passwordFieldValue = ((EditText) findViewById(R.id.create_account_password)).getText().toString();
- final String passwordConfirmFielddValue = ((EditText) findViewById(R.id.create_account_confirm_password))
- .getText().toString();
-
- return passwordFieldValue.equals(passwordConfirmFielddValue) && !"".equals(passwordConfirmFielddValue);
- }
-
- /**
- * Check the format of the email.
- * @return true if the email is valid.
- */
- private boolean checkEmail() {
- String email = ((TextView) findViewById(R.id.create_account_username)).getText().toString();
- return Pattern.matches("[a-zA-Z0-9._%+-]+@(?:[a-zA-Z0-9-]+.)+[a-zA-Z]{2,4}", email);
- }
-
- /**
- * Initialize the "Create this account" button which allows the user to create an account.
- */
- private void initCreateAccountButton() {
- mCreateAccountButton = (Button) findViewById(R.id.create_account_button);
- mCreateAccountButton.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- String usernameFieldValue = ((EditText) findViewById(R.id.create_account_username)).getText()
- .toString();
- String passwordFieldValue = ((EditText) findViewById(R.id.create_account_password)).getText()
- .toString();
- String username = StringUtils.parseName(usernameFieldValue);
- if (!checkEmail())
- createErrorDialog(getString(R.string.create_account_err_username));
- else if (!checkPasswords())
- createErrorDialog(getString(R.string.create_account_err_passwords));
- else {
- if (createAccount(username, passwordFieldValue))
- finish();
- }
-
- }
- });
- Button createAccountLoginButton = (Button) findViewById(R.id.create_account_login_button);
- createAccountLoginButton.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- String usernameFieldValue = ((EditText) findViewById(R.id.create_account_username)).getText()
- .toString();
- String username = StringUtils.parseName(usernameFieldValue);
- String passwordFieldValue = ((EditText) findViewById(R.id.create_account_password)).getText()
- .toString();
- if (!checkEmail())
- createErrorDialog(getString(R.string.create_account_err_username));
- else if (!checkPasswords())
- createErrorDialog(getString(R.string.create_account_err_passwords));
- else {
- if (createAccount(username, passwordFieldValue)) {
- SharedPreferences.Editor settingsEditor = mSettings.edit();
- settingsEditor.putString(BeemApplication.ACCOUNT_USERNAME_KEY, usernameFieldValue);
- settingsEditor.putString(BeemApplication.ACCOUNT_PASSWORD_KEY, passwordFieldValue);
- settingsEditor.putBoolean("settings_key_gmail", false);
- settingsEditor.commit();
- finish();
- }
- }
- }
- });
- }
-}
--- a/src/com/beem/project/beem/ui/Settings.java Fri Aug 10 05:53:51 2012 +0200
+++ b/src/com/beem/project/beem/ui/Settings.java Sat Sep 22 03:21:58 2012 +0200
@@ -52,6 +52,7 @@
import android.view.MenuItem;
import com.beem.project.beem.R;
+import com.beem.project.beem.ui.wizard.Account;
/**
* This class represents an activity which allows the user to change his account or proxy parameters.
@@ -94,7 +95,7 @@
Intent i = null;
switch (item.getItemId()) {
case R.id.settings_menu_create_account:
- i = new Intent(this, CreateAccount.class);
+ i = new Intent(this, Account.class);
startActivity(i);
return true;
case R.id.settings_menu_privacy_lists:
--- a/src/com/beem/project/beem/ui/wizard/Account.java Fri Aug 10 05:53:51 2012 +0200
+++ b/src/com/beem/project/beem/ui/wizard/Account.java Sat Sep 22 03:21:58 2012 +0200
@@ -44,25 +44,28 @@
package com.beem.project.beem.ui.wizard;
import android.app.Activity;
-import android.content.Intent;
import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentTransaction;
+import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
+import android.view.ViewGroup;
import android.widget.Button;
import android.widget.RadioGroup;
-import com.beem.project.beem.ui.CreateAccount;
import com.beem.project.beem.R;
/**
* The first activity of an user friendly wizard to configure a XMPP account.
- *
- * @author Da Risk <darisk972@gmail.com>
*/
-public class Account extends Activity implements OnClickListener, RadioGroup.OnCheckedChangeListener {
+public class Account extends FragmentActivity {
- private RadioGroup mConfigureGroup;
- private Button mNextButton;
+ private static final String TAG = Account.class.getSimpleName();
+
+ private FragmentManager fragmentMgr;
/**
* Constructor.
@@ -73,35 +76,94 @@
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.wizard_account);
- mConfigureGroup = (RadioGroup) findViewById(R.id.configure_group);
- mConfigureGroup.setOnCheckedChangeListener(this);
- mNextButton = (Button) findViewById(R.id.next);
- mNextButton.setOnClickListener(this);
- }
+ fragmentMgr = getSupportFragmentManager();
+ if (savedInstanceState == null) {
+ FragmentTransaction t = fragmentMgr.beginTransaction();
+ t.add(android.R.id.content, MainFragment.newInstance(), "Main");
+ t.commit();
- @Override
- public void onClick(View v) {
- if (v == mNextButton) {
- int selectedid = mConfigureGroup.getCheckedRadioButtonId();
- Intent i = null;
- if (selectedid == R.id.configure_account) {
- i = new Intent(this, AccountConfigure.class);
- finish();
- } else if (selectedid == R.id.create_account) {
- i = new Intent(this, CreateAccount.class);
- }
- if (i != null) {
- startActivity(i);
- }
}
}
- @Override
- public void onCheckedChanged(RadioGroup group, int checkedId) {
- if (checkedId == -1)
- mNextButton.setEnabled(false);
- else
- mNextButton.setEnabled(true);
+ /**
+ * Callback called when the create account option is selected.
+ *
+ */
+ public void onCreateAccountSelected() {
+ Fragment f = CreateAccountFragment.newInstance();
+ FragmentTransaction transaction = fragmentMgr.beginTransaction();
+
+ transaction.replace(android.R.id.content, f, "createAccount");
+ transaction.addToBackStack(null);
+ transaction.commit();
+ }
+
+ /**
+ * Callback called when the configure account option is selected.
+ *
+ */
+ public void onConfigureAccountSelected() {
+ Fragment f = AccountConfigureFragment.newInstance();
+ FragmentTransaction transaction = fragmentMgr.beginTransaction();
+
+ transaction.replace(android.R.id.content, f, "configureAccount");
+ transaction.addToBackStack(null);
+ transaction.commit();
+ }
+
+ /**
+ * Main fragment of the wizard account activity.
+ */
+ public static class MainFragment extends Fragment implements OnClickListener, RadioGroup.OnCheckedChangeListener {
+ private RadioGroup mConfigureGroup;
+ private Button mNextButton;
+
+ private Account activity;
+
+ /**
+ * Create a new MainFragment.
+ *
+ * @return a MainFragment
+ */
+ static MainFragment newInstance() {
+ return new MainFragment();
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ View v = inflater.inflate(R.layout.wizard_account_main_fragment, container, false);
+ mNextButton = (Button) v.findViewById(R.id.next);
+ mNextButton.setOnClickListener(this);
+ mConfigureGroup = (RadioGroup) v.findViewById(R.id.configure_group);
+ mConfigureGroup.setOnCheckedChangeListener(this);
+ return v;
+ }
+
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ this.activity = (Account) activity;
+ }
+
+ @Override
+ public void onClick(View v) {
+ if (v == mNextButton) {
+ int selectedid = mConfigureGroup.getCheckedRadioButtonId();
+ if (selectedid == R.id.configure_account) {
+ activity.onConfigureAccountSelected();
+ } else if (selectedid == R.id.create_account) {
+ activity.onCreateAccountSelected();
+ }
+ }
+ }
+
+ @Override
+ public void onCheckedChanged(RadioGroup group, int checkedId) {
+ if (checkedId == -1)
+ mNextButton.setEnabled(false);
+ else
+ mNextButton.setEnabled(true);
+ }
+
}
}
--- a/src/com/beem/project/beem/ui/wizard/AccountConfigure.java Fri Aug 10 05:53:51 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,231 +0,0 @@
-/*
- BEEM is a videoconference application on the Android Platform.
-
- Copyright (C) 2009 by Frederic-Charles Barthelery,
- Jean-Manuel Da Silva,
- Nikita Kozlov,
- Philippe Lago,
- Jean Baptiste Vergely,
- Vincent Veronis.
-
- This file is part of BEEM.
-
- BEEM is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- BEEM is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with BEEM. If not, see <http://www.gnu.org/licenses/>.
-
- Please send bug reports with examples or suggestions to
- contact@beem-project.com or http://dev.beem-project.com/
-
- Epitech, hereby disclaims all copyright interest in the program "Beem"
- written by Frederic-Charles Barthelery,
- Jean-Manuel Da Silva,
- Nikita Kozlov,
- Philippe Lago,
- Jean Baptiste Vergely,
- Vincent Veronis.
-
- Nicolas Sadirac, November 26, 2009
- President of Epitech.
-
- Flavien Astraud, November 26, 2009
- Head of the EIP Laboratory.
-
-*/
-package com.beem.project.beem.ui.wizard;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.os.Bundle;
-import android.preference.PreferenceManager;
-import android.text.Editable;
-import android.text.InputFilter;
-import android.text.LoginFilter;
-import android.text.TextUtils;
-import android.text.TextWatcher;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.Button;
-import android.widget.EditText;
-
-import org.jivesoftware.smack.util.StringUtils;
-
-import com.beem.project.beem.ui.Login;
-import com.beem.project.beem.ui.Settings;
-import com.beem.project.beem.BeemApplication;
-import com.beem.project.beem.R;
-
-/**
- * Activity to enter the information required in order to configure a XMPP account.
- *
- * @author Da Risk <darisk972@gmail.com>
- */
-public class AccountConfigure extends Activity implements OnClickListener {
-
- private static final int MANUAL_CONFIGURATION = 1;
- private Button mNextButton;
- private Button mManualConfigButton;
- private EditText mAccountJID;
- private EditText mAccountPassword;
- private final JidTextWatcher mJidTextWatcher = new JidTextWatcher();
- private final PasswordTextWatcher mPasswordTextWatcher = new PasswordTextWatcher();
- private boolean mValidJid;
- private boolean mValidPassword;
-
- /**
- * Constructor.
- */
- public AccountConfigure() {
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.wizard_account_configure);
- mManualConfigButton = (Button) findViewById(R.id.manual_setup);
- mManualConfigButton.setOnClickListener(this);
- mNextButton = (Button) findViewById(R.id.next);
- mNextButton.setOnClickListener(this);
- mAccountJID = (EditText) findViewById(R.id.account_username);
- mAccountPassword = (EditText) findViewById(R.id.account_password);
-
-
- InputFilter[] orgFilters = mAccountJID.getFilters();
- InputFilter[] newFilters = new InputFilter[orgFilters.length + 1];
- int i;
- for (i = 0; i < orgFilters.length; i++)
- newFilters[i] = orgFilters[i];
- newFilters[i] = new LoginFilter.UsernameFilterGeneric();
- mAccountJID.setFilters(newFilters);
- mAccountJID.addTextChangedListener(mJidTextWatcher);
- mAccountPassword.addTextChangedListener(mPasswordTextWatcher);
- }
-
- @Override
- public void onClick(View v) {
- Intent i = null;
- if (v == mNextButton) {
- configureAccount();
- i = new Intent(this, Login.class);
- i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
- startActivity(i);
- finish();
- } else if (v == mManualConfigButton) {
- i = new Intent(this, Settings.class);
- i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
- startActivityForResult(i, MANUAL_CONFIGURATION);
- }
- }
-
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- if (requestCode == MANUAL_CONFIGURATION) {
- SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
- String login = settings.getString(BeemApplication.ACCOUNT_USERNAME_KEY, "");
- String password = settings.getString(BeemApplication.ACCOUNT_PASSWORD_KEY, "");
- mAccountJID.setText(login);
- mAccountPassword.setText(password);
- checkUsername(login);
- checkPassword(password);
- mNextButton.setEnabled(mValidJid && mValidPassword);
- }
- }
-
- /**
- * Store the account in the settings.
- */
- private void configureAccount() {
- SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
- SharedPreferences.Editor edit = settings.edit();
- edit.putString(BeemApplication.ACCOUNT_USERNAME_KEY, mAccountJID.getText().toString());
- edit.putString(BeemApplication.ACCOUNT_PASSWORD_KEY, mAccountPassword.getText().toString());
- edit.commit();
- }
-
- /**
- * Check that the username is really a JID.
- * @param username the username to check.
- */
- private void checkUsername(String username) {
- String name = StringUtils.parseName(username);
- String server = StringUtils.parseServer(username);
- if (TextUtils.isEmpty(name) || TextUtils.isEmpty(server)) {
- mValidJid = false;
- } else {
- mValidJid = true;
- }
- }
-
- /**
- * Check password.
- * @param password the password to check.
- */
- private void checkPassword(String password) {
- if (password.length() > 0)
- mValidPassword = true;
- else
- mValidPassword = false;
- }
-
- /**
- * Text watcher to test the existence of a password.
- */
- private class PasswordTextWatcher implements TextWatcher {
-
- /**
- * Constructor.
- */
- public PasswordTextWatcher() {
- }
-
- @Override
- public void afterTextChanged(Editable s) {
- checkPassword(s.toString());
- mNextButton.setEnabled(mValidJid && mValidPassword);
- }
-
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- }
-
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- }
- }
-
- /**
- * TextWatcher to check the validity of a JID.
- */
- private class JidTextWatcher implements TextWatcher {
-
- /**
- * Constructor.
- */
- public JidTextWatcher() {
- }
-
- @Override
- public void afterTextChanged(Editable s) {
- checkUsername(s.toString());
- mNextButton.setEnabled(mValidJid && mValidPassword);
- }
-
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- }
-
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- }
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/com/beem/project/beem/ui/wizard/AccountConfigureFragment.java Sat Sep 22 03:21:58 2012 +0200
@@ -0,0 +1,454 @@
+/*
+ BEEM is a videoconference application on the Android Platform.
+
+ Copyright (C) 2009 by Frederic-Charles Barthelery,
+ Jean-Manuel Da Silva,
+ Nikita Kozlov,
+ Philippe Lago,
+ Jean Baptiste Vergely,
+ Vincent Veronis.
+
+ This file is part of BEEM.
+
+ BEEM is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ BEEM is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with BEEM. If not, see <http://www.gnu.org/licenses/>.
+
+ Please send bug reports with examples or suggestions to
+ contact@beem-project.com or http://dev.beem-project.com/
+
+ Epitech, hereby disclaims all copyright interest in the program "Beem"
+ written by Frederic-Charles Barthelery,
+ Jean-Manuel Da Silva,
+ Nikita Kozlov,
+ Philippe Lago,
+ Jean Baptiste Vergely,
+ Vincent Veronis.
+
+ Nicolas Sadirac, November 26, 2009
+ President of Epitech.
+
+ Flavien Astraud, November 26, 2009
+ Head of the EIP Laboratory.
+
+*/
+package com.beem.project.beem.ui.wizard;
+
+import android.accounts.AccountManager;
+import android.annotation.TargetApi;
+import android.app.Activity;
+import android.app.Dialog;
+import android.app.ProgressDialog;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.AsyncTask;
+import android.os.Build;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+import android.support.v4.app.DialogFragment;
+import android.support.v4.app.Fragment;
+import android.text.Editable;
+import android.text.InputFilter;
+import android.text.LoginFilter;
+import android.text.TextUtils;
+import android.text.TextWatcher;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.TextView;
+
+import com.beem.project.beem.BeemApplication;
+import com.beem.project.beem.R;
+import com.beem.project.beem.ui.Login;
+import com.beem.project.beem.ui.Settings;
+
+import org.jivesoftware.smack.Connection;
+import org.jivesoftware.smack.ConnectionConfiguration;
+import org.jivesoftware.smack.XMPPConnection;
+import org.jivesoftware.smack.XMPPException;
+import org.jivesoftware.smack.util.StringUtils;
+
+/**
+ * Fragment to enter the information required in order to configure a XMPP account.
+ *
+ */
+public class AccountConfigureFragment extends Fragment implements OnClickListener {
+
+ private static final String TAG = AccountConfigureFragment.class.getSimpleName();
+
+ private static final String GOOGLE_ACCOUNT_TYPE = "com.google";
+ private static final int SELECT_ACCOUNT_CODE = 1;
+ private static final int MANUAL_CONFIGURATION_CODE = 2;
+
+ private Button mNextButton;
+ private Button mManualConfigButton;
+ private Button mSelectAccountButton;
+ private TextView mErrorLabel;
+ private EditText mAccountJID;
+ private EditText mAccountPassword;
+ private final JidTextWatcher mJidTextWatcher = new JidTextWatcher();
+ private final PasswordTextWatcher mPasswordTextWatcher = new PasswordTextWatcher();
+ private boolean mValidJid;
+ private boolean mValidPassword;
+ private String mSelectedAccountName;
+ private String mSelectedAccountType;
+
+ private com.beem.project.beem.ui.wizard.AccountConfigureFragment.ConnectionTestTask task;
+
+ /**
+ * Create a new AccountConfigureFragment.
+ *
+ * @return a new AccountConfigureFragment
+ */
+ public static AccountConfigureFragment newInstance() {
+ return new AccountConfigureFragment();
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ Log.d(TAG, "onCreate");
+ setRetainInstance(true);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ View v = inflater.inflate(R.layout.wizard_account_configure, container, false);
+ mManualConfigButton = (Button) v.findViewById(R.id.manual_setup);
+ mManualConfigButton.setOnClickListener(this);
+ mNextButton = (Button) v.findViewById(R.id.next);
+ mNextButton.setOnClickListener(this);
+ mSelectAccountButton = (Button) v.findViewById(R.id.select_account_btn);
+ mSelectAccountButton.setOnClickListener(this);
+ mErrorLabel = (TextView) v.findViewById(R.id.error_label);
+ mAccountJID = (EditText) v.findViewById(R.id.account_username);
+ mAccountPassword = (EditText) v.findViewById(R.id.account_password);
+ InputFilter[] orgFilters = mAccountJID.getFilters();
+ InputFilter[] newFilters = new InputFilter[orgFilters.length + 1];
+ int i;
+ for (i = 0; i < orgFilters.length; i++)
+ newFilters[i] = orgFilters[i];
+ newFilters[i] = new LoginFilter.UsernameFilterGeneric();
+ mAccountJID.setFilters(newFilters);
+ mAccountJID.addTextChangedListener(mJidTextWatcher);
+ mAccountPassword.addTextChangedListener(mPasswordTextWatcher);
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH
+ || true) // true to disable the feature until ready
+ v.findViewById(R.id.account_layout).setVisibility(View.GONE);
+ return v;
+ }
+
+
+ @TargetApi(14)
+ @Override
+ public void onClick(View v) {
+ if (v == mNextButton) {
+ String jid = mAccountJID.getText().toString();
+ jid = StringUtils.parseBareAddress(jid);
+ String password = mAccountPassword.getText().toString();
+ task = new ConnectionTestTask();
+ task.execute(jid, password);
+ } else if (v == mManualConfigButton) {
+ onManualConfigurationSelected();
+ } else if (v == mSelectAccountButton) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
+ Intent i = AccountManager.newChooseAccountIntent(null, null,
+ new String[] {GOOGLE_ACCOUNT_TYPE}, true, null, null, null, null);
+ startActivityForResult(i, SELECT_ACCOUNT_CODE);
+ }
+ }
+ }
+
+ /**
+ * Callback called when the Manual configuration button is selected.
+ *
+ */
+ public void onManualConfigurationSelected() {
+ Intent i = new Intent(getActivity(), Settings.class);
+ i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ startActivityForResult(i, MANUAL_CONFIGURATION_CODE);
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (requestCode == SELECT_ACCOUNT_CODE && resultCode == Activity.RESULT_OK) {
+ mSelectedAccountName = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
+ mSelectedAccountType = data.getStringExtra(AccountManager.KEY_ACCOUNT_TYPE);
+ onDeviceAccountSelected(mSelectedAccountName, mSelectedAccountType);
+ } else if (requestCode == MANUAL_CONFIGURATION_CODE) {
+ SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(getActivity());
+ String login = settings.getString(BeemApplication.ACCOUNT_USERNAME_KEY, "");
+ String password = settings.getString(BeemApplication.ACCOUNT_PASSWORD_KEY, "");
+ mAccountJID.setText(login);
+ mAccountPassword.setText(password);
+ } else {
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+ }
+
+ /**
+ * Callback called when the account was connected successfully.
+ *
+ * @param jid the jid used to connect
+ * @param password the password used to connect
+ *
+ */
+ private void onAccountConnectionSuccess(String jid, String password) {
+ Activity a = getActivity();
+ saveCredential(jid, password);
+ // launch login
+ Intent i = new Intent(a, Login.class);
+ i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ startActivity(i);
+ a.finish();
+ }
+
+ /**
+ * Callback called when the account connection failed.
+ *
+ */
+ private void onAccountConnectionFailed() {
+ //TODO display error
+ mAccountPassword.setText("");
+ mErrorLabel.setVisibility(View.VISIBLE);
+ }
+
+ /**
+ * Callback called when the user select an account from the device (Android Account api).
+ *
+ * @param accountName the account name
+ * @param accountType the account type
+ *
+ */
+ private void onDeviceAccountSelected(String accountName, String accountType) {
+ Activity a = getActivity();
+ //TODO Save credential
+ Log.d(TAG, "Account selected is " + accountName + " from " + accountType);
+ // launch login
+ Intent i = new Intent(a, Login.class);
+ i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ startActivity(i);
+ a.finish();
+ }
+
+ /**
+ * Save the user credentials.
+ *
+ * @param jid the jid of the user
+ * @param pass the password of the user
+ *
+ */
+ private void saveCredential(String jid, String pass) {
+ SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(getActivity());
+ SharedPreferences.Editor edit = settings.edit();
+ edit.putString(BeemApplication.ACCOUNT_USERNAME_KEY, jid);
+ edit.putString(BeemApplication.ACCOUNT_PASSWORD_KEY, pass);
+ edit.commit();
+ }
+
+ /**
+ * Check that the username is really a JID.
+ * @param username the username to check.
+ */
+ private void checkUsername(String username) {
+ String name = StringUtils.parseName(username);
+ String server = StringUtils.parseServer(username);
+ if (TextUtils.isEmpty(name) || TextUtils.isEmpty(server)) {
+ mValidJid = false;
+ } else {
+ mValidJid = true;
+ }
+ }
+
+ /**
+ * Check password.
+ * @param password the password to check.
+ */
+ private void checkPassword(String password) {
+ if (password.length() > 0)
+ mValidPassword = true;
+ else
+ mValidPassword = false;
+ }
+
+ /**
+ * Text watcher to test the existence of a password.
+ */
+ private class PasswordTextWatcher implements TextWatcher {
+
+ /**
+ * Constructor.
+ */
+ public PasswordTextWatcher() {
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ checkPassword(s.toString());
+ mNextButton.setEnabled(mValidJid && mValidPassword);
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ }
+ }
+
+ /**
+ * TextWatcher to check the validity of a JID.
+ */
+ private class JidTextWatcher implements TextWatcher {
+
+ /**
+ * Constructor.
+ */
+ public JidTextWatcher() {
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ checkUsername(s.toString());
+ mNextButton.setEnabled(mValidJid && mValidPassword);
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ }
+ }
+
+ /**
+ * AsyncTask use to test the credentials.
+ */
+ class ConnectionTestTask extends AsyncTask<String, Void, Boolean> {
+
+ private ProgressFragment progress;
+ private ConnectionConfiguration config;
+ private XMPPException exception;
+ private String jid;
+ private String password;
+ private String server;
+
+ @Override
+ protected void onPreExecute() {
+ mErrorLabel.setVisibility(View.INVISIBLE);
+ progress = ProgressFragment.newInstance();
+ progress.show(getFragmentManager(), "progressFragment");
+ }
+
+ @Override
+ protected void onPostExecute(Boolean result) {
+ if (result) {
+ onAccountConnectionSuccess(jid, password);
+ } else {
+ onAccountConnectionFailed();
+ }
+ ProgressFragment pf = (ProgressFragment) getFragmentManager().findFragmentByTag("progressFragment");
+ if (pf != null)
+ pf.dismiss();
+ }
+
+ @Override
+ protected Boolean doInBackground(String... params) {
+ Log.d(TAG, "Xmpp login task");
+ jid = params[0];
+ password = params[1];
+ server = StringUtils.parseServer(jid);
+ Log.d(TAG, "jid " + jid + " server " + server);
+
+ int port = -1;
+ if (params.length > 2) {
+ server = params[2];
+ }
+ if (params.length > 3) {
+ if (!TextUtils.isEmpty(params[3])) {
+ port = Integer.parseInt(params[3]);
+ }
+ }
+ Connection connection = prepareConnection(jid, server, port);
+ try {
+ connection.connect();
+ connection.login(StringUtils.parseName(jid), password);
+ } catch (XMPPException e) {
+ Log.e(TAG, "Unable to connect to Xmpp server", e);
+ exception = e;
+ return false;
+ } finally {
+ connection.disconnect();
+ }
+ return true;
+ }
+
+ /**
+ * Initialize the XMPP connection.
+ *
+ * @param jid the jid to use
+ * @param server the server to use
+ * @param port the port
+ *
+ * @return the XMPPConnection prepared to connect
+ */
+ private Connection prepareConnection(String jid, String server, int port) {
+ String serviceName = StringUtils.parseServer(jid);
+ if (port != -1 || !TextUtils.isEmpty(server)) {
+ if (port == -1)
+ port = 5222;
+ if (TextUtils.isEmpty(server))
+ server = serviceName;
+ config = new ConnectionConfiguration(server, port, serviceName);
+ } else {
+ config = new ConnectionConfiguration(serviceName);
+ }
+ return new XMPPConnection(config);
+ }
+ }
+
+ /**
+ * A progress Fragment.
+ */
+ public static class ProgressFragment extends DialogFragment {
+
+ /**
+ * Create a new ProgressFragment.
+ *
+ * @return a ProgressFragment
+ */
+ public static ProgressFragment newInstance() {
+ return new ProgressFragment();
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setCancelable(false);
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ Log.d(TAG, "create progress dialog");
+ ProgressDialog p = new ProgressDialog(getActivity());
+ p.setTitle("Connexion en cours");
+ p.setMessage("Please wait");
+ return p;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/com/beem/project/beem/ui/wizard/CreateAccountFragment.java Sat Sep 22 03:21:58 2012 +0200
@@ -0,0 +1,340 @@
+/*
+ BEEM is a videoconference application on the Android Platform.
+
+ Copyright (C) 2009-2012 by Frederic-Charles Barthelery,
+ Nikita Kozlov,
+ Vincent Veronis.
+
+ This file is part of BEEM.
+
+ BEEM is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ BEEM is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with BEEM. If not, see <http://www.gnu.org/licenses/>.
+
+ Please send bug reports with examples or suggestions to
+ contact@beem-project.com or http://www.beem-project.com/
+
+*/
+package com.beem.project.beem.ui.wizard;
+
+import java.util.regex.Pattern;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.app.ProgressDialog;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+import android.support.v4.app.DialogFragment;
+import android.support.v4.app.Fragment;
+import android.text.Editable;
+import android.text.TextUtils;
+import android.text.TextWatcher;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.TextView;
+
+import com.beem.project.beem.BeemApplication;
+import com.beem.project.beem.R;
+import com.beem.project.beem.ui.Login;
+
+import org.jivesoftware.smack.AccountManager;
+import org.jivesoftware.smack.Connection;
+import org.jivesoftware.smack.ConnectionConfiguration;
+import org.jivesoftware.smack.XMPPConnection;
+import org.jivesoftware.smack.XMPPException;
+import org.jivesoftware.smack.util.StringUtils;
+
+
+/**
+ * Fragment used to create an account on an XMPP server.
+ */
+public class CreateAccountFragment extends Fragment implements android.view.View.OnClickListener {
+ private static final String TAG = CreateAccountFragment.class.getSimpleName();
+ private TextView username;
+ private TextView password;
+ private TextView confirmPassword;
+ private Button createButton;
+ private CreateAccountTask task;
+ private final NotEmptyTextWatcher mTextWatcher = new NotEmptyTextWatcher();
+
+ /**
+ * Create a CreateAccountFragment.
+ *
+ */
+ public CreateAccountFragment() {
+ }
+
+ /**
+ * Create a CreateAccountFragment.
+ * @return a new CreateAccountFragment
+ */
+ public static CreateAccountFragment newInstance() {
+ return new CreateAccountFragment();
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setRetainInstance(true);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ View v = inflater.inflate(R.layout.create_account, container, false);
+ username = (TextView) v.findViewById(R.id.create_account_username);
+ username.addTextChangedListener(mTextWatcher);
+ password = (TextView) v.findViewById(R.id.create_account_password);
+ password.addTextChangedListener(mTextWatcher);
+ confirmPassword = (TextView) v.findViewById(R.id.create_account_confirm_password);
+ confirmPassword.addTextChangedListener(mTextWatcher);
+ createButton = (Button) v.findViewById(R.id.next);
+ createButton.setOnClickListener(this);
+ return v;
+ }
+
+ @Override
+ public void onClick(View v) {
+ if (v == createButton) {
+ boolean create = true;
+ if (!checkEmail()) {
+ username.setError(getString(R.string.create_account_err_username));
+ create = false;
+ }
+ if (!checkPasswords()) {
+ password.setError(getString(R.string.create_account_err_passwords));
+ confirmPassword.setError(getString(R.string.create_account_err_passwords));
+ create = false;
+ }
+ if (create) {
+ String jid = username.getText().toString();
+ jid = StringUtils.parseBareAddress(jid);
+ String pass = password.getText().toString();
+ task = new CreateAccountTask();
+ task.execute(jid, pass);
+ }
+ }
+ }
+
+ /**
+ * Save the user credentials.
+ *
+ * @param jid the jid of the user
+ * @param pass the password of the user
+ *
+ */
+ private void saveCredential(String jid, String pass) {
+ SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(getActivity());
+ SharedPreferences.Editor edit = settings.edit();
+ edit.putString(BeemApplication.ACCOUNT_USERNAME_KEY, jid);
+ edit.putString(BeemApplication.ACCOUNT_PASSWORD_KEY, pass);
+ edit.commit();
+ }
+
+ /**
+ * Callback called when the account is successfully created.
+ *
+ * @param jid the jid of the account.
+ * @param pass the password of the account.
+ *
+ */
+ private void onAccountCreationSuccess(String jid, String pass) {
+ Activity a = getActivity();
+ saveCredential(jid, pass);
+ // launch login
+ Intent i = new Intent(a, Login.class);
+ i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ startActivity(i);
+ a.finish();
+ }
+
+ /**
+ * Callback called when the account failed to create.
+ *
+ * @param e the exception which occurs
+ *
+ */
+ private void onAccountCreationFailed(XMPPException e) {
+ // TODO displayError
+ }
+
+ /**
+ * Check the format of the email.
+ *
+ * @return true if the email is valid.
+ */
+ private boolean checkEmail() {
+ String email = username.getText().toString();
+ return Pattern.matches("[a-zA-Z0-9._%+-]+@(?:[a-zA-Z0-9-]+.)+[a-zA-Z]{2,4}", email);
+ }
+
+ /**
+ * Check if the fields password and confirm password match.
+ *
+ * @return return true if password & confirm password fields match, else
+ * false
+ */
+ private boolean checkPasswords() {
+ CharSequence pass = password.getText();
+ return !TextUtils.isEmpty(pass) && TextUtils.equals(pass, confirmPassword.getText());
+ }
+
+ /**
+ * AsyncTask use to create an XMPP account on a server.
+ */
+ private class CreateAccountTask extends AsyncTask<String, Void, Boolean> {
+
+ private ProgressFragment progress;
+ private ConnectionConfiguration config;
+ private XMPPException exception;
+ private String jid;
+ private String password;
+ private String server;
+
+ @Override
+ protected void onPreExecute() {
+ progress = ProgressFragment.newInstance();
+ progress.show(getFragmentManager(), "progressFragment");
+ }
+
+ @Override
+ protected void onPostExecute(Boolean result) {
+ if (result) {
+ onAccountCreationSuccess(jid, password);
+ } else {
+ onAccountCreationFailed(exception);
+ }
+ ProgressFragment pf = (ProgressFragment) getFragmentManager().findFragmentByTag("progressFragment");
+ if (pf != null)
+ pf.dismiss();
+ }
+
+ @Override
+ protected Boolean doInBackground(String... params) {
+ Log.d(TAG, "Xmpp login task");
+ jid = params[0];
+ password = params[1];
+ server = StringUtils.parseServer(jid);
+ Log.d(TAG, "jid " + jid + " server " + server);
+
+ int port = -1;
+ if (params.length > 2) {
+ server = params[2];
+ }
+ if (params.length > 3) {
+ if (!TextUtils.isEmpty(params[3])) {
+ port = Integer.parseInt(params[3]);
+ }
+ }
+ Connection connection = prepareConnection(jid, server, port);
+ try {
+ connection.connect();
+ AccountManager accountManager = new AccountManager(connection);
+ accountManager.createAccount(StringUtils.parseName(jid), password);
+ } catch (XMPPException e) {
+ Log.e(TAG, "Unable to create account", e);
+ exception = e;
+ return false;
+ } finally {
+ connection.disconnect();
+ }
+ return true;
+ }
+
+ /**
+ * Initialize the XMPP connection.
+ *
+ * @param jid the jid to use
+ * @param server the server to use
+ * @param port the port
+ *
+ * @return the XMPPConnection prepared to connect
+ */
+ private Connection prepareConnection(String jid, String server, int port) {
+ String serviceName = StringUtils.parseServer(jid);
+ if (port != -1 || !TextUtils.isEmpty(server)) {
+ if (port == -1)
+ port = 5222;
+ if (TextUtils.isEmpty(server))
+ server = serviceName;
+ config = new ConnectionConfiguration(server, port, serviceName);
+ } else {
+ config = new ConnectionConfiguration(serviceName);
+ }
+ return new XMPPConnection(config);
+ }
+ }
+
+ /**
+ * A progress Fragment.
+ */
+ public static class ProgressFragment extends DialogFragment {
+
+ /**
+ * Create a new ProgressFragment.
+ *
+ * @return a ProgressFragment
+ */
+ public static ProgressFragment newInstance() {
+ return new ProgressFragment();
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setCancelable(false);
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ Log.d(TAG, "create progress dialog");
+ ProgressDialog p = new ProgressDialog(getActivity());
+ p.setTitle("Creation du compte en cours");
+ p.setMessage("Please wait");
+ return p;
+ }
+ }
+
+ /**
+ * Text watcher to test if all fields are field.
+ */
+ private class NotEmptyTextWatcher implements TextWatcher {
+
+ /**
+ * Constructor.
+ */
+ public NotEmptyTextWatcher() {
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ boolean enable = !(TextUtils.isEmpty(username.getText())
+ || TextUtils.isEmpty(password.getText())
+ || TextUtils.isEmpty(confirmPassword.getText()));
+ createButton.setEnabled(enable);
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ }
+ }
+
+}