• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 Esmertec AG.
3  * Copyright (C) 2008 The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 package com.android.im.app;
18 
19 import com.android.im.IChatSession;
20 import com.android.im.IChatSessionManager;
21 import com.android.im.IConnectionListener;
22 import com.android.im.IImConnection;
23 import com.android.im.R;
24 import com.android.im.app.adapter.ConnectionListenerAdapter;
25 import com.android.im.engine.ImConnection;
26 import com.android.im.engine.ImErrorInfo;
27 import com.android.im.plugin.BrandingResourceIDs;
28 import com.android.im.service.ImServiceConstants;
29 
30 import android.app.Activity;
31 import android.app.AlertDialog;
32 import android.content.ContentResolver;
33 import android.content.ContentUris;
34 import android.content.ContentValues;
35 import android.content.DialogInterface;
36 import android.content.Intent;
37 import android.content.res.Resources;
38 import android.database.Cursor;
39 import android.net.Uri;
40 import android.os.Bundle;
41 import android.os.RemoteException;
42 import android.os.Handler;
43 import android.provider.Im;
44 import android.util.Log;
45 import android.view.Menu;
46 import android.view.MenuItem;
47 import android.view.Window;
48 import android.widget.ImageView;
49 
50 public class SigningInActivity extends Activity {
51     private static final String SYNC_SETTINGS_ACTION = "android.settings.SYNC_SETTINGS";
52     private static final String SYNC_SETTINGS_CATEGORY = "android.intent.category.DEFAULT";
53 
54     private IImConnection mConn;
55     private IConnectionListener mListener;
56     private SimpleAlertHandler mHandler;
57     private ImApp mApp;
58     private long mProviderId;
59     private long mAccountId;
60     private String mProviderName;
61 
62     private String mUserName;
63     private String mPassword;
64 
65     private String mToAddress;
66 
67     protected static final int ID_CANCEL_SIGNIN = Menu.FIRST + 1;
68 
69     @Override
onCreate(Bundle icicle)70     protected void onCreate(Bundle icicle) {
71         super.onCreate(icicle);
72 
73         //setTheme(android.R.style.Theme_Dialog);
74         getWindow().requestFeature(Window.FEATURE_LEFT_ICON);
75         setContentView(R.layout.signing_in_activity);
76         Intent intent = getIntent();
77         mToAddress = intent.getStringExtra(ImApp.EXTRA_INTENT_SEND_TO_USER);
78 
79         Uri data = intent.getData();
80         if (data == null) {
81             if(Log.isLoggable(ImApp.LOG_TAG, Log.DEBUG)) {
82                 log("Need account data to sign in");
83             }
84             finish();
85             return;
86         }
87         ContentResolver cr = getContentResolver();
88         Cursor c = cr.query(data, null, null, null, null);
89         if (c == null) {
90             if (Log.isLoggable(ImApp.LOG_TAG, Log.DEBUG)) {
91                 log("Query fail:" + data);
92             }
93             finish();
94             return;
95         }
96         if (!c.moveToFirst()) {
97             if (Log.isLoggable(ImApp.LOG_TAG, Log.DEBUG)) {
98                 log("No data for " + data);
99             }
100             c.close();
101             finish();
102             return;
103         }
104 
105         mProviderId = c.getLong(c.getColumnIndexOrThrow(Im.Account.PROVIDER));
106         mAccountId = c.getLong(c.getColumnIndexOrThrow(Im.Account._ID));
107         mUserName = c.getString(c.getColumnIndexOrThrow(Im.Account.USERNAME));
108         String pwExtra = intent.getStringExtra(ImApp.EXTRA_INTENT_PASSWORD);
109         mPassword = pwExtra != null ? pwExtra
110                 : c.getString(c.getColumnIndexOrThrow(Im.Account.PASSWORD));
111         final boolean isActive = c.getInt(c.getColumnIndexOrThrow(Im.Account.ACTIVE)) == 1;
112 
113         c.close();
114         mApp = ImApp.getApplication(this);
115         final ProviderDef provider = mApp.getProvider(mProviderId);
116         mProviderName = provider.mName;
117 
118         BrandingResources brandingRes = mApp.getBrandingResource(mProviderId);
119         getWindow().setFeatureDrawable(Window.FEATURE_LEFT_ICON,
120                 brandingRes.getDrawable(BrandingResourceIDs.DRAWABLE_LOGO));
121 
122         setTitle(getResources().getString(R.string.signing_in_to,
123                 provider.mFullName));
124 
125         ImageView splash = (ImageView)findViewById(R.id.splashscr);
126         splash.setImageDrawable(brandingRes.getDrawable(
127                 BrandingResourceIDs.DRAWABLE_SPLASH_SCREEN));
128 
129         mHandler = new SimpleAlertHandler(this);
130         mListener = new MyConnectionListener(mHandler);
131 
132         mApp.callWhenServiceConnected(mHandler, new Runnable() {
133             public void run() {
134                 if (mApp.serviceConnected()) {
135                     if (!isActive) {
136                         activateAccount(mProviderId, mAccountId);
137                     }
138                     signInAccount();
139                 }
140             }
141         });
142 
143         // assume we can sign in successfully.
144         setResult(RESULT_OK);
145     }
146 
147     @Override
onRestart()148     protected void onRestart() {
149         super.onRestart();
150 
151         if (mApp.serviceConnected() && mApp.isBackgroundDataEnabled()) {
152             signInAccount();
153         } else {
154             if(Log.isLoggable(ImApp.LOG_TAG, Log.DEBUG)) {
155                 log("onRestart: service disconnected or background data disabled...");
156             }
157             setResult(RESULT_CANCELED);
158             finish();
159         }
160     }
161 
signInAccount()162     void signInAccount() {
163         try {
164             IImConnection conn = mApp.getConnection(mProviderId);
165             if (conn != null) {
166                 mConn = conn;
167                 // register listener before get state so that we won't miss
168                 // any state change event.
169                 conn.registerConnectionListener(mListener);
170                 int state = conn.getState();
171                 if (state != ImConnection.LOGGING_IN) {
172                     // already signed in or failed
173                     conn.unregisterConnectionListener(mListener);
174                     handleConnectionEvent(state, null);
175                 }
176             } else {
177                 if (mApp.isBackgroundDataEnabled()) {
178                     mConn = mApp.createConnection(mProviderId);
179                     mConn.registerConnectionListener(mListener);
180                     mConn.login(mAccountId, mUserName, mPassword, true);
181                 } else {
182                     promptForBackgroundDataSetting();
183                     return;
184                 }
185             }
186 
187         } catch (RemoteException e) {
188             mHandler.showServiceErrorAlert();
189             finish();
190         }
191     }
192 
activateAccount(long providerId, long accountId)193     private void activateAccount(long providerId, long accountId) {
194         // Update the active value. We restrict to only one active
195         // account per provider right now, so update all accounts of
196         // this provider to inactive first and then update this
197         // account to active.
198         ContentValues values = new ContentValues(1);
199         values.put(Im.Account.ACTIVE, 0);
200         ContentResolver cr = getContentResolver();
201         cr.update(Im.Account.CONTENT_URI, values,
202                 Im.Account.PROVIDER + "=" + providerId, null);
203 
204         values.put(Im.Account.ACTIVE, 1);
205         cr.update(ContentUris.withAppendedId(Im.Account.CONTENT_URI, accountId),
206                 values, null, null);
207     }
208 
209     @Override
onStop()210     protected void onStop() {
211         super.onStop();
212 
213         if (mApp != null) {
214             mApp.removePendingCall(mHandler);
215         }
216         if (mConn != null) {
217             try {
218                 if (Log.isLoggable(ImApp.LOG_TAG, Log.DEBUG)) {
219                     log("unregisterConnectonListener");
220                 }
221                 mConn.unregisterConnectionListener(mListener);
222             } catch (RemoteException e) {
223                 Log.w(ImApp.LOG_TAG, "<SigningInActivity> Connection disappeared!");
224             }
225         }
226         // When background data is enabled, we don't want this activity in the backlist
227         // so we always call finish() when we leave signing in screen. Otherwise, we
228         // don't finish since we need to keep signing in if user choose to enable background.
229         if (mApp.isBackgroundDataEnabled()) {
230             finish();
231         }
232     }
233 
234     @Override
onCreateOptionsMenu(Menu menu)235     public boolean onCreateOptionsMenu(Menu menu) {
236         menu.add(0, ID_CANCEL_SIGNIN, 0, R.string.menu_cancel_signin)
237             .setIcon(android.R.drawable.ic_menu_close_clear_cancel);
238 
239         return true;
240     }
241 
242     @Override
onOptionsItemSelected(MenuItem item)243     public boolean onOptionsItemSelected(MenuItem item) {
244         if (item.getItemId() == ID_CANCEL_SIGNIN) {
245             if (mConn != null) {
246                 try {
247                     if (mConn.getState() == ImConnection.LOGGING_IN) {
248                         if (Log.isLoggable(ImApp.LOG_TAG, Log.DEBUG)) {
249                             log("Cancelling sign in");
250                         }
251                         mConn.logout();
252                         finish();
253                     }
254                 } catch (RemoteException e) {
255                     Log.w(ImApp.LOG_TAG, "<SigningInActivity> Connection disappeared!");
256                 }
257             }
258             return true;
259         } else {
260             return super.onOptionsItemSelected(item);
261         }
262     }
263 
264     /**
265      * Popup a dialog to ask the user whether he/she wants to enable
266      * background connection to continue. If yes, enable the setting
267      * and broadcast the change. Otherwise, quit the signing in window
268      * immediately.
269      */
promptForBackgroundDataSetting()270     private void promptForBackgroundDataSetting() {
271         new AlertDialog.Builder(SigningInActivity.this)
272             .setTitle(R.string.bg_data_prompt_title)
273             .setIcon(android.R.drawable.ic_dialog_alert)
274             .setMessage(getString(R.string.bg_data_prompt_message, mProviderName))
275             .setPositiveButton(R.string.bg_data_prompt_ok, new DialogInterface.OnClickListener() {
276                 public void onClick(DialogInterface dialog, int whichButton) {
277                     Intent intent = new Intent(SYNC_SETTINGS_ACTION);
278                     intent.addCategory(SYNC_SETTINGS_CATEGORY);
279                     startActivity(intent);
280                 }
281              })
282             .setNegativeButton(R.string.bg_data_prompt_cancel,
283                 new DialogInterface.OnClickListener() {
284                     public void onClick(DialogInterface dialog, int whichButton) {
285                         setResult(RESULT_CANCELED);
286                         finish();
287                     }
288              })
289             .show();
290     }
291 
handleConnectionEvent(int state, ImErrorInfo error)292     void handleConnectionEvent(int state, ImErrorInfo error) {
293         if (isFinishing()) {
294             return;
295         }
296 
297         if (state == ImConnection.LOGGED_IN) {
298             // sign in successfully, finish and switch to contact list
299             finish();
300             try {
301                 Intent intent;
302                 long accountId = mConn.getAccountId();
303 
304                 if (mToAddress != null) {
305                     IChatSessionManager manager = mConn.getChatSessionManager();
306                     IChatSession session = manager.getChatSession(mToAddress);
307                     if(session == null) {
308                         session = manager.createChatSession(mToAddress);
309                     }
310                     Uri data = ContentUris.withAppendedId(Im.Chats.CONTENT_URI, session.getId());
311                     intent = new Intent(Intent.ACTION_VIEW, data);
312                     intent.putExtra("from", mToAddress);
313                     intent.putExtra("providerId", mProviderId);
314                     intent.putExtra("accountId", accountId);
315                     intent.addCategory(ImApp.IMPS_CATEGORY);
316 
317                 } else {
318                     intent = new Intent(this, ContactListActivity.class);
319                     intent.putExtra(ImServiceConstants.EXTRA_INTENT_ACCOUNT_ID, accountId);
320                 }
321                 startActivity(intent);
322             } catch (RemoteException e) {
323                 // Ouch!  Service died!  We'll just disappear.
324                 Log.w(ImApp.LOG_TAG, "<SigningInActivity> Connection disappeared while signing in!");
325             }
326         } else if (state == ImConnection.DISCONNECTED) {
327             // sign in failed
328             Resources r = getResources();
329             new AlertDialog.Builder(this)
330                 .setTitle(R.string.error)
331                 .setMessage(r.getString(R.string.login_service_failed, mProviderName,
332                             error == null? "": ErrorResUtils.getErrorRes(r, error.getCode())))
333                 .setPositiveButton(R.string.ok,
334                         new DialogInterface.OnClickListener() {
335                             public void onClick(DialogInterface dialog, int whichButton) {
336                                 setResult(RESULT_CANCELED);
337                                 finish();
338                             }
339                         })
340                 .setCancelable(false)
341                 .show();
342         }
343     }
344 
log(String msg)345     private static final void log(String msg) {
346         Log.d(ImApp.LOG_TAG, "<SigningInActivity>" + msg);
347     }
348 
349     private final class MyConnectionListener extends ConnectionListenerAdapter {
MyConnectionListener(Handler handler)350         MyConnectionListener(Handler handler) {
351             super(handler);
352         }
353 
354         @Override
onConnectionStateChange(IImConnection connection, int state, ImErrorInfo error)355         public void onConnectionStateChange(IImConnection connection,
356                 int state, ImErrorInfo error) {
357             handleConnectionEvent(state, error);
358         }
359     }
360 }
361