| /* |
| * 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); |
| } |
| } |
| } |