Skip to content
Snippets Groups Projects
SFLPhoneHome.java 21.1 KiB
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 java.util.Random;

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.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.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
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.EditText;
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;
    static final String TAG = "SFLPhoneHome";
    private static final int REQUEST_CODE_PREFERENCES = 1;
    ImageButton buttonCall, buttonHangup;
    static Animation animation;
    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;
    /**
     * The {@link ViewPager} that will host the section contents.
     */
    ViewPager mViewPager;
Emeric Vigier's avatar
Emeric Vigier 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()");
    }

    @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);
        }

        setContentView(R.layout.activity_sflphone_home);

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

        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);
        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();

        LocalBroadcastManager.getInstance(this).registerReceiver(mAccountList, new IntentFilter("accounts-changed"));
        LocalBroadcastManager.getInstance(this).registerReceiver(mAccountList, new IntentFilter("account-state-changed"));

        SipCall.setSFLPhoneHomeContext(this);
    @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);

    /** 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);
            Log.d(TAG, "Service connected service=" + service);
        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            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());
Emeric Vigier's avatar
Emeric Vigier committed
        if(item.getItemId() != 0) {
            // When the button is clicked, launch an activity through this intent
            Intent launchPreferencesIntent = new Intent().setClass(this, SFLPhonePreferenceActivity.class);
Emeric Vigier's avatar
Emeric Vigier committed
            // Make it a subactivity so we know when it returns
            startActivityForResult(launchPreferencesIntent, REQUEST_CODE_PREFERENCES);
Emeric Vigier's avatar
Emeric Vigier committed

        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);
Emeric Vigier's avatar
Emeric Vigier committed
    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);
Emeric Vigier's avatar
Emeric Vigier committed
    }

    /**
     * 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();
Emeric Vigier's avatar
Emeric Vigier committed
                fragment = mContactListFragment;
                break;
            case 1:
                mCallElementList = new CallElementList();
Emeric Vigier's avatar
Emeric Vigier committed
                SipCall.setCallElementList(mCallElementList);
                mCallElementList.setAccountList(mAccountList);
Emeric Vigier's avatar
Emeric Vigier committed
                fragment = mCallElementList;
                break;
            case 2:
                fragment = new HistorySectionFragment();
Emeric Vigier's avatar
Emeric Vigier committed
                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);
Emeric Vigier's avatar
Emeric Vigier committed
            fragment.setArguments(args);
            return fragment;
        }

        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;
        }

Emeric Vigier's avatar
Emeric Vigier committed
        @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
Emeric Vigier's avatar
Emeric Vigier committed
    {
        public HistorySectionFragment()
Emeric Vigier's avatar
Emeric Vigier committed
        {
            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");
Emeric Vigier's avatar
Emeric Vigier committed
            case R.id.buttonCall:
                processingNewCallAction();
Emeric Vigier's avatar
Emeric Vigier committed
                break;
            case R.id.buttonHangUp:
                processingHangUpAction();
Emeric Vigier's avatar
Emeric Vigier committed
                break;
            default:
                Log.w(TAG, "unknown button " + view.getId());
                break;
Emeric Vigier's avatar
Emeric Vigier committed
    }

    public void processingNewCallAction() {
        // 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);