Newer
Older
/*
* Copyright (C) 2004-2012 Savoir-Faire Linux Inc.
*
* Author: Adrien Beraud <adrien.beraud@gmail.com>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Additional permission under GNU GPL version 3 section 7:
*
* If you modify this program, or any covered work, by linking or
* combining it with the OpenSSL project's OpenSSL library (or a
* modified version of that library), containing parts covered by the
* terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
* grants you additional permission to convey the resulting work.
* Corresponding Source for a non-source form of such a combination
* shall include the source code for the parts of OpenSSL used as well
* as that of the covered work.
*/
package com.savoirfairelinux.sflphone.client;
import android.app.ActionBar;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import android.support.v13.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.content.LocalBroadcastManager;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.TextView;
import com.savoirfairelinux.sflphone.R;
import com.savoirfairelinux.sflphone.service.ISipService;
import com.savoirfairelinux.sflphone.service.SipService;
import com.savoirfairelinux.sflphone.utils.AccountList;
import com.savoirfairelinux.sflphone.utils.CallList;
import java.util.HashMap;
public class SFLPhoneHome extends Activity implements ActionBar.TabListener, OnClickListener
SectionsPagerAdapter mSectionsPagerAdapter = null;
Alexandre Savard
committed
static final String TAG = "SFLPhoneHome";
private static final int REQUEST_CODE_PREFERENCES = 1;
ImageButton buttonCall, buttonHangup;
private ContactListFragment mContactListFragment = null;
private CallElementList mCallElementList = null;
private HistorySectionFragment mHistorySectionFragment = null;
private ButtonSectionFragment mButtonSectionFragment = null;
private boolean mBound = false;
private ISipService service;
public AccountList mAccountList;
public CallList mCallList = new CallList(this);
private SFLphoneApplication mApplication;
private static final int ACTION_BAR_TAB_CONTACT = 0;
private static final int ACTION_BAR_TAB_CALL = 1;
private static final int ACTION_BAR_TAB_HISTORY = 2;
private static final int ACTION_BAR_TAB_TEST = 3;
Alexandre Savard
committed
/**
* The {@link ViewPager} that will host the section contents.
*/
ViewPager mViewPager;
Alexandre Savard
committed
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};
// public SFLPhoneHome extends Activity implements ActionBar.TabListener, OnClickListener
/* called before activity is killed, e.g. rotation */
@Override
protected void onSaveInstanceState(Bundle bundle) {
super.onSaveInstanceState(bundle);
for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
try {
/* putFragment (Bundle bundle, String key, Fragment fragment) */
getFragmentManager().putFragment(bundle, mSectionsPagerAdapter.getClassName(i), mSectionsPagerAdapter.getFragment(i));
} catch (IllegalStateException e) {
Log.e(TAG, "IllegalStateException: fragment=" + mSectionsPagerAdapter.getFragment(i));
}
}
Log.w(TAG, "onSaveInstanceState()");
}
Alexandre Savard
committed
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
mApplication = (SFLphoneApplication) getApplication();
// Bind to LocalService
if (!mBound) {
Log.i(TAG, "onStart: Binding service...");
Intent intent = new Intent(this, SipService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
Alexandre Savard
committed
setContentView(R.layout.activity_sflphone_home);
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
if (mSectionsPagerAdapter == null) {
mSectionsPagerAdapter = new SectionsPagerAdapter(getFragmentManager());
}
/* getFragment(Bundle, String) */
if (savedInstanceState != null) {
Log.w(TAG, "Activity restarted, recreating PagerAdapter...");
/* getFragment (Bundle bundle, String key) */
mContactListFragment = (ContactListFragment) getFragmentManager().getFragment(
savedInstanceState, mSectionsPagerAdapter.getClassName(ACTION_BAR_TAB_CONTACT));
mCallElementList = (CallElementList) getFragmentManager().getFragment(
savedInstanceState, mSectionsPagerAdapter.getClassName(ACTION_BAR_TAB_CALL));
mHistorySectionFragment = (HistorySectionFragment) getFragmentManager().getFragment(
savedInstanceState, mSectionsPagerAdapter.getClassName(ACTION_BAR_TAB_HISTORY));
mButtonSectionFragment = (ButtonSectionFragment) getFragmentManager().getFragment(
savedInstanceState, mSectionsPagerAdapter.getClassName(ACTION_BAR_TAB_TEST));
}
if (mContactListFragment == null) {
mContactListFragment = new ContactListFragment();
Log.w(TAG, "Recreated mContactListFragment=" + mContactListFragment);
}
if (mCallElementList == null) {
mCallElementList = new CallElementList();
Log.w(TAG, "Recreated mCallElementList=" + mCallElementList);
}
if (mHistorySectionFragment == null) {
mHistorySectionFragment = new HistorySectionFragment();
Log.w(TAG, "Recreated mHistorySectionFragment=" + mHistorySectionFragment);
}
if (mButtonSectionFragment == null) {
mButtonSectionFragment = new ButtonSectionFragment();
Log.w(TAG, "Recreated mButtonSectionFragment=" + mButtonSectionFragment);
}
Alexandre Savard
committed
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
final ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// final ActionBar actionBar = getActionBar();
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
// When swiping between different sections, select the corresponding tab.
// We can also use ActionBar.Tab#select() to do this if we have a reference to the
// Tab.
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener()
{
@Override
public void onPageSelected(int position)
{
actionBar.setSelectedNavigationItem(position);
}
});
// For each of the sections in the app, add a tab to the action bar.
for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
// Create a tab with text corresponding to the page title defined by the adapter.
// Also specify this Activity object, which implements the TabListener interface, as the
// listener for when this tab is selected.
Log.i(TAG, "adding tab: " + i);
actionBar.addTab(actionBar.newTab().setIcon(icon_res_id[i]).setText(mSectionsPagerAdapter.getPageTitle(i)).setTabListener(this));
}
actionBar.setSelectedNavigationItem(ACTION_BAR_TAB_CALL);
Alexandre Savard
committed
buttonCall = (ImageButton) findViewById(R.id.buttonCall);
buttonHangup = (ImageButton) findViewById(R.id.buttonHangUp);
// Change alpha from fully visible to invisible
animation = new AlphaAnimation(1, 0);
// duration - half a second
animation.setDuration(500);
// do not alter animation rate
animation.setInterpolator(new LinearInterpolator());
// Repeat animation infinitely
animation.setRepeatCount(Animation.INFINITE);
// Reverse
animation.setRepeatMode(Animation.REVERSE);
LocalBroadcastManager.getInstance(this).registerReceiver(mCallList, new IntentFilter("new-call-created"));
LocalBroadcastManager.getInstance(this).registerReceiver(mCallList, new IntentFilter("call-state-changed"));
LocalBroadcastManager.getInstance(this).registerReceiver(mCallList, new IntentFilter("incoming-call"));
mAccountList = mApplication.getAccountList();
Alexandre Savard
committed
LocalBroadcastManager.getInstance(this).registerReceiver(mAccountList, new IntentFilter("accounts-changed"));
LocalBroadcastManager.getInstance(this).registerReceiver(mAccountList, new IntentFilter("account-state-changed"));
SipCall.setSFLPhoneHomeContext(this);
Alexandre Savard
committed
}
@Override
protected void onStart() {
Log.i(TAG, "onStart");
super.onStart();
}
/* user gets back to the activity, e.g. through task manager */
@Override
protected void onRestart() {
super.onRestart();
}
/* activity gets back to the foreground and user input */
@Override
protected void onResume() {
Log.i(TAG, "onResume");
super.onResume();
}
/* activity no more in foreground */
@Override
protected void onPause() {
super.onPause();
}
/* activity is no longer visible */
@Override
protected void onStop() {
super.onStop();
}
/* activity finishes itself or is being killed by the system */
@Override
protected void onDestroy() {
/* stop the service, if no other bound user, no need to check if it is running */
if (mBound) {
Log.i(TAG, "onStop: Unbinding service...");
unbindService(mConnection);
mBound = false;
}
// Log.i(TAG, "onDestroy: stopping SipService...");
// stopService(new Intent(this, SipService.class));
// mApplication.setServiceRunning(false);
/* unregister broadcast receiver */
LocalBroadcastManager.getInstance(this).unregisterReceiver(mCallList);
LocalBroadcastManager.getInstance(this).unregisterReceiver(mAccountList);
super.onDestroy();
}
/** Defines callbacks for service binding, passed to bindService() */
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className,
IBinder binder) {
service = ISipService.Stub.asInterface(binder);
mApplication.setSipService(service);
Alexandre Savard
committed
mAccountList.setSipService(service);
Log.d(TAG, "Service connected service=" + service);
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
mApplication.setSipService(null);
mBound = false;
Log.w(TAG, "Service disconnected service=" + service);
// private void startSipService() {
// Thread thread = new Thread("StartSFLphoneService") {
// public void run() {
// Intent sipServiceIntent = new Intent(SFLPhoneHome.this, SipService.class);
// //sipServiceIntent.putExtra(ServiceConstants.EXTRA_OUTGOING_ACTIVITY, new ComponentName(SFLPhoneHome.this, SFLPhoneHome.class));
// startService(sipServiceIntent);
// mApplication.setServiceRunning(true);
// };
// };
// try {
// thread.start();
// } catch (IllegalThreadStateException e) {
// AlertDialog.Builder builder = new AlertDialog.Builder(this);
// builder.setMessage("Cannot start SFLPhone SipService!");
// AlertDialog alert = builder.create();
// alert.show();
// finish();
// }
// }
@Override
public boolean onOptionsItemSelected(MenuItem item) {
Log.i("SFLphone", "onOptionsItemSelected " + item.getItemId());
if(item.getItemId() != 0) {
// When the button is clicked, launch an activity through this intent
Intent launchPreferencesIntent = new Intent().setClass(this, SFLPhonePreferenceActivity.class);
// Make it a subactivity so we know when it returns
startActivityForResult(launchPreferencesIntent, REQUEST_CODE_PREFERENCES);
}
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
return super.onOptionsItemSelected(item);
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.activity_sflphone_home, menu);
return true;
}
@Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction)
{
}
@Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction)
{
// When the given tab is selected, switch to the corresponding page in the ViewPager.
mViewPager.setCurrentItem(tab.getPosition());
}
@Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction)
{
// Log.d(TAG, "onTabReselected");
}
public void onSelectedCallAction(SipCall call) {
int callState = call.getCallStateInt();
if((callState == SipCall.CALL_STATE_NONE) ||
(callState == SipCall.CALL_STATE_CURRENT)) {
buttonCall.setEnabled(false);
buttonHangup.setEnabled(true);
}
else {
buttonCall.setEnabled(true);
buttonHangup.setEnabled(false);
}
buttonCall.setTag(call);
buttonHangup.setTag(call);
}
public void onUnselectedCallAction() {
buttonCall.setTag(null);
buttonCall.setTag(null);
buttonCall.setEnabled(true);
buttonHangup.setEnabled(false);
}
public void setIncomingCallID(String accountID, String callID, String from) {
Log.i(TAG, "incomingCall(" + accountID + ", " + callID + ", " + from + ")");
buttonCall.startAnimation(animation);
buttonCall.setImageResource(R.drawable.ic_incomingcall);
}
/**
* A {@link FragmentStatePagerAdapter} that returns a fragment corresponding to
* one of the primary sections of the app.
*/
public class SectionsPagerAdapter extends FragmentStatePagerAdapter
{
public SectionsPagerAdapter(FragmentManager fm)
{
super(fm);
}
@Override
public Fragment getItem(int i)
{
Fragment fragment;
switch (i) {
case 0:
mContactListFragment = new ContactListFragment();
fragment = mContactListFragment;
break;
case 1:
mCallElementList = new CallElementList();
Alexandre Savard
committed
mCallElementList.setAccountList(mAccountList);
fragment = new HistorySectionFragment();
break;
case 3:
fragment = new ButtonSectionFragment();
Log.i(TAG, "getItem: fragment is " + fragment);
break;
default:
Log.e(TAG, "getItem: unknown tab position " + i);
return null;
}
Bundle args = new Bundle();
args.putInt(HistorySectionFragment.ARG_SECTION_NUMBER, i + 1);
fragment.setArguments(args);
return fragment;
}
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
public Fragment getFragment(int i)
{
Fragment fragment;
switch (i) {
case 0:
fragment = mContactListFragment;
break;
case 1:
fragment = mCallElementList;
break;
case 2:
fragment = mHistorySectionFragment;
break;
case 3:
fragment = mButtonSectionFragment;
break;
default:
Log.e(TAG, "getClassName: unknown fragment position " + i);
fragment = null;
}
// Log.w(TAG, "getFragment: fragment=" + fragment);
return fragment;
}
public String getClassName(int i)
{
String name;
switch (i) {
case 0:
name = ContactListFragment.class.getName();
break;
case 1:
name = CallElementList.class.getName();
break;
case 2:
name = HistorySectionFragment.class.getName();
break;
case 3:
name = ButtonSectionFragment.class.getName();
break;
default:
Log.e(TAG, "getClassName: unknown fragment position " + i);
return null;
}
// Log.w(TAG, "getClassName: name=" + name);
return name;
}
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
@Override
public int getCount()
{
return 4;
}
@Override
public CharSequence getPageTitle(int position)
{
switch (position) {
case 0:
return getString(R.string.title_section0).toUpperCase();
case 1:
return getString(R.string.title_section1).toUpperCase();
case 2:
return getString(R.string.title_section2).toUpperCase();
case 3:
return getString(R.string.title_section3).toUpperCase();
default:
Log.e(TAG, "getPageTitle: unknown tab position " + position);
break;
}
return null;
}
}
/**
* A dummy fragment representing a section of the app, but that simply
* displays dummy text.
*/
public static class HistorySectionFragment extends Fragment
public HistorySectionFragment()
{
setRetainInstance(true);
}
public static final String ARG_SECTION_NUMBER = "section_number";
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState)
{
TextView textView = new TextView(getActivity());
textView.setGravity(Gravity.CENTER);
Bundle args = getArguments();
textView.setText(Integer.toString(args.getInt(ARG_SECTION_NUMBER)));
textView.setText("java sucks");
return textView;
}
}
@Override
public void onClick(View view)
Log.i(TAG, "onClic from SFLPhoneHome");
switch (view.getId()) {
processingNewCallAction();
processingHangUpAction();
break;
default:
Log.w(TAG, "unknown button " + view.getId());
break;
public void processingNewCallAction() {
Alexandre Savard
committed
// String accountID = mAccountList.currentAccountID;
String accountID = mCallElementList.getSelectedAccount();
EditText editText = (EditText) findViewById(R.id.phoneNumberTextEntry);
String to = editText.getText().toString();
Random random = new Random();
String callID = Integer.toString(random.nextInt());
SipCall.CallInfo info = new SipCall.CallInfo();
info.mCallID = callID;
info.mAccountID = accountID;
info.mDisplayName = "Cool Guy!";
info.mPhone = to;
info.mEmail = "coolGuy@coolGuy.com";
info.mCallType = SipCall.CALL_TYPE_OUTGOING;
SipCall call = CallList.getCallInstance(info);
call.launchCallActivity(this);
call.placeCallUpdateUi();
call.notifyServicePlaceCall(service);
onSelectedCallAction(call);
}
public void processingHangUpAction() {
SipCall call = (SipCall)buttonHangup.getTag();
if(call != null)
call.notifyServiceHangup(service);