blob: 1e426450c0ed92bae553cd88d5ed77eb051451f5 [file] [log] [blame]
/*
* Copyright (C) 2008 Esmertec AG.
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.im.app;
import com.android.im.IChatSession;
import com.android.im.IChatSessionManager;
import com.android.im.IConnectionListener;
import com.android.im.IImConnection;
import com.android.im.R;
import com.android.im.app.adapter.ConnectionListenerAdapter;
import com.android.im.engine.ImConnection;
import com.android.im.engine.ImErrorInfo;
import com.android.im.plugin.BrandingResourceIDs;
import com.android.im.provider.Imps;
import com.android.im.service.ImServiceConstants;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Resources;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.Handler;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.Window;
import android.widget.ImageView;
public class SigningInActivity extends Activity {
private static final String SYNC_SETTINGS_ACTION = "android.settings.SYNC_SETTINGS";
private static final String SYNC_SETTINGS_CATEGORY = "android.intent.category.DEFAULT";
private IImConnection mConn;
private IConnectionListener mListener;
private SimpleAlertHandler mHandler;
private ImApp mApp;
private long mProviderId;
private long mAccountId;
private String mProviderName;
private String mUserName;
private String mPassword;
private String mToAddress;
protected static final int ID_CANCEL_SIGNIN = Menu.FIRST + 1;
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
//setTheme(android.R.style.Theme_Dialog);
getWindow().requestFeature(Window.FEATURE_LEFT_ICON);
setContentView(R.layout.signing_in_activity);
Intent intent = getIntent();
mToAddress = intent.getStringExtra(ImApp.EXTRA_INTENT_SEND_TO_USER);
Uri data = intent.getData();
if (data == null) {
if(Log.isLoggable(ImApp.LOG_TAG, Log.DEBUG)) {
log("Need account data to sign in");
}
finish();
return;
}
ContentResolver cr = getContentResolver();
Cursor c = cr.query(data, null, null, null, null);
if (c == null) {
if (Log.isLoggable(ImApp.LOG_TAG, Log.DEBUG)) {
log("Query fail:" + data);
}
finish();
return;
}
if (!c.moveToFirst()) {
if (Log.isLoggable(ImApp.LOG_TAG, Log.DEBUG)) {
log("No data for " + data);
}
c.close();
finish();
return;
}
mProviderId = c.getLong(c.getColumnIndexOrThrow(Imps.Account.PROVIDER));
mAccountId = c.getLong(c.getColumnIndexOrThrow(Imps.Account._ID));
mUserName = c.getString(c.getColumnIndexOrThrow(Imps.Account.USERNAME));
String pwExtra = intent.getStringExtra(ImApp.EXTRA_INTENT_PASSWORD);
mPassword = pwExtra != null ? pwExtra
: c.getString(c.getColumnIndexOrThrow(Imps.Account.PASSWORD));
final boolean isActive = c.getInt(c.getColumnIndexOrThrow(Imps.Account.ACTIVE)) == 1;
c.close();
mApp = ImApp.getApplication(this);
final ProviderDef provider = mApp.getProvider(mProviderId);
mProviderName = provider.mName;
BrandingResources brandingRes = mApp.getBrandingResource(mProviderId);
getWindow().setFeatureDrawable(Window.FEATURE_LEFT_ICON,
brandingRes.getDrawable(BrandingResourceIDs.DRAWABLE_LOGO));
setTitle(getResources().getString(R.string.signing_in_to,
provider.mFullName));
ImageView splash = (ImageView)findViewById(R.id.splashscr);
splash.setImageDrawable(brandingRes.getDrawable(
BrandingResourceIDs.DRAWABLE_SPLASH_SCREEN));
mHandler = new SimpleAlertHandler(this);
mListener = new MyConnectionListener(mHandler);
mApp.callWhenServiceConnected(mHandler, new Runnable() {
public void run() {
if (mApp.serviceConnected()) {
if (!isActive) {
activateAccount(mProviderId, mAccountId);
}
signInAccount();
}
}
});
// assume we can sign in successfully.
setResult(RESULT_OK);
}
@Override
protected void onRestart() {
super.onRestart();
if (mApp.serviceConnected() && mApp.isBackgroundDataEnabled()) {
signInAccount();
} else {
if(Log.isLoggable(ImApp.LOG_TAG, Log.DEBUG)) {
log("onRestart: service disconnected or background data disabled...");
}
setResult(RESULT_CANCELED);
finish();
}
}
void signInAccount() {
try {
IImConnection conn = mApp.getConnection(mProviderId);
if (conn != null) {
mConn = conn;
// register listener before get state so that we won't miss
// any state change event.
conn.registerConnectionListener(mListener);
int state = conn.getState();
if (state != ImConnection.LOGGING_IN) {
// already signed in or failed
conn.unregisterConnectionListener(mListener);
handleConnectionEvent(state, null);
}
} else {
if (mApp.isBackgroundDataEnabled()) {
mConn = mApp.createConnection(mProviderId);
mConn.registerConnectionListener(mListener);
mConn.login(mAccountId, mUserName, mPassword, true);
} else {
promptForBackgroundDataSetting();
return;
}
}
} catch (RemoteException e) {
mHandler.showServiceErrorAlert();
finish();
}
}
private void activateAccount(long providerId, long accountId) {
// Update the active value. We restrict to only one active
// account per provider right now, so update all accounts of
// this provider to inactive first and then update this
// account to active.
ContentValues values = new ContentValues(1);
values.put(Imps.Account.ACTIVE, 0);
ContentResolver cr = getContentResolver();
cr.update(Imps.Account.CONTENT_URI, values,
Imps.Account.PROVIDER + "=" + providerId, null);
values.put(Imps.Account.ACTIVE, 1);
cr.update(ContentUris.withAppendedId(Imps.Account.CONTENT_URI, accountId),
values, null, null);
}
@Override
protected void onStop() {
super.onStop();
if (mApp != null) {
mApp.removePendingCall(mHandler);
}
if (mConn != null) {
try {
if (Log.isLoggable(ImApp.LOG_TAG, Log.DEBUG)) {
log("unregisterConnectonListener");
}
mConn.unregisterConnectionListener(mListener);
} catch (RemoteException e) {
Log.w(ImApp.LOG_TAG, "<SigningInActivity> Connection disappeared!");
}
}
// When background data is enabled, we don't want this activity in the backlist
// so we always call finish() when we leave signing in screen. Otherwise, we
// don't finish since we need to keep signing in if user choose to enable background.
if (mApp.isBackgroundDataEnabled()) {
finish();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, ID_CANCEL_SIGNIN, 0, R.string.menu_cancel_signin)
.setIcon(android.R.drawable.ic_menu_close_clear_cancel);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == ID_CANCEL_SIGNIN) {
if (mConn != null) {
try {
if (mConn.getState() == ImConnection.LOGGING_IN) {
if (Log.isLoggable(ImApp.LOG_TAG, Log.DEBUG)) {
log("Cancelling sign in");
}
mConn.logout();
finish();
}
} catch (RemoteException e) {
Log.w(ImApp.LOG_TAG, "<SigningInActivity> Connection disappeared!");
}
}
return true;
} else {
return super.onOptionsItemSelected(item);
}
}
/**
* Popup a dialog to ask the user whether he/she wants to enable
* background connection to continue. If yes, enable the setting
* and broadcast the change. Otherwise, quit the signing in window
* immediately.
*/
private void promptForBackgroundDataSetting() {
new AlertDialog.Builder(SigningInActivity.this)
.setTitle(R.string.bg_data_prompt_title)
.setIcon(android.R.drawable.ic_dialog_alert)
.setMessage(getString(R.string.bg_data_prompt_message, mProviderName))
.setPositiveButton(R.string.bg_data_prompt_ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
Intent intent = new Intent(SYNC_SETTINGS_ACTION);
intent.addCategory(SYNC_SETTINGS_CATEGORY);
startActivity(intent);
}
})
.setNegativeButton(R.string.bg_data_prompt_cancel,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
setResult(RESULT_CANCELED);
finish();
}
})
.show();
}
void handleConnectionEvent(int state, ImErrorInfo error) {
if (isFinishing()) {
return;
}
if (state == ImConnection.LOGGED_IN) {
// sign in successfully, finish and switch to contact list
finish();
try {
Intent intent;
long accountId = mConn.getAccountId();
if (mToAddress != null) {
IChatSessionManager manager = mConn.getChatSessionManager();
IChatSession session = manager.getChatSession(mToAddress);
if(session == null) {
session = manager.createChatSession(mToAddress);
}
Uri data = ContentUris.withAppendedId(Imps.Chats.CONTENT_URI, session.getId());
intent = new Intent(Intent.ACTION_VIEW, data);
intent.putExtra("from", mToAddress);
intent.putExtra("providerId", mProviderId);
intent.putExtra("accountId", accountId);
intent.addCategory(ImApp.IMPS_CATEGORY);
} else {
intent = new Intent(this, ContactListActivity.class);
intent.putExtra(ImServiceConstants.EXTRA_INTENT_ACCOUNT_ID, accountId);
}
startActivity(intent);
} catch (RemoteException e) {
// Ouch! Service died! We'll just disappear.
Log.w(ImApp.LOG_TAG, "<SigningInActivity> Connection disappeared while signing in!");
}
} else if (state == ImConnection.DISCONNECTED) {
// sign in failed
Resources r = getResources();
new AlertDialog.Builder(this)
.setTitle(R.string.error)
.setMessage(r.getString(R.string.login_service_failed, mProviderName,
error == null? "": ErrorResUtils.getErrorRes(r, error.getCode())))
.setPositiveButton(R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
setResult(RESULT_CANCELED);
finish();
}
})
.setCancelable(false)
.show();
}
}
private static final void log(String msg) {
Log.d(ImApp.LOG_TAG, "<SigningInActivity>" + msg);
}
private final class MyConnectionListener extends ConnectionListenerAdapter {
MyConnectionListener(Handler handler) {
super(handler);
}
@Override
public void onConnectionStateChange(IImConnection connection,
int state, ImErrorInfo error) {
handleConnectionEvent(state, error);
}
}
}