blob: ad0692493ae9c3a65f108f07d21e6b468ba33772 [file] [log] [blame]
alisionf76de3b2013-04-16 15:35:22 -04001/*
2 * Copyright (C) 2004-2012 Savoir-Faire Linux Inc.
3 *
4 * Author: Adrien Beraud <adrien.beraud@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 * Additional permission under GNU GPL version 3 section 7:
21 *
22 * If you modify this program, or any covered work, by linking or
23 * combining it with the OpenSSL project's OpenSSL library (or a
24 * modified version of that library), containing parts covered by the
25 * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
26 * grants you additional permission to convey the resulting work.
27 * Corresponding Source for a non-source form of such a combination
28 * shall include the source code for the parts of OpenSSL used as well
29 * as that of the covered work.
30 */
31package com.savoirfairelinux.sflphone.client;
32
33import java.util.Random;
34
35import android.app.ActionBar;
36import android.app.Activity;
37import android.app.Fragment;
38import android.app.FragmentManager;
39import android.app.FragmentTransaction;
40import android.content.ComponentName;
41import android.content.Context;
42import android.content.Intent;
43import android.content.IntentFilter;
44import android.content.ServiceConnection;
45import android.os.Bundle;
46import android.os.IBinder;
47import android.support.v13.app.FragmentStatePagerAdapter;
48import android.support.v4.content.LocalBroadcastManager;
49import android.support.v4.view.ViewPager;
50import android.util.Log;
alisionf76de3b2013-04-16 15:35:22 -040051import android.view.Menu;
52import android.view.MenuItem;
53import android.view.View;
54import android.view.View.OnClickListener;
alisionf76de3b2013-04-16 15:35:22 -040055import android.view.animation.AlphaAnimation;
56import android.view.animation.Animation;
57import android.view.animation.LinearInterpolator;
58import android.widget.EditText;
59import android.widget.ImageButton;
alisionf76de3b2013-04-16 15:35:22 -040060
61import com.savoirfairelinux.sflphone.R;
alisiond9e29442013-04-17 16:10:18 -040062import com.savoirfairelinux.sflphone.client.receiver.AccountListReceiver;
63import com.savoirfairelinux.sflphone.client.receiver.CallListReceiver;
alisionf76de3b2013-04-16 15:35:22 -040064import com.savoirfairelinux.sflphone.fragments.ButtonSectionFragment;
65import com.savoirfairelinux.sflphone.fragments.CallElementListFragment;
66import com.savoirfairelinux.sflphone.fragments.ContactListFragment;
alisiond9e29442013-04-17 16:10:18 -040067import com.savoirfairelinux.sflphone.fragments.HistoryFragment;
alisionf76de3b2013-04-16 15:35:22 -040068import com.savoirfairelinux.sflphone.model.SipCall;
69import com.savoirfairelinux.sflphone.service.CallManagerCallBack;
70import com.savoirfairelinux.sflphone.service.ConfigurationManagerCallback;
71import com.savoirfairelinux.sflphone.service.ISipService;
72import com.savoirfairelinux.sflphone.service.SipService;
73
74public class SFLPhoneHomeActivity extends Activity implements ActionBar.TabListener, OnClickListener {
75 SectionsPagerAdapter mSectionsPagerAdapter = null;
76 static final String TAG = "SFLPhoneHome";
77 private static final int REQUEST_CODE_PREFERENCES = 1;
78 ImageButton buttonCall, buttonHangup;
79 static Animation animation;
80 private ContactListFragment mContactListFragment = null;
81 private CallElementListFragment mCallElementList = null;
alisiond9e29442013-04-17 16:10:18 -040082 private HistoryFragment mHistorySectionFragment = null;
alisionf76de3b2013-04-16 15:35:22 -040083 private ButtonSectionFragment mButtonSectionFragment = null;
84 private boolean mBound = false;
85 private ISipService service;
86 public AccountListReceiver mAccountList;
alisiond9e29442013-04-17 16:10:18 -040087 public CallListReceiver mCallList = new CallListReceiver(this);
alisionf76de3b2013-04-16 15:35:22 -040088 private SFLphoneApplication mApplication;
89
90 private static final int ACTION_BAR_TAB_CONTACT = 0;
91 private static final int ACTION_BAR_TAB_CALL = 1;
92 private static final int ACTION_BAR_TAB_HISTORY = 2;
93 private static final int ACTION_BAR_TAB_TEST = 3;
94
95 /**
96 * The {@link ViewPager} that will host the section contents.
97 */
98 ViewPager mViewPager;
99
100 final private int[] icon_res_id = { R.drawable.ic_tab_call, R.drawable.ic_tab_call, R.drawable.ic_tab_history, R.drawable.ic_tab_play_selected };
101
102 // public SFLPhoneHome extends Activity implements ActionBar.TabListener, OnClickListener
103
104 /* called before activity is killed, e.g. rotation */
105 @Override
106 protected void onSaveInstanceState(Bundle bundle) {
107 super.onSaveInstanceState(bundle);
108 for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
109 try {
110 /* putFragment (Bundle bundle, String key, Fragment fragment) */
111 getFragmentManager().putFragment(bundle, mSectionsPagerAdapter.getClassName(i), mSectionsPagerAdapter.getFragment(i));
112 } catch (IllegalStateException e) {
113 Log.e(TAG, "IllegalStateException: fragment=" + mSectionsPagerAdapter.getFragment(i));
114 }
115 }
116 Log.w(TAG, "onSaveInstanceState()");
117 }
118
119 @Override
120 public void onCreate(Bundle savedInstanceState) {
121 super.onCreate(savedInstanceState);
122
123 mApplication = (SFLphoneApplication) getApplication();
124
125 // Bind to LocalService
126 if (!mBound) {
127 Log.i(TAG, "onStart: Binding service...");
128 Intent intent = new Intent(this, SipService.class);
129 bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
130 }
131
132 setContentView(R.layout.activity_sflphone_home);
133
134 if (mSectionsPagerAdapter == null) {
135 mSectionsPagerAdapter = new SectionsPagerAdapter(getFragmentManager());
136 }
137
138 /* getFragment(Bundle, String) */
139 if (savedInstanceState != null) {
140 Log.w(TAG, "Activity restarted, recreating PagerAdapter...");
141 /* getFragment (Bundle bundle, String key) */
142 mContactListFragment = (ContactListFragment) getFragmentManager().getFragment(savedInstanceState,
143 mSectionsPagerAdapter.getClassName(ACTION_BAR_TAB_CONTACT));
144 mCallElementList = (CallElementListFragment) getFragmentManager().getFragment(savedInstanceState,
145 mSectionsPagerAdapter.getClassName(ACTION_BAR_TAB_CALL));
alisiond9e29442013-04-17 16:10:18 -0400146 mHistorySectionFragment = (HistoryFragment) getFragmentManager().getFragment(savedInstanceState,
alisionf76de3b2013-04-16 15:35:22 -0400147 mSectionsPagerAdapter.getClassName(ACTION_BAR_TAB_HISTORY));
148 mButtonSectionFragment = (ButtonSectionFragment) getFragmentManager().getFragment(savedInstanceState,
149 mSectionsPagerAdapter.getClassName(ACTION_BAR_TAB_TEST));
150 }
151
152 if (mContactListFragment == null) {
153 mContactListFragment = new ContactListFragment();
154 Log.w(TAG, "Recreated mContactListFragment=" + mContactListFragment);
155 }
156 if (mCallElementList == null) {
157 mCallElementList = new CallElementListFragment();
158 Log.w(TAG, "Recreated mCallElementList=" + mCallElementList);
159 }
160 if (mHistorySectionFragment == null) {
alisiond9e29442013-04-17 16:10:18 -0400161 mHistorySectionFragment = new HistoryFragment();
alisionf76de3b2013-04-16 15:35:22 -0400162 Log.w(TAG, "Recreated mHistorySectionFragment=" + mHistorySectionFragment);
163 }
164 if (mButtonSectionFragment == null) {
165 mButtonSectionFragment = new ButtonSectionFragment();
166 Log.w(TAG, "Recreated mButtonSectionFragment=" + mButtonSectionFragment);
167 }
168
169 final ActionBar actionBar = getActionBar();
170 actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
171 // final ActionBar actionBar = getActionBar();
172
173 // Set up the ViewPager with the sections adapter.
174 mViewPager = (ViewPager) findViewById(R.id.pager);
175 mViewPager.setAdapter(mSectionsPagerAdapter);
176
177 // When swiping between different sections, select the corresponding tab.
178 // We can also use ActionBar.Tab#select() to do this if we have a reference to the
179 // Tab.
180 mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
181 @Override
182 public void onPageSelected(int position) {
183 actionBar.setSelectedNavigationItem(position);
184 }
185 });
186
187 // For each of the sections in the app, add a tab to the action bar.
188 for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
189 // Create a tab with text corresponding to the page title defined by the adapter.
190 // Also specify this Activity object, which implements the TabListener interface, as the
191 // listener for when this tab is selected.
192 actionBar.addTab(actionBar.newTab().setIcon(icon_res_id[i]).setText(mSectionsPagerAdapter.getPageTitle(i)).setTabListener(this));
193 }
194
195 actionBar.setSelectedNavigationItem(ACTION_BAR_TAB_CALL);
196
197 buttonCall = (ImageButton) findViewById(R.id.buttonCall);
198 buttonHangup = (ImageButton) findViewById(R.id.buttonHangUp);
199
200 // Change alpha from fully visible to invisible
201 animation = new AlphaAnimation(1, 0);
202 // duration - half a second
203 animation.setDuration(500);
204 // do not alter animation rate
205 animation.setInterpolator(new LinearInterpolator());
206 // Repeat animation infinitely
207 animation.setRepeatCount(Animation.INFINITE);
208 // Reverse
209 animation.setRepeatMode(Animation.REVERSE);
210
211 IntentFilter callFilter = new IntentFilter(CallManagerCallBack.NEW_CALL_CREATED);
212 callFilter.addAction(CallManagerCallBack.INCOMING_CALL);
213 callFilter.addAction(CallManagerCallBack.CALL_STATE_CHANGED);
214 LocalBroadcastManager.getInstance(this).registerReceiver(mCallList, callFilter);
215
216 mAccountList = mApplication.getAccountList();
217 Log.w(TAG, "mAccountList=" + mAccountList + ", mCallElementList=" + mCallElementList);
218
219 IntentFilter accountFilter = new IntentFilter(ConfigurationManagerCallback.ACCOUNTS_CHANGED);
220 accountFilter.addAction(ConfigurationManagerCallback.ACCOUNT_STATE_CHANGED);
221 LocalBroadcastManager.getInstance(this).registerReceiver(mAccountList, accountFilter);
222
223 SipCall.setSFLPhoneHomeContext(this);
224 }
225
226 @Override
227 protected void onStart() {
228 Log.i(TAG, "onStart");
229 super.onStart();
230 }
231
232 /* user gets back to the activity, e.g. through task manager */
233 @Override
234 protected void onRestart() {
235 super.onRestart();
236 }
237
238 /* activity gets back to the foreground and user input */
239 @Override
240 protected void onResume() {
241 Log.i(TAG, "onResume");
242 super.onResume();
243 }
244
245 /* activity no more in foreground */
246 @Override
247 protected void onPause() {
248 super.onPause();
249 }
250
251 /* activity is no longer visible */
252 @Override
253 protected void onStop() {
254 super.onStop();
255 }
256
257 /* activity finishes itself or is being killed by the system */
258 @Override
259 protected void onDestroy() {
260 /* stop the service, if no other bound user, no need to check if it is running */
261 if (mBound) {
262 Log.i(TAG, "onStop: Unbinding service...");
263 unbindService(mConnection);
264 mBound = false;
265 }
266 // Log.i(TAG, "onDestroy: stopping SipService...");
267 // stopService(new Intent(this, SipService.class));
268 // mApplication.setServiceRunning(false);
269
270 /* unregister broadcast receiver */
271 LocalBroadcastManager.getInstance(this).unregisterReceiver(mCallList);
272 LocalBroadcastManager.getInstance(this).unregisterReceiver(mAccountList);
273
274 super.onDestroy();
275 }
276
277 /** Defines callbacks for service binding, passed to bindService() */
278 private ServiceConnection mConnection = new ServiceConnection() {
279
280 @Override
281 public void onServiceConnected(ComponentName className, IBinder binder) {
282 service = ISipService.Stub.asInterface(binder);
283 mApplication.setSipService(service);
284 mBound = true;
285 mAccountList.setSipService(service);
286 Log.d(TAG, "Service connected service=" + service);
287 }
288
289 @Override
290 public void onServiceDisconnected(ComponentName arg0) {
291 mApplication.setSipService(null);
292 mBound = false;
293 Log.d(TAG, "Service disconnected service=" + service);
294 }
295 };
296
297 // private void startSipService() {
298 // Thread thread = new Thread("StartSFLphoneService") {
299 // public void run() {
300 // Intent sipServiceIntent = new Intent(SFLPhoneHome.this, SipService.class);
301 // //sipServiceIntent.putExtra(ServiceConstants.EXTRA_OUTGOING_ACTIVITY, new ComponentName(SFLPhoneHome.this, SFLPhoneHome.class));
302 // startService(sipServiceIntent);
303 // mApplication.setServiceRunning(true);
304 // };
305 // };
306 // try {
307 // thread.start();
308 // } catch (IllegalThreadStateException e) {
309 // AlertDialog.Builder builder = new AlertDialog.Builder(this);
310 // builder.setMessage("Cannot start SFLPhone SipService!");
311 // AlertDialog alert = builder.create();
312 // alert.show();
313 // finish();
314 // }
315 // }
316
317 @Override
318 public boolean onOptionsItemSelected(MenuItem item) {
319 Log.i("SFLphone", "onOptionsItemSelected " + item.getItemId());
320 if (item.getItemId() != 0) {
321 // When the button is clicked, launch an activity through this intent
322 Intent launchPreferencesIntent = new Intent().setClass(this, SFLPhonePreferenceActivity.class);
323
324 // Make it a subactivity so we know when it returns
325 startActivityForResult(launchPreferencesIntent, REQUEST_CODE_PREFERENCES);
326 }
327
328 return super.onOptionsItemSelected(item);
329 }
330
331 @Override
332 public boolean onCreateOptionsMenu(Menu menu) {
333 getMenuInflater().inflate(R.menu.activity_sflphone_home, menu);
334 return true;
335 }
336
337 @Override
338 public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
339 }
340
341 @Override
342 public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
343 // When the given tab is selected, switch to the corresponding page in the ViewPager.
344 mViewPager.setCurrentItem(tab.getPosition());
345 }
346
347 @Override
348 public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
349 // Log.d(TAG, "onTabReselected");
350 }
351
352 public void onSelectedCallAction(SipCall call) {
353 int callState = call.getCallStateInt();
354
355 if ((callState == SipCall.CALL_STATE_NONE) || (callState == SipCall.CALL_STATE_CURRENT)) {
356 buttonCall.setEnabled(false);
357 buttonHangup.setEnabled(true);
358 } else {
359 buttonCall.setEnabled(true);
360 buttonHangup.setEnabled(false);
361 }
362
363 buttonCall.setTag(call);
364 buttonHangup.setTag(call);
365 }
366
367 public void onUnselectedCallAction() {
368 buttonCall.setTag(null);
369 buttonCall.setTag(null);
370
371 buttonCall.setEnabled(true);
372 buttonHangup.setEnabled(false);
373 }
374
375 public void setIncomingCallID(String accountID, String callID, String from) {
376 Log.i(TAG, "incomingCall(" + accountID + ", " + callID + ", " + from + ")");
377 buttonCall.startAnimation(animation);
378 buttonCall.setImageResource(R.drawable.ic_incomingcall);
379 }
380
381 /**
382 * A {@link FragmentStatePagerAdapter} that returns a fragment corresponding to one of the primary sections of the app.
383 */
384 public class SectionsPagerAdapter extends FragmentStatePagerAdapter {
385
386 public SectionsPagerAdapter(FragmentManager fm) {
387 super(fm);
388 }
389
390 @Override
391 public Fragment getItem(int i) {
392 Fragment fragment;
393
394 switch (i) {
395 case 0:
396 mContactListFragment = new ContactListFragment();
397 fragment = mContactListFragment;
398 Log.w(TAG, "getItem() ContactListFragment=" + fragment);
399 break;
400 case 1:
401 mCallElementList = new CallElementListFragment();
402 SipCall.setCallElementList(mCallElementList);
403 mCallElementList.setAccountList(mAccountList);
404 fragment = mCallElementList;
405 Log.w(TAG, "getItem() CallElementList=" + fragment);
406 break;
407 case 2:
alisiond9e29442013-04-17 16:10:18 -0400408 fragment = new HistoryFragment();
409 Log.w(TAG, "getItem() HistoryFragment=" + fragment);
alisionf76de3b2013-04-16 15:35:22 -0400410 break;
411 case 3:
412 fragment = new ButtonSectionFragment();
413 Log.w(TAG, "getItem() ButtonSectionFragment=" + fragment);
414 break;
415 default:
416 Log.e(TAG, "getItem() unknown tab position " + i);
417 return null;
418 }
419
420 // Log.i(TAG, "getItem() fragment is " + fragment);
421 Bundle args = new Bundle();
alisiond9e29442013-04-17 16:10:18 -0400422 args.putInt(HistoryFragment.ARG_SECTION_NUMBER, i + 1);
alisionf76de3b2013-04-16 15:35:22 -0400423 fragment.setArguments(args);
424 return fragment;
425 }
426
427 public Fragment getFragment(int i) {
428 Fragment fragment;
429
430 switch (i) {
431 case 0:
432 fragment = mContactListFragment;
433 break;
434 case 1:
435 fragment = mCallElementList;
436 break;
437 case 2:
438 fragment = mHistorySectionFragment;
439 break;
440 case 3:
441 fragment = mButtonSectionFragment;
442 break;
443 default:
444 Log.e(TAG, "getClassName: unknown fragment position " + i);
445 fragment = null;
446 }
447
448 // Log.w(TAG, "getFragment: fragment=" + fragment);
449 return fragment;
450 }
451
452 public String getClassName(int i) {
453 String name;
454
455 switch (i) {
456 case 0:
457 name = ContactListFragment.class.getName();
458 break;
459 case 1:
460 name = CallElementListFragment.class.getName();
461 break;
462 case 2:
alisiond9e29442013-04-17 16:10:18 -0400463 name = HistoryFragment.class.getName();
alisionf76de3b2013-04-16 15:35:22 -0400464 break;
465 case 3:
466 name = ButtonSectionFragment.class.getName();
467 break;
468 default:
469 Log.e(TAG, "getClassName: unknown fragment position " + i);
470 return null;
471 }
472
473 // Log.w(TAG, "getClassName: name=" + name);
474 return name;
475 }
476
477 @Override
478 public int getCount() {
479 return 4;
480 }
481
482 @Override
483 public CharSequence getPageTitle(int position) {
484 switch (position) {
485 case 0:
486 return getString(R.string.title_section0).toUpperCase();
487 case 1:
488 return getString(R.string.title_section1).toUpperCase();
489 case 2:
490 return getString(R.string.title_section2).toUpperCase();
491 case 3:
492 return getString(R.string.title_section3).toUpperCase();
493 default:
494 Log.e(TAG, "getPageTitle: unknown tab position " + position);
495 break;
496 }
497 return null;
498 }
499 }
500
alisionf76de3b2013-04-16 15:35:22 -0400501
502 @Override
503 public void onClick(View view) {
504 Log.i(TAG, "onClic from SFLPhoneHome");
505 switch (view.getId()) {
506 case R.id.buttonCall:
507 processingNewCallAction();
508 break;
509 case R.id.buttonHangUp:
510 processingHangUpAction();
511 break;
512 default:
513 Log.w(TAG, "unknown button " + view.getId());
514 break;
515 }
516 }
517
518 public void processingNewCallAction() {
519 // String accountID = mAccountList.currentAccountID;
520 Log.w(TAG, "processingNewCallAction() mCallElementList=" + mCallElementList);
521 String accountID = mCallElementList.getSelectedAccount();
522 EditText editText = (EditText) findViewById(R.id.phoneNumberTextEntry);
523 String to = editText.getText().toString();
524
525 Random random = new Random();
526 String callID = Integer.toString(random.nextInt());
527 SipCall.CallInfo info = new SipCall.CallInfo();
528
529 info.mCallID = callID;
530 info.mAccountID = accountID;
531 info.mDisplayName = "Cool Guy!";
532 info.mPhone = to;
533 info.mEmail = "coolGuy@coolGuy.com";
534 info.mCallType = SipCall.CALL_TYPE_OUTGOING;
535
alisiond9e29442013-04-17 16:10:18 -0400536 SipCall call = CallListReceiver.getCallInstance(info);
alisionf76de3b2013-04-16 15:35:22 -0400537 call.launchCallActivity(this);
538 call.placeCallUpdateUi();
539 call.notifyServicePlaceCall(service);
540
541 onSelectedCallAction(call);
542 }
543
544 public void processingHangUpAction() {
545 SipCall call = (SipCall) buttonHangup.getTag();
546 if (call != null)
547 call.notifyServiceHangup(service);
548 }
549}