diff --git a/AndroidManifest.xml b/AndroidManifest.xml index ccd6d1567dcf3a43c540461870956f3bda5ba305..a48df58e11ed207b75d70678dd55f08aea1f21e9 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -32,27 +32,41 @@ as that of the covered work. --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.sflphone" + android:installLocation="auto" android:versionCode="9" android:versionName="1.2.3.10" > + <supports-screens + android:anyDensity="true" + android:largeScreens="true" + android:normalScreens="true" + android:smallScreens="true" + android:xlargeScreens="true" /> + <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="19" /> <uses-permission android:name="android.permission.INTERNET" /> - <uses-permission android:name="android.permission.READ_CONTACTS" /> - <uses-permission android:name="android.permission.READ_PROFILE" /> - <uses-permission android:name="android.permission.CALL_PHONE" /> + <uses-permission android:name="android.permission.RECORD_AUDIO" /> + <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" /> + <uses-permission android:name="android.permission.CALL_PHONE" /> + <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> - <uses-permission android:name="android.permission.RECORD_AUDIO" /> + <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> + <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> + <uses-permission android:name="android.permission.READ_CONTACTS" /> + <uses-permission android:name="android.permission.READ_PROFILE" /> + <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.VIBRATE" /> - <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> + <uses-permission android:name="android.permission.WRITE_CALL_LOG" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> - <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> + <uses-permission android:name="android.permission.READ_LOGS" /> + <uses-permission android:name="android.permission.USE_SIP" /> <uses-feature android:name="android.hardware.wifi" @@ -86,14 +100,6 @@ as that of the covered work. <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> - <activity - android:name="org.sflphone.client.AccountsManagementActivity" - android:screenOrientation="portrait" - android:theme="@style/AppThemeWithoutOverlay" > - <meta-data - android:name="android.support.PARENT_ACTIVITY" - android:value="org.sflphone.client.SFLPhoneHomeActivity" /> - </activity> <activity android:name="org.sflphone.client.AccountWizard" android:screenOrientation="portrait" @@ -134,12 +140,6 @@ as that of the covered work. <action android:name=".service.SipService" /> </intent-filter> </service> - - <activity - android:name="org.sflphone.client.ActivityHolder" - android:label="@string/title_activity_sflphone_home" - android:theme="@style/AppThemeWithoutOverlay" > - </activity> </application> </manifest> \ No newline at end of file diff --git a/res/layout/activity_home.xml b/res/layout/activity_home.xml index 39a58834c6246c4e9190123b0a80f93fb1332dff..953845a5d083a479a91aa8daa0da804eb742529d 100644 --- a/res/layout/activity_home.xml +++ b/res/layout/activity_home.xml @@ -31,7 +31,6 @@ as that of the covered work. --> <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res/org.sflphone" android:id="@+id/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent" > @@ -41,36 +40,13 @@ as that of the covered work. android:layout_width="match_parent" android:layout_height="match_parent" > - <RelativeLayout - xmlns:app="http://schemas.android.com/apk/res/org.sflphone" + <FrameLayout + android:id="@+id/main_frame" android:layout_width="match_parent" android:layout_height="match_parent" + android:paddingTop="?android:attr/actionBarSize" android:orientation="vertical" > - - <ImageView - android:layout_width="match_parent" - android:layout_height="?android:attr/actionBarSize" - android:layout_alignParentTop="true" - android:background="@color/sfl_dark_blue" /> - - <org.sflphone.views.PagerSlidingTabStrip - android:id="@+id/pts_main" - android:layout_width="match_parent" - android:layout_height="?android:attr/actionBarSize" - android:layout_alignParentTop="true" - android:layout_marginTop="?android:attr/actionBarSize" - android:background="@color/sfl_blue_0" - app:shouldExpand="true" - app:indicatorColor="@color/sfl_light_blue" - app:underlineColor="@color/sfl_light_blue" /> - - <android.support.v4.view.ViewPager - android:id="@+id/pager" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_below="@+id/pts_main" - android:paddingBottom="@dimen/contact_drawer_handle_height" /> - </RelativeLayout> + </FrameLayout> <FrameLayout android:id="@+id/contacts_frame" diff --git a/res/layout/frag_about.xml b/res/layout/frag_about.xml index d0720de0068c792322eba588ef630ab53957cdbd..6e03f8e61d7d457ae1cd086ab864d7d818bc839b 100644 --- a/res/layout/frag_about.xml +++ b/res/layout/frag_about.xml @@ -4,45 +4,50 @@ android:layout_height="match_parent" android:padding="@dimen/padding_medium" > - <RelativeLayout + <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <ImageView android:id="@+id/logo" - android:layout_width="wrap_content" + android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_alignParentTop="true" android:src="@drawable/logo_sfl_coul_rgb" /> - <TextView - android:id="@+id/app_name" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_below="@+id/logo" - android:gravity="center" - android:text="@string/app_name" - android:textAppearance="?android:attr/textAppearanceLarge" /> - - <TextView - android:id="@+id/web_site" + <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" - android:gravity="center" - android:layout_below="@+id/app_name" - android:text="@string/web_site" - android:textAppearance="?android:attr/textAppearanceSmall" /> + android:background="@drawable/item_generic_selector" > - <TextView - android:id="@+id/licence" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_below="@+id/web_site" - android:layout_centerHorizontal="true" - android:gravity="center" - android:text="@string/copyright" - android:textAppearance="?android:attr/textAppearanceSmall" /> - </RelativeLayout> + <TextView + android:id="@+id/app_name" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_alignParentTop="true" + android:gravity="center" + android:text="@string/app_name" + android:textAppearance="?android:attr/textAppearanceLarge" /> + + <TextView + android:id="@+id/web_site" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_below="@+id/app_name" + android:gravity="center" + android:text="@string/web_site" + android:textAppearance="?android:attr/textAppearanceSmall" /> + + <TextView + android:id="@+id/licence" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_below="@+id/web_site" + android:layout_centerHorizontal="true" + android:gravity="center" + android:text="@string/copyright" + android:textAppearance="?android:attr/textAppearanceSmall" /> + </RelativeLayout> + </LinearLayout> </ScrollView> \ No newline at end of file diff --git a/res/layout/frag_accounts_list.xml b/res/layout/frag_accounts_list.xml index 52c6f11337e38f38f8ce497eb391639b9ef0a0de..ce82933f753c96171406191eebf89a5e561ce52d 100644 --- a/res/layout/frag_accounts_list.xml +++ b/res/layout/frag_accounts_list.xml @@ -24,6 +24,7 @@ android:id="@android:id/list" android:layout_width="match_parent" android:layout_height="wrap_content" + android:background="@color/white" android:choiceMode="multipleChoice" android:dividerHeight="1px" android:visibility="gone" @@ -72,6 +73,7 @@ <ListView android:id="@+id/ip2ip" android:layout_width="match_parent" - android:layout_height="wrap_content" /> + android:layout_height="wrap_content" + android:background="@color/white" /> </LinearLayout> \ No newline at end of file diff --git a/res/layout/frag_call_list.xml b/res/layout/frag_call_list.xml index d4d2726e0f9491233028aea437f48ada98dceb19..ffe3d463567c5cec275be7260e4db3b0a8806894 100644 --- a/res/layout/frag_call_list.xml +++ b/res/layout/frag_call_list.xml @@ -1,16 +1,119 @@ <?xml version="1.0" encoding="utf-8"?> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" +<!-- +Copyright (C) 2004-2013 Savoir-Faire Linux Inc. + +Author: Alexandre Lision <alexandre.lision@savoirfairelinux.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. +--> + +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" - android:layout_height="match_parent" - android:background="@color/lighter_gray" - android:orientation="vertical" > + android:layout_height="match_parent" > + + <RelativeLayout + android:id="@+id/calls_layouts" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_alignParentTop="true" + android:layout_margin="10dp" + android:background="@drawable/item_generic_selector" > + + <LinearLayout + android:id="@+id/linear1" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_alignParentLeft="true" + android:layout_alignParentTop="true" + android:weightSum="4" > + + <TextView + android:id="@+id/calls_counter" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:gravity="center" + android:textSize="40sp" /> - <ListView - android:id="@+id/call_list" + <TextView + android:id="@+id/textView2" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="3" + android:text="@string/home_calls_title" + android:textSize="30sp" /> + </LinearLayout> + + <ListView + android:id="@+id/calls_list" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_below="@+id/linear1" > + </ListView> + </RelativeLayout> + + <RelativeLayout + android:id="@+id/confs_layouts" android:layout_width="match_parent" android:layout_height="wrap_content" - android:choiceMode="singleChoice" - android:clickable="true" > - </ListView> + android:layout_below="@+id/calls_layouts" + android:layout_margin="10dp" + android:background="@drawable/item_generic_selector" > + + <LinearLayout + android:id="@+id/linear2" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_alignParentLeft="true" + android:layout_alignParentTop="true" + android:weightSum="4" > + + <TextView + android:id="@+id/confs_counter" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:gravity="center" + android:textSize="40sp" /> + + <TextView + android:id="@+id/textView4" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="3" + android:text="@string/home_conferences_title" + android:textSize="30sp" /> + </LinearLayout> + + <ListView + android:id="@+id/confs_list" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_below="@+id/linear2" > + </ListView> + </RelativeLayout> -</LinearLayout> \ No newline at end of file +</RelativeLayout> \ No newline at end of file diff --git a/res/layout/frag_home.xml b/res/layout/frag_home.xml index ffe3d463567c5cec275be7260e4db3b0a8806894..2653f764a89b30f724634a9438ce0287485ee2d9 100644 --- a/res/layout/frag_home.xml +++ b/res/layout/frag_home.xml @@ -1,119 +1,30 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -Copyright (C) 2004-2013 Savoir-Faire Linux Inc. - -Author: Alexandre Lision <alexandre.lision@savoirfairelinux.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. ---> - <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res/org.sflphone" android:layout_width="match_parent" - android:layout_height="match_parent" > + android:layout_height="match_parent" + android:orientation="vertical" > - <RelativeLayout - android:id="@+id/calls_layouts" + <ImageView android:layout_width="match_parent" - android:layout_height="wrap_content" + android:layout_height="?android:attr/actionBarSize" android:layout_alignParentTop="true" - android:layout_margin="10dp" - android:background="@drawable/item_generic_selector" > - - <LinearLayout - android:id="@+id/linear1" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_alignParentLeft="true" - android:layout_alignParentTop="true" - android:weightSum="4" > - - <TextView - android:id="@+id/calls_counter" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_weight="1" - android:gravity="center" - android:textSize="40sp" /> - - <TextView - android:id="@+id/textView2" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_weight="3" - android:text="@string/home_calls_title" - android:textSize="30sp" /> - </LinearLayout> - - <ListView - android:id="@+id/calls_list" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_below="@+id/linear1" > - </ListView> - </RelativeLayout> + android:background="@color/sfl_dark_blue" /> - <RelativeLayout - android:id="@+id/confs_layouts" + <org.sflphone.views.PagerSlidingTabStrip + android:id="@+id/pts_main" android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_below="@+id/calls_layouts" - android:layout_margin="10dp" - android:background="@drawable/item_generic_selector" > - - <LinearLayout - android:id="@+id/linear2" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_alignParentLeft="true" - android:layout_alignParentTop="true" - android:weightSum="4" > - - <TextView - android:id="@+id/confs_counter" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_weight="1" - android:gravity="center" - android:textSize="40sp" /> - - <TextView - android:id="@+id/textView4" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_weight="3" - android:text="@string/home_conferences_title" - android:textSize="30sp" /> - </LinearLayout> + android:layout_height="?android:attr/actionBarSize" + android:layout_alignParentTop="true" + android:background="@color/sfl_blue_0" + app:indicatorColor="@color/sfl_light_blue" + app:shouldExpand="true" + app:underlineColor="@color/sfl_light_blue" /> - <ListView - android:id="@+id/confs_list" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_below="@+id/linear2" > - </ListView> - </RelativeLayout> + <android.support.v4.view.ViewPager + android:id="@+id/pager" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_below="@+id/pts_main" + android:paddingBottom="@dimen/contact_drawer_handle_height" /> </RelativeLayout> \ No newline at end of file diff --git a/res/values/arrays.xml b/res/values/arrays.xml index 55114779d41b16e69b141657942561b054f2b00e..95038b170b6f7d34463e3b76d9d7f7863a831d0f 100644 --- a/res/values/arrays.xml +++ b/res/values/arrays.xml @@ -32,6 +32,7 @@ as that of the covered work. <resources> <string-array name="menu_items_param"> + <item>@string/menu_item_home</item> <item>@string/menu_item_accounts</item> <item>@string/menu_item_about</item> </string-array> diff --git a/src/org/sflphone/adapters/AccountSelectionAdapter.java b/src/org/sflphone/adapters/AccountSelectionAdapter.java index cb34f16685bb6dec138e771f0855df5030ad3a2e..75227c41b56ab29e84c7cd16eb82aafe61129b18 100644 --- a/src/org/sflphone/adapters/AccountSelectionAdapter.java +++ b/src/org/sflphone/adapters/AccountSelectionAdapter.java @@ -66,8 +66,6 @@ public class AccountSelectionAdapter extends BaseAdapter { entryView.alias.setText(accounts.get(pos).getAlias()); - Log.i(TAG, "getView:" + accounts.get(pos).getRegistered_state()); - entryView.host.setText(accounts.get(pos).getHost() + " - " + accounts.get(pos).getRegistered_state()); // accManager.displayAccountDetails(accounts.get(pos), entryView); if (pos == selectedAccount) { diff --git a/src/org/sflphone/adapters/SectionsPagerAdapter.java b/src/org/sflphone/adapters/SectionsPagerAdapter.java index 4fea902371484528cddb534b60096866a09f75fe..dc68879cd5123aafd8601058731ffa79010b9838 100644 --- a/src/org/sflphone/adapters/SectionsPagerAdapter.java +++ b/src/org/sflphone/adapters/SectionsPagerAdapter.java @@ -6,7 +6,7 @@ import java.util.Locale; import org.sflphone.R; import org.sflphone.fragments.DialingFragment; import org.sflphone.fragments.HistoryFragment; -import org.sflphone.fragments.HomeFragment; +import org.sflphone.fragments.CallListFragment; import org.sflphone.views.PagerSlidingTabStrip; import android.app.Fragment; @@ -28,7 +28,7 @@ public class SectionsPagerAdapter extends FragmentStatePagerAdapter implements P mContext = c; fragments = new ArrayList<Fragment>(); fragments.add(new DialingFragment()); - fragments.add(new HomeFragment()); + fragments.add(new CallListFragment()); fragments.add(new HistoryFragment()); } @@ -46,7 +46,7 @@ public class SectionsPagerAdapter extends FragmentStatePagerAdapter implements P name = DialingFragment.class.getName(); break; case 1: - name = HomeFragment.class.getName(); + name = CallListFragment.class.getName(); break; case 2: name = HistoryFragment.class.getName(); @@ -85,7 +85,7 @@ public class SectionsPagerAdapter extends FragmentStatePagerAdapter implements P public void updateHome() { try { - ((HomeFragment) fragments.get(1)).updateLists(); + ((CallListFragment) fragments.get(1)).updateLists(); } catch (RemoteException e) { e.printStackTrace(); } catch (Exception e1) { diff --git a/src/org/sflphone/client/AccountsManagementActivity.java b/src/org/sflphone/client/AccountsManagementActivity.java deleted file mode 100644 index b5f6405507e9e5f92aaffb6908923e641794cec4..0000000000000000000000000000000000000000 --- a/src/org/sflphone/client/AccountsManagementActivity.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2004-2013 Savoir-Faire Linux Inc. - * - * Author: Alexandre Savard <alexandre.savard@savoirfairelinux.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 org.sflphone.client; - -import org.sflphone.R; -import org.sflphone.fragments.AccountsManagementFragment; -import org.sflphone.service.ISipService; -import org.sflphone.service.SipService; - -import android.app.Activity; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.os.Bundle; -import android.os.IBinder; -import android.util.Log; -import android.view.MenuItem; - -public class AccountsManagementActivity extends Activity implements AccountsManagementFragment.Callbacks{ - - static final String TAG = AccountsManagementActivity.class.getSimpleName(); - private boolean mBound = false; - private ISipService service; - - - private ServiceConnection mConnection = new ServiceConnection() { - - @Override - public void onServiceConnected(ComponentName className, IBinder binder) { - service = ISipService.Stub.asInterface(binder); - mBound = true; - Log.d(TAG, "Service connected"); - - getFragmentManager().beginTransaction().replace(R.id.list_accounts_frame, new AccountsManagementFragment()).commit(); - } - - @Override - public void onServiceDisconnected(ComponentName arg0) { - mBound = false; - Log.d(TAG, "Service disconnected"); - } - }; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - Log.i(TAG, "onCreate SFLPhonePreferenceActivity"); - - setContentView(R.layout.activity_mgmt_accounts); - - getActionBar().setDisplayHomeAsUpEnabled(true); - - if (!mBound) { - Log.i(TAG, "onCreate: Binding service..."); - Intent intent = new Intent(this, SipService.class); - bindService(intent, mConnection, Context.BIND_AUTO_CREATE); - } - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - finish(); - return true; - default: - return false; - } - } - - @Override - protected void onDestroy() { - - if (mBound) { - unbindService(mConnection); - mBound = false; - } - super.onDestroy(); - } - - - @Override - public ISipService getService() { - return service; - } - -} diff --git a/src/org/sflphone/client/ActivityHolder.java b/src/org/sflphone/client/ActivityHolder.java deleted file mode 100644 index 34d167e47514f27bae8d9129cd718aa446b3270b..0000000000000000000000000000000000000000 --- a/src/org/sflphone/client/ActivityHolder.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2004-2013 Savoir-Faire Linux Inc. - * - * Author: Alexandre Lision <alexandre.lision@savoirfairelinux.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 org.sflphone.client; - -import org.sflphone.R; -import org.sflphone.fragments.AboutFragment; -import org.sflphone.fragments.HelpGesturesFragment; - -import android.app.Activity; -import android.app.FragmentTransaction; -import android.os.Bundle; -import android.view.MenuItem; - -/** - * This Activity holds some conex fragments not requiring a lot of interaction: HelpGesturesFragment, LegalFragment, ContributeFragment - * @author lisional - * - */ -public class ActivityHolder extends Activity { - - public interface args { - int FRAG_GESTURES = 0; - int FRAG_ABOUT= 1; - } - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_holder); - - - FragmentTransaction ft = getFragmentManager().beginTransaction(); - switch(getIntent().getIntExtra("ActivityHolder.args", -1)){ - case args.FRAG_GESTURES: - ft.replace(R.id.frag_container, new HelpGesturesFragment()); - break; - case args.FRAG_ABOUT: - ft.replace(R.id.frag_container, new AboutFragment()); - break; - } - - ft.commit(); - - getActionBar().setDisplayHomeAsUpEnabled(true); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - finish(); - return true; - default: - return true; - } - } - -} diff --git a/src/org/sflphone/client/CallActivity.java b/src/org/sflphone/client/CallActivity.java index 70b78e7be6437aef77bf248c6313f2fa23ae360e..7d3c3d25f5402b817952f4d532b246299cd7013c 100644 --- a/src/org/sflphone/client/CallActivity.java +++ b/src/org/sflphone/client/CallActivity.java @@ -67,6 +67,8 @@ import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; +import android.os.PowerManager; +import android.os.PowerManager.WakeLock; import android.os.RemoteException; import android.os.SystemClock; import android.support.v4.widget.SlidingPaneLayout; @@ -87,6 +89,8 @@ public class CallActivity extends Activity implements CallInterface, IMFragment. IMFragment mIMFragment; CallFragment mCurrentCallFragment; + + /* result code sent in case of call failure */ public static int RESULT_FAILURE = -10; private CallProximityManager mProximityManager; @@ -104,6 +108,9 @@ public class CallActivity extends Activity implements CallInterface, IMFragment. mSlidingPaneLayout.setParallaxDistance(500); mSlidingPaneLayout.setSliderFadeColor(Color.TRANSPARENT); + Window w = getWindow(); + w.setFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED, WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED); + mSlidingPaneLayout.setPanelSlideListener(new SlidingPaneLayout.PanelSlideListener() { @Override @@ -184,8 +191,10 @@ public class CallActivity extends Activity implements CallInterface, IMFragment. protected void onDestroy() { unregisterReceiver(mReceiver); unbindService(mConnection); + mProximityManager.stopTracking(); mProximityManager.release(0); + super.onDestroy(); } diff --git a/src/org/sflphone/client/HomeActivity.java b/src/org/sflphone/client/HomeActivity.java index 81d1e0ab038751cdb485dad9e8b0b8101beb314d..fce72876862a4badc1741e3bd3654506a7184e4c 100644 --- a/src/org/sflphone/client/HomeActivity.java +++ b/src/org/sflphone/client/HomeActivity.java @@ -41,7 +41,9 @@ import java.util.Timer; import java.util.TimerTask; import org.sflphone.R; -import org.sflphone.adapters.SectionsPagerAdapter; +import org.sflphone.fragments.AboutFragment; +import org.sflphone.fragments.AccountsManagementFragment; +import org.sflphone.fragments.CallListFragment; import org.sflphone.fragments.ContactListFragment; import org.sflphone.fragments.DialingFragment; import org.sflphone.fragments.HistoryFragment; @@ -55,12 +57,13 @@ import org.sflphone.receivers.CallReceiver; import org.sflphone.service.CallManagerCallBack; import org.sflphone.service.ISipService; import org.sflphone.service.SipService; -import org.sflphone.views.PagerSlidingTabStrip; import org.sflphone.views.SlidingUpPanelLayout; import org.sflphone.views.SlidingUpPanelLayout.PanelSlideListener; import android.app.Activity; import android.app.AlertDialog; +import android.app.Fragment; +import android.app.FragmentManager.BackStackEntry; import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; @@ -80,21 +83,18 @@ import android.provider.ContactsContract.CommonDataKinds.Phone; import android.provider.ContactsContract.CommonDataKinds.SipAddress; import android.support.v4.app.ActionBarDrawerToggle; import android.support.v4.view.GravityCompat; -import android.support.v4.view.ViewPager; import android.support.v4.widget.DrawerLayout; import android.util.Log; import android.view.Gravity; import android.view.MenuItem; import android.view.View; -import android.view.WindowManager; import android.widget.RelativeLayout; import android.widget.Toast; -public class HomeActivity extends Activity implements DialingFragment.Callbacks, ContactListFragment.Callbacks, HomeFragment.Callbacks, - HistoryFragment.Callbacks, CallInterface, MenuFragment.Callbacks { +public class HomeActivity extends Activity implements DialingFragment.Callbacks, AccountsManagementFragment.Callbacks, ContactListFragment.Callbacks, + CallListFragment.Callbacks, HistoryFragment.Callbacks, CallInterface, MenuFragment.Callbacks { - SectionsPagerAdapter mSectionsPagerAdapter = null; - static final String TAG = "HomeActivity"; + static final String TAG = HomeActivity.class.getSimpleName(); private ContactListFragment mContactsFragment = null; private MenuFragment fMenu; @@ -112,15 +112,13 @@ public class HomeActivity extends Activity implements DialingFragment.Callbacks, SlidingUpPanelLayout mContactDrawer; private DrawerLayout mNavigationDrawer; private ActionBarDrawerToggle mDrawerToggle; - /** - * The {@link ViewPager} that will host the section contents. - */ - ViewPager mViewPager; CallReceiver callReceiver; private boolean isClosing = false; private Timer t = new Timer(); + private Fragment fContent; + /* called before activity is killed, e.g. rotation */ @Override protected void onSaveInstanceState(Bundle bundle) { @@ -189,10 +187,6 @@ public class HomeActivity extends Activity implements DialingFragment.Callbacks, } }); - // Set up the ViewPager with the sections adapter. - mViewPager = (ViewPager) findViewById(R.id.pager); - mViewPager.setPageTransformer(true, new ZoomOutPageTransformer(0.7f)); - mTitle = mDrawerTitle = getTitle(); mNavigationDrawer = (DrawerLayout) findViewById(R.id.drawer_layout); @@ -335,6 +329,15 @@ public class HomeActivity extends Activity implements DialingFragment.Callbacks, return; } + if (getFragmentManager().getBackStackEntryCount() > 0) { + BackStackEntry entry = getFragmentManager().getBackStackEntryAt(getFragmentManager().getBackStackEntryCount() - 1); + + fContent = getFragmentManager().findFragmentByTag(entry.getName()); + + getFragmentManager().popBackStack(); + return; + } + if (isClosing) { super.onBackPressed(); t.cancel(); @@ -398,16 +401,9 @@ public class HomeActivity extends Activity implements DialingFragment.Callbacks, try { fMenu = new MenuFragment(); - getFragmentManager().beginTransaction().replace(R.id.left_drawer, fMenu).commit(); - mSectionsPagerAdapter = new SectionsPagerAdapter(HomeActivity.this, getFragmentManager()); - - mViewPager.setOffscreenPageLimit(2); - mViewPager.setAdapter(mSectionsPagerAdapter); - mViewPager.setCurrentItem(1); + fContent = new HomeFragment(); + getFragmentManager().beginTransaction().replace(R.id.left_drawer, fMenu).replace(R.id.main_frame, fContent).commit(); - final PagerSlidingTabStrip strip = PagerSlidingTabStrip.class.cast(findViewById(R.id.pts_main)); - - strip.setViewPager(mViewPager); service.destroyNotification(); } catch (RemoteException e) { Log.e(TAG, e.toString()); @@ -478,7 +474,7 @@ public class HomeActivity extends Activity implements DialingFragment.Callbacks, String cID = b.getString("CallID"); String state = b.getString("State"); Log.i(TAG, "callStateChanged" + cID + " " + state); - mSectionsPagerAdapter.updateHome(); + // mSectionsPagerAdapter.updateHome(); } @@ -677,20 +673,6 @@ public class HomeActivity extends Activity implements DialingFragment.Callbacks, startActivityForResult(intent, REQUEST_CODE_CALL); } - public class ZoomOutPageTransformer implements ViewPager.PageTransformer { - private static final float MIN_ALPHA = .6f; - - public ZoomOutPageTransformer(float scalingStart) { - super(); - } - - @Override - public void transformPage(View page, float position) { - final float normalizedposition = Math.abs(Math.abs(position) - 1); - page.setAlpha(MIN_ALPHA + (1.f - MIN_ALPHA) * normalizedposition); - } - } - @Override public void setDragView(RelativeLayout relativeLayout) { mContactDrawer.setDragView(relativeLayout); @@ -702,15 +684,20 @@ public class HomeActivity extends Activity implements DialingFragment.Callbacks, switch (pos) { case 0: - in.setClass(this, AccountsManagementActivity.class); - startActivityForResult(in, HomeActivity.REQUEST_CODE_PREFERENCES); + fContent = new HomeFragment(); + getFragmentManager().beginTransaction().replace(R.id.main_frame, fContent).addToBackStack("HomeTransac").commit(); break; case 1: - in.putExtra("ActivityHolder.args", ActivityHolder.args.FRAG_ABOUT); - in.setClass(this, ActivityHolder.class); - startActivity(in); + fContent = new AccountsManagementFragment(); + getFragmentManager().beginTransaction().replace(R.id.main_frame, fContent).addToBackStack("AccountsTransac").commit(); + break; + case 2: + fContent = new AboutFragment(); + getFragmentManager().beginTransaction().replace(R.id.main_frame, fContent).addToBackStack("AboutTransac").commit(); break; } + + mNavigationDrawer.closeDrawers(); } } diff --git a/src/org/sflphone/fragments/AccountCreationFragment.java b/src/org/sflphone/fragments/AccountCreationFragment.java index 3b3032cfff015b2865f3e34c7a66b98291427a4c..7aed9da7f00aa8d920a21264730d8d4c856d931b 100644 --- a/src/org/sflphone/fragments/AccountCreationFragment.java +++ b/src/org/sflphone/fragments/AccountCreationFragment.java @@ -4,7 +4,7 @@ import java.util.HashMap; import org.sflphone.R; import org.sflphone.account.AccountDetailBasic; -import org.sflphone.client.AccountsManagementActivity; +import org.sflphone.client.HomeActivity; import org.sflphone.service.ISipService; import android.app.Activity; @@ -208,7 +208,7 @@ public class AccountCreationFragment extends Fragment { e.printStackTrace(); } - Intent resultIntent = new Intent(getActivity(), AccountsManagementActivity.class); + Intent resultIntent = new Intent(getActivity(), HomeActivity.class); getActivity().setResult(Activity.RESULT_OK, resultIntent); resultIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); startActivity(resultIntent); diff --git a/src/org/sflphone/fragments/CallFragment.java b/src/org/sflphone/fragments/CallFragment.java index 452c218ab5083fa9081683bb60815cf032f04dbc..354c3ffcb32065538f5b11d7ce670ca524946aef 100644 --- a/src/org/sflphone/fragments/CallFragment.java +++ b/src/org/sflphone/fragments/CallFragment.java @@ -55,7 +55,9 @@ import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.PointF; import android.os.Bundle; +import android.os.PowerManager; import android.os.RemoteException; +import android.os.PowerManager.WakeLock; import android.util.Log; import android.view.KeyEvent; import android.view.LayoutInflater; @@ -90,6 +92,10 @@ public class CallFragment extends Fragment implements Callback { private ToggleButton speakers; + private PowerManager powerManager; + // Screen wake lock for incoming call + private WakeLock wakeLock; + private BubblesView view; private BubbleModel model; @@ -108,6 +114,16 @@ public class CallFragment extends Fragment implements Callback { Log.e(TAG, "BUBBLE_SIZE " + BUBBLE_SIZE); this.setHasOptionsMenu(true); + powerManager = (PowerManager) getActivity().getSystemService(Context.POWER_SERVICE); + wakeLock = powerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.ON_AFTER_RELEASE, + "org.sflphone.onIncomingCall"); + wakeLock.setReferenceCounted(false); + + Log.d(TAG, "Acquire wake up lock"); + if (wakeLock != null && !wakeLock.isHeld()) { + wakeLock.acquire(); + } + } /** @@ -200,6 +216,10 @@ public class CallFragment extends Fragment implements Callback { @Override public void onPause() { super.onPause(); + if (wakeLock != null && wakeLock.isHeld()) { + wakeLock.release(); + } + } @Override diff --git a/src/org/sflphone/fragments/CallListFragment.java b/src/org/sflphone/fragments/CallListFragment.java index f26d9e7ea35b134a90cd3a73028439f8f797e3c8..e25f92fd7c935c3f54bcfd886a5f96f5cf3e8d86 100644 --- a/src/org/sflphone/fragments/CallListFragment.java +++ b/src/org/sflphone/fragments/CallListFragment.java @@ -28,30 +28,30 @@ * shall include the source code for the parts of OpenSSL used as well * as that of the covered work. */ - package org.sflphone.fragments; import java.util.ArrayList; import java.util.HashMap; +import java.util.Observable; +import java.util.Observer; import org.sflphone.R; +import org.sflphone.model.CallTimer; import org.sflphone.model.Conference; import org.sflphone.model.SipCall; import org.sflphone.service.ISipService; import android.app.Activity; -import android.app.AlertDialog; -import android.app.Dialog; -import android.app.DialogFragment; import android.app.Fragment; import android.content.ClipData; import android.content.ClipData.Item; import android.content.Context; -import android.content.DialogInterface; import android.content.Intent; import android.graphics.Color; import android.os.Bundle; +import android.os.Handler; import android.os.RemoteException; +import android.os.SystemClock; import android.os.Vibrator; import android.util.Log; import android.view.DragEvent; @@ -63,31 +63,22 @@ import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.AdapterView.OnItemLongClickListener; -import android.widget.ArrayAdapter; import android.widget.BaseAdapter; -import android.widget.ListAdapter; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; public class CallListFragment extends Fragment { - static final String TAG = CallListFragment.class.getSimpleName(); + private static final String TAG = CallListFragment.class.getSimpleName(); private Callbacks mCallbacks = sDummyCallbacks; - - CallListAdapter mAdapter; + private TextView nb_calls, nb_confs; + CallListAdapter confs_adapter, calls_adapter; + CallTimer timer; public static final int REQUEST_TRANSFER = 10; public static final int REQUEST_CONF = 20; - @Override - public void onCreate(Bundle savedBundle) { - super.onCreate(savedBundle); - - mAdapter = new CallListAdapter(getActivity()); - - } - /** * A dummy implementation of the {@link Callbacks} interface that does nothing. Used only when this fragment is not attached to an activity. */ @@ -95,15 +86,12 @@ public class CallListFragment extends Fragment { @Override public ISipService getService() { + Log.i(TAG, "I'm a dummy"); return null; } @Override - public void onCallSelected(Conference conf) { - } - - @Override - public void onCallsTerminated() { + public void selectedCall(Conference c) { } }; @@ -112,11 +100,10 @@ public class CallListFragment extends Fragment { * */ public interface Callbacks { - public ISipService getService(); - public void onCallSelected(Conference conf); + public ISipService getService(); - public void onCallsTerminated(); + public void selectedCall(Conference c); } @@ -129,99 +116,249 @@ public class CallListFragment extends Fragment { } mCallbacks = (Callbacks) activity; + + } + + private Runnable mUpdateTimeTask = new Runnable() { + public void run() { + final long start = SystemClock.uptimeMillis(); + long millis = SystemClock.uptimeMillis() - start; + int seconds = (int) (millis / 1000); + int minutes = seconds / 60; + seconds = seconds % 60; + + calls_adapter.notifyDataSetChanged(); + confs_adapter.notifyDataSetChanged(); + mHandler.postAtTime(this, start + (((minutes * 60) + seconds + 1) * 1000)); + } + }; + + private Handler mHandler = new Handler(); + + @Override + public void onResume() { + super.onResume(); + if (mCallbacks.getService() != null) { + try { + updateLists(); + if (!calls_adapter.isEmpty() || !confs_adapter.isEmpty()) { + mHandler.postDelayed(mUpdateTimeTask, 0); + } + + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } + } + + } + + @SuppressWarnings("unchecked") + // No proper solution with HashMap runtime cast + public void updateLists() throws RemoteException { + HashMap<String, SipCall> calls = (HashMap<String, SipCall>) mCallbacks.getService().getCallList(); + HashMap<String, Conference> confs = (HashMap<String, Conference>) mCallbacks.getService().getConferenceList(); + + updateCallList(calls); + updateConferenceList(confs); + } + + private void updateConferenceList(HashMap<String, Conference> confs) { + nb_confs.setText("" + confs.size()); + confs_adapter.updateDataset(new ArrayList<Conference>(confs.values())); + } + + private void updateCallList(HashMap<String, SipCall> calls) { + nb_calls.setText("" + calls.size()); + ArrayList<Conference> conferences = new ArrayList<Conference>(); + for (SipCall call : calls.values()) { + Conference confOne = new Conference("-1"); + confOne.getParticipants().add(call); + conferences.add(confOne); + } + + calls_adapter.updateDataset(conferences); + } @Override public void onDetach() { + super.onDetach(); mCallbacks = sDummyCallbacks; + + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); } - ListView list; + @Override + public void onPause() { + super.onPause(); + mHandler.removeCallbacks(mUpdateTimeTask); + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + + super.onActivityCreated(savedInstanceState); + + // Give some text to display if there is no data. In a real + // application this would come from a resource. + // setEmptyText("No phone numbers"); + + // We have a menu item to show in action bar. + setHasOptionsMenu(true); + + } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.frag_call_list, container, false); - - list = (ListView) rootView.findViewById(R.id.call_list); - - list.setDivider(getResources().getDrawable(android.R.drawable.divider_horizontal_dark)); - list.setDividerHeight(10); - list.setAdapter(mAdapter); - list.setOnItemClickListener(mItemClickListener); -// list.setOnTouchListener(new SwipeListViewTouchListener(list, new SwipeListViewTouchListener.OnSwipeCallback() { -// @Override -// public void onSwipeLeft(ListView listView, int[] reverseSortedPositions) { -// // Log.i(this.getClass().getName(), "swipe left : pos="+reverseSortedPositions[0]); -// // TODO : YOUR CODE HERE FOR LEFT ACTION -// Conference tmp = mAdapter.getItem(reverseSortedPositions[0]); -// try { -// if (tmp.hasMultipleParticipants()) { -// mCallbacks.getService().hangUpConference(tmp.getId()); -// } else { -// mCallbacks.getService().hangUp(tmp.getParticipants().get(0).getCallId()); -// } -// } catch (RemoteException e) { -// // TODO Auto-generated catch block -// e.printStackTrace(); -// } -// -// } -// -// @Override -// public void onSwipeRight(ListView listView, int[] reverseSortedPositions) { -// // Log.i(ProfileMenuActivity.class.getClass().getName(), "swipe right : pos="+reverseSortedPositions[0]); -// // TODO : YOUR CODE HERE FOR RIGHT ACTION -// -// Conference tmp = mAdapter.getItem(reverseSortedPositions[0]); -// try { -// if (tmp.hasMultipleParticipants()) { -// if (tmp.isOnHold()) { -// mCallbacks.getService().unholdConference(tmp.getId()); -// } else { -// mCallbacks.getService().holdConference(tmp.getId()); -// } -// } else { -// if (tmp.isOnHold()) { -// Toast.makeText(getActivity(), "call is on hold, unholding", Toast.LENGTH_SHORT).show(); -// mCallbacks.getService().unhold(tmp.getParticipants().get(0).getCallId()); -// } else { -// Toast.makeText(getActivity(), "call is current, holding", Toast.LENGTH_SHORT).show(); -// mCallbacks.getService().hold(tmp.getParticipants().get(0).getCallId()); -// } -// } -// } catch (RemoteException e) { -// // TODO Auto-generated catch block -// e.printStackTrace(); -// } -// } -// }, true, // example : left action = dismiss -// false)); // example : right action without dismiss animation); - list.setOnItemLongClickListener(mItemLongClickListener); - - return rootView; + Log.i(TAG, "onCreateView"); + View inflatedView = inflater.inflate(R.layout.frag_call_list, container, false); + + nb_calls = (TextView) inflatedView.findViewById(R.id.calls_counter); + nb_confs = (TextView) inflatedView.findViewById(R.id.confs_counter); + + confs_adapter = new CallListAdapter(getActivity()); + ((ListView) inflatedView.findViewById(R.id.confs_list)).setAdapter(confs_adapter); + + calls_adapter = new CallListAdapter(getActivity()); + ((ListView) inflatedView.findViewById(R.id.calls_list)).setAdapter(calls_adapter); + ((ListView) inflatedView.findViewById(R.id.calls_list)).setOnItemClickListener(callClickListener); + ((ListView) inflatedView.findViewById(R.id.confs_list)).setOnItemClickListener(callClickListener); + + ((ListView) inflatedView.findViewById(R.id.calls_list)).setOnItemLongClickListener(mItemLongClickListener); + ((ListView) inflatedView.findViewById(R.id.confs_list)).setOnItemLongClickListener(mItemLongClickListener); + + return inflatedView; + } + + OnItemClickListener callClickListener = new OnItemClickListener() { + + @Override + public void onItemClick(AdapterView<?> arg0, View v, int arg2, long arg3) { + mCallbacks.selectedCall((Conference) v.getTag()); + } + }; + + private OnItemLongClickListener mItemLongClickListener = new OnItemLongClickListener() { + + @Override + public boolean onItemLongClick(AdapterView<?> adptv, View view, int pos, long arg3) { + final Vibrator vibe = (Vibrator) view.getContext().getSystemService(Context.VIBRATOR_SERVICE); + vibe.vibrate(80); + Intent i = new Intent(); + Bundle b = new Bundle(); + b.putParcelable("conference", (Conference) adptv.getAdapter().getItem(pos)); + i.putExtra("bconference", b); + + DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view); + ClipData data = ClipData.newIntent("conference", i); + view.startDrag(data, shadowBuilder, view, 0); + return false; + } + + }; + + public class CallListAdapter extends BaseAdapter implements Observer { + + private ArrayList<Conference> calls; + + private Context mContext; + + public CallListAdapter(Context act) { + super(); + mContext = act; + calls = new ArrayList<Conference>(); + + } + + public ArrayList<Conference> getDataset() { + return calls; + } + + public void remove(Conference transfer) { + + } + + public void updateDataset(ArrayList<Conference> list) { + calls.clear(); + calls.addAll(list); + notifyDataSetChanged(); + } + + @Override + public int getCount() { + return calls.size(); + } + + @Override + public Conference getItem(int position) { + return calls.get(position); + } + + @Override + public long getItemId(int position) { + return 0; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + if (convertView == null) + convertView = LayoutInflater.from(mContext).inflate(R.layout.item_calllist, null); + + Conference call = calls.get(position); + if (call.getParticipants().size() == 1) { + ((TextView) convertView.findViewById(R.id.call_title)).setText(call.getParticipants().get(0).getContact().getmDisplayName()); + + long duration = System.currentTimeMillis() / 1000 - (call.getParticipants().get(0).getTimestamp_start()); + + ((TextView) convertView.findViewById(R.id.call_time)).setText(String.format("%d:%02d:%02d", duration / 3600, (duration % 3600) / 60, + (duration % 60))); + } else { +// String tmp = "Conference with " + call.getParticipants().size() + " participants"; + ((TextView) convertView.findViewById(R.id.call_title)).setText(getString(R.string.home_conf_item, call.getParticipants().size())); + } + // ((TextView) convertView.findViewById(R.id.num_participants)).setText("" + call.getParticipants().size()); + ((TextView) convertView.findViewById(R.id.call_status)).setText(call.getState()); + + convertView.setOnDragListener(dragListener); + convertView.setTag(call); + + return convertView; + } + + @Override + public void update(Observable observable, Object data) { + Log.i(TAG, "Updating views..."); + notifyDataSetChanged(); + } + } OnDragListener dragListener = new OnDragListener() { - @SuppressWarnings("deprecation") // deprecated in API 16.... + @SuppressWarnings("deprecation") + // deprecated in API 16.... @Override public boolean onDrag(View v, DragEvent event) { switch (event.getAction()) { case DragEvent.ACTION_DRAG_STARTED: // Do nothing - Log.w(TAG, "ACTION_DRAG_STARTED"); + // Log.w(TAG, "ACTION_DRAG_STARTED"); break; case DragEvent.ACTION_DRAG_ENTERED: - Log.w(TAG, "ACTION_DRAG_ENTERED"); + // Log.w(TAG, "ACTION_DRAG_ENTERED"); v.setBackgroundColor(Color.GREEN); break; case DragEvent.ACTION_DRAG_EXITED: - Log.w(TAG, "ACTION_DRAG_EXITED"); - v.setBackgroundDrawable(getResources().getDrawable(R.drawable.item_contact_selector)); + // Log.w(TAG, "ACTION_DRAG_EXITED"); + v.setBackgroundDrawable(getResources().getDrawable(R.drawable.item_generic_selector)); break; case DragEvent.ACTION_DROP: - Log.w(TAG, "ACTION_DROP"); + // Log.w(TAG, "ACTION_DROP"); View view = (View) event.getLocalState(); Item i = event.getClipData().getItemAt(0); @@ -243,18 +380,14 @@ public class CallListFragment extends Fragment { dialog.setTargetFragment(CallListFragment.this, 0); dialog.show(getFragmentManager(), "dialog"); - Toast.makeText( - getActivity(), - "Dropped " + initial.getParticipants().get(0).getContact().getmDisplayName() + " on " - + target.getParticipants().get(0).getContact().getmDisplayName(), Toast.LENGTH_SHORT).show(); // view.setBackgroundColor(Color.WHITE); // v.setBackgroundColor(Color.BLACK); break; case DragEvent.ACTION_DRAG_ENDED: - Log.w(TAG, "ACTION_DRAG_ENDED"); + // Log.w(TAG, "ACTION_DRAG_ENDED"); View view1 = (View) event.getLocalState(); view1.setVisibility(View.VISIBLE); - v.setBackgroundDrawable(getResources().getDrawable(R.drawable.item_contact_selector)); + v.setBackgroundDrawable(getResources().getDrawable(R.drawable.item_generic_selector)); default: break; } @@ -263,92 +396,6 @@ public class CallListFragment extends Fragment { }; - private OnItemLongClickListener mItemLongClickListener = new OnItemLongClickListener() { - - @Override - public boolean onItemLongClick(AdapterView<?> arg0, View view, int pos, long arg3) { - final Vibrator vibe = (Vibrator) view.getContext().getSystemService(Context.VIBRATOR_SERVICE); - vibe.vibrate(80); - Intent i = new Intent(); - Bundle b = new Bundle(); - b.putParcelable("conference", mAdapter.getItem(pos)); - i.putExtra("bconference", b); - - DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view); - ClipData data = ClipData.newIntent("conference", i); - view.startDrag(data, shadowBuilder, view, 0); - return false; - } - - }; - - private OnItemClickListener mItemClickListener = new OnItemClickListener() { - - @Override - public void onItemClick(AdapterView<?> arg0, View arg1, int pos, long arg3) { - mCallbacks.onCallSelected(mAdapter.getItem(pos)); - - } - }; - - @SuppressWarnings("unchecked") // No proper solution with HashMap runtime cast - public void update() { - try { - HashMap<String, SipCall> list = (HashMap<String, SipCall>) mCallbacks.getService().getCallList(); - - // Toast.makeText(getActivity(), "Calls: " + list.size(), Toast.LENGTH_SHORT).show(); - ArrayList<Conference> conferences = new ArrayList<Conference>(); - HashMap<String, Conference> tmp = (HashMap<String, Conference>) mCallbacks.getService().getConferenceList(); - conferences.addAll(tmp.values()); - - ArrayList<SipCall> simple_calls = new ArrayList<SipCall>(list.values()); - for (SipCall call : simple_calls) { - Conference confOne = new Conference("-1"); - confOne.getParticipants().add(call); - conferences.add(confOne); - } - - if (conferences.isEmpty()) { - mCallbacks.onCallsTerminated(); - } - - mAdapter.update(conferences); - } catch (RemoteException e) { - Log.e(TAG, e.toString()); - } - - } - - // private void makeTransferDialog(int groupPosition) { - // FragmentManager fm = getFragmentManager(); - // TransferDFragment editNameDialog = new TransferDFragment(); - // - // if (!mAdapter.getItem(groupPosition).hasMultipleParticipants()) { - // Bundle b = new Bundle(); - // b.putParcelableArrayList("calls", mAdapter.getConcurrentCalls(groupPosition)); - // b.putParcelable("call_selected", mAdapter.getItem(groupPosition)); - // editNameDialog.setArguments(b); - // editNameDialog.setTargetFragment(this, REQUEST_TRANSFER); - // editNameDialog.show(fm, "dialog"); - // } else { - // Toast.makeText(getActivity(), "Transfer a Conference ?", Toast.LENGTH_SHORT).show(); - // } - // - // } - // - // private void makeConferenceDialog(int groupPosition) { - // FragmentManager fm = getFragmentManager(); - // ConferenceDFragment confDialog = ConferenceDFragment.newInstance(); - // - // Bundle b = new Bundle(); - // b.putParcelableArrayList("calls", mAdapter.getConcurrentCalls(groupPosition)); - // b.putParcelable("call_selected", mAdapter.getItem(groupPosition)); - // confDialog.setArguments(b); - // confDialog.setTargetFragment(this, REQUEST_CONF); - // confDialog.show(fm, "dialog"); - // - // } - @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); @@ -361,21 +408,21 @@ public class CallListFragment extends Fragment { try { mCallbacks.getService().attendedTransfer(transfer.getParticipants().get(0).getCallId(), c.getParticipants().get(0).getCallId()); - mAdapter.remove(transfer); - mAdapter.remove(c); - mAdapter.notifyDataSetChanged(); + calls_adapter.remove(transfer); + calls_adapter.remove(c); + calls_adapter.notifyDataSetChanged(); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } - Toast.makeText(getActivity(), "Transfer complete", Toast.LENGTH_LONG).show(); + Toast.makeText(getActivity(), getString(R.string.home_transfer_complet), Toast.LENGTH_LONG).show(); break; case 1: String to = data.getStringExtra("to_number"); transfer = data.getParcelableExtra("transfer"); try { - Toast.makeText(getActivity(), "Transferring " + transfer.getParticipants().get(0).getContact().getmDisplayName() + " to " + to, + Toast.makeText(getActivity(), getString(R.string.home_transfering,transfer.getParticipants().get(0).getContact().getmDisplayName(),to), Toast.LENGTH_SHORT).show(); mCallbacks.getService().transfer(transfer.getParticipants().get(0).getCallId(), to); mCallbacks.getService().hangUp(transfer.getParticipants().get(0).getCallId()); @@ -431,143 +478,4 @@ public class CallListFragment extends Fragment { } } - public class CallListAdapter extends BaseAdapter { - - private ArrayList<Conference> calls; - - private Context mContext; - - public CallListAdapter(Context act) { - super(); - mContext = act; - calls = new ArrayList<Conference>(); - - } - - public ArrayList<Conference> getConcurrentCalls(int position) { - ArrayList<Conference> toReturn = new ArrayList<Conference>(); - for (int i = 0; i < calls.size(); ++i) { - if (position != i) - toReturn.add(calls.get(i)); - } - return toReturn; - } - - public void remove(Conference transfer) { - calls.remove(transfer); - } - - public void update(ArrayList<Conference> list) { - calls.clear(); - calls.addAll(list); - notifyDataSetChanged(); - } - - @Override - public int getCount() { - return calls.size(); - } - - @Override - public Conference getItem(int position) { - return calls.get(position); - } - - @Override - public long getItemId(int position) { - return 0; - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - if (convertView == null) - convertView = LayoutInflater.from(mContext).inflate(R.layout.item_calllist, null); - - Conference call = calls.get(position); - if (call.getParticipants().size() == 1) { - ((TextView) convertView.findViewById(R.id.call_title)).setText(call.getParticipants().get(0).getContact().getmDisplayName()); - - long duration = System.currentTimeMillis() / 1000 - (call.getParticipants().get(0).getTimestamp_start()); - - ((TextView) convertView.findViewById(R.id.call_time)).setText(String.format("%d:%02d:%02d", duration/3600, (duration%3600)/60, (duration%60))); - } else { - String tmp = "Conference with " + call.getParticipants().size() + " participants"; - - ((TextView) convertView.findViewById(R.id.call_title)).setText(tmp); - } - - ((TextView) convertView.findViewById(R.id.call_status)).setText(call.getState()); - convertView.setOnDragListener(dragListener); - - convertView.setTag(call); - return convertView; - } - - } - - public static class DropActionsChoice extends DialogFragment { - - ListAdapter mAdapter; - private Bundle args; - - /** - * Create a new instance of CallActionsDFragment - */ - public static DropActionsChoice newInstance() { - DropActionsChoice f = new DropActionsChoice(); - return f; - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - // Pick a style based on the num. - int style = DialogFragment.STYLE_NORMAL, theme = 0; - setStyle(style, theme); - } - - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - ListView rootView = new ListView(getActivity()); - - args = getArguments(); - mAdapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, getResources().getStringArray( - R.array.drop_actions)); - - // ListView list = (ListView) rootView.findViewById(R.id.concurrent_calls); - rootView.setAdapter(mAdapter); - rootView.setOnItemClickListener(new OnItemClickListener() { - - @Override - public void onItemClick(AdapterView<?> arg0, View arg1, int pos, long arg3) { - Intent in = new Intent(); - - in.putExtra("transfer", args.getParcelable("call_initial")); - in.putExtra("target", args.getParcelable("call_targeted")); - - switch (pos) { - case 0: // Transfer - getTargetFragment().onActivityResult(REQUEST_TRANSFER, 0, in); - break; - case 1: // Conference - getTargetFragment().onActivityResult(REQUEST_CONF, 0, in); - break; - } - dismiss(); - - } - }); - - final AlertDialog a = new AlertDialog.Builder(getActivity()).setView(rootView).setTitle("Choose Action") - .setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int whichButton) { - dismiss(); - } - }).create(); - - return a; - } - } - } diff --git a/src/org/sflphone/fragments/DropActionsChoice.java b/src/org/sflphone/fragments/DropActionsChoice.java new file mode 100644 index 0000000000000000000000000000000000000000..75d39ee78ab967525818b6ab883f3fd09938df9e --- /dev/null +++ b/src/org/sflphone/fragments/DropActionsChoice.java @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2004-2013 Savoir-Faire Linux Inc. + * + * Author: Alexandre Lision <alexandre.lision@savoirfairelinux.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 org.sflphone.fragments; + +import org.sflphone.R; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.app.DialogFragment; +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.ArrayAdapter; +import android.widget.ListAdapter; +import android.widget.ListView; + +public class DropActionsChoice extends DialogFragment { + + ListAdapter mAdapter; + private Bundle args; + public static final int REQUEST_TRANSFER = 10; + public static final int REQUEST_CONF = 20; + + /** + * Create a new instance of CallActionsDFragment + */ + public static DropActionsChoice newInstance() { + DropActionsChoice f = new DropActionsChoice(); + return f; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + // Pick a style based on the num. + int style = DialogFragment.STYLE_NORMAL, theme = 0; + setStyle(style, theme); + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + ListView rootView = new ListView(getActivity()); + + args = getArguments(); + mAdapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, getResources().getStringArray(R.array.drop_actions)); + + // ListView list = (ListView) rootView.findViewById(R.id.concurrent_calls); + rootView.setAdapter(mAdapter); + rootView.setOnItemClickListener(new OnItemClickListener() { + + @Override + public void onItemClick(AdapterView<?> arg0, View arg1, int pos, long arg3) { + Intent in = new Intent(); + + in.putExtra("transfer", args.getParcelable("call_initial")); + in.putExtra("target", args.getParcelable("call_targeted")); + + switch (pos) { + case 0: // Transfer + getTargetFragment().onActivityResult(REQUEST_TRANSFER, 0, in); + break; + case 1: // Conference + getTargetFragment().onActivityResult(REQUEST_CONF, 0, in); + break; + } + dismiss(); + + } + }); + + final AlertDialog a = new AlertDialog.Builder(getActivity()).setView(rootView).setTitle("Choose Action") + .setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { + dismiss(); + } + }).create(); + + return a; + } + +} diff --git a/src/org/sflphone/fragments/HomeFragment.java b/src/org/sflphone/fragments/HomeFragment.java index 03eb086967383c99fccd8641400a4b969fa9e7cc..08a0456832a07a18082c6fae2a47c6306e2a76cf 100644 --- a/src/org/sflphone/fragments/HomeFragment.java +++ b/src/org/sflphone/fragments/HomeFragment.java @@ -1,482 +1,81 @@ -/* - * Copyright (C) 2004-2013 Savoir-Faire Linux Inc. - * - * Author: Alexandre Lision <alexandre.lision@savoirfairelinux.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 org.sflphone.fragments; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Observable; -import java.util.Observer; - import org.sflphone.R; -import org.sflphone.fragments.CallListFragment.DropActionsChoice; -import org.sflphone.model.CallTimer; -import org.sflphone.model.Conference; -import org.sflphone.model.SipCall; -import org.sflphone.service.ISipService; +import org.sflphone.adapters.SectionsPagerAdapter; +import org.sflphone.views.PagerSlidingTabStrip; import android.app.Activity; import android.app.Fragment; -import android.content.ClipData; -import android.content.ClipData.Item; -import android.content.Context; import android.content.Intent; -import android.graphics.Color; import android.os.Bundle; -import android.os.Handler; -import android.os.RemoteException; -import android.os.SystemClock; -import android.os.Vibrator; -import android.util.Log; -import android.view.DragEvent; +import android.support.v4.view.ViewPager; import android.view.LayoutInflater; import android.view.View; -import android.view.View.DragShadowBuilder; -import android.view.View.OnDragListener; import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemClickListener; -import android.widget.AdapterView.OnItemLongClickListener; -import android.widget.BaseAdapter; -import android.widget.ListView; -import android.widget.TextView; -import android.widget.Toast; public class HomeFragment extends Fragment { - private static final String TAG = HomeFragment.class.getSimpleName(); - - private Callbacks mCallbacks = sDummyCallbacks; - private TextView nb_calls, nb_confs; - CallListAdapter confs_adapter, calls_adapter; - CallTimer timer; - - public static final int REQUEST_TRANSFER = 10; - public static final int REQUEST_CONF = 20; - + static final String TAG = HomeFragment.class.getSimpleName(); + /** - * A dummy implementation of the {@link Callbacks} interface that does nothing. Used only when this fragment is not attached to an activity. + * The {@link ViewPager} that will host the section contents. */ - private static Callbacks sDummyCallbacks = new Callbacks() { - - @Override - public ISipService getService() { - Log.i(TAG, "I'm a dummy"); - return null; - } - - @Override - public void selectedCall(Conference c) { - } - }; - - /** - * The Activity calling this fragment has to implement this interface - * - */ - public interface Callbacks { - - public ISipService getService(); - - public void selectedCall(Conference c); - - } + ViewPager mViewPager; + SectionsPagerAdapter mSectionsPagerAdapter = null; @Override public void onAttach(Activity activity) { super.onAttach(activity); - - if (!(activity instanceof Callbacks)) { - throw new IllegalStateException("Activity must implement fragment's callbacks."); - } - - mCallbacks = (Callbacks) activity; - - } - - private Runnable mUpdateTimeTask = new Runnable() { - public void run() { - final long start = SystemClock.uptimeMillis(); - long millis = SystemClock.uptimeMillis() - start; - int seconds = (int) (millis / 1000); - int minutes = seconds / 60; - seconds = seconds % 60; - - calls_adapter.notifyDataSetChanged(); - confs_adapter.notifyDataSetChanged(); - mHandler.postAtTime(this, start + (((minutes * 60) + seconds + 1) * 1000)); - } - }; - - private Handler mHandler = new Handler(); - - @Override - public void onResume() { - super.onResume(); - if (mCallbacks.getService() != null) { - try { - updateLists(); - if (!calls_adapter.isEmpty() || !confs_adapter.isEmpty()) { - mHandler.postDelayed(mUpdateTimeTask, 0); - } - - } catch (RemoteException e) { - Log.e(TAG, e.toString()); - } - } - - } - - @SuppressWarnings("unchecked") - // No proper solution with HashMap runtime cast - public void updateLists() throws RemoteException { - HashMap<String, SipCall> calls = (HashMap<String, SipCall>) mCallbacks.getService().getCallList(); - HashMap<String, Conference> confs = (HashMap<String, Conference>) mCallbacks.getService().getConferenceList(); - - updateCallList(calls); - updateConferenceList(confs); - } - - private void updateConferenceList(HashMap<String, Conference> confs) { - nb_confs.setText("" + confs.size()); - confs_adapter.updateDataset(new ArrayList<Conference>(confs.values())); - } - - private void updateCallList(HashMap<String, SipCall> calls) { - nb_calls.setText("" + calls.size()); - ArrayList<Conference> conferences = new ArrayList<Conference>(); - for (SipCall call : calls.values()) { - Conference confOne = new Conference("-1"); - confOne.getParticipants().add(call); - conferences.add(confOne); - } - - calls_adapter.updateDataset(conferences); - } @Override public void onDetach() { - super.onDetach(); - mCallbacks = sDummyCallbacks; - - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); } - + @Override - public void onPause() { - super.onPause(); - mHandler.removeCallbacks(mUpdateTimeTask); - } - - @Override - public void onActivityCreated(Bundle savedInstanceState) { - - super.onActivityCreated(savedInstanceState); - - // Give some text to display if there is no data. In a real - // application this would come from a resource. - // setEmptyText("No phone numbers"); - - // We have a menu item to show in action bar. - setHasOptionsMenu(true); - + public void onCreate(Bundle savedBundle){ + super.onCreate(savedBundle); + mSectionsPagerAdapter = new SectionsPagerAdapter(getActivity(), getFragmentManager()); + } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - Log.i(TAG, "onCreateView"); - View inflatedView = inflater.inflate(R.layout.frag_home, container, false); - - nb_calls = (TextView) inflatedView.findViewById(R.id.calls_counter); - nb_confs = (TextView) inflatedView.findViewById(R.id.confs_counter); - - confs_adapter = new CallListAdapter(getActivity()); - ((ListView) inflatedView.findViewById(R.id.confs_list)).setAdapter(confs_adapter); - - calls_adapter = new CallListAdapter(getActivity()); - ((ListView) inflatedView.findViewById(R.id.calls_list)).setAdapter(calls_adapter); - ((ListView) inflatedView.findViewById(R.id.calls_list)).setOnItemClickListener(callClickListener); - ((ListView) inflatedView.findViewById(R.id.confs_list)).setOnItemClickListener(callClickListener); - - ((ListView) inflatedView.findViewById(R.id.calls_list)).setOnItemLongClickListener(mItemLongClickListener); - ((ListView) inflatedView.findViewById(R.id.confs_list)).setOnItemLongClickListener(mItemLongClickListener); - - return inflatedView; + ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.frag_home, container, false); + + + // Set up the ViewPager with the sections adapter. + mViewPager = (ViewPager) rootView.findViewById(R.id.pager); + mViewPager.setPageTransformer(true, new ZoomOutPageTransformer(0.7f)); + + mViewPager.setOffscreenPageLimit(2); + mViewPager.setAdapter(mSectionsPagerAdapter); + mViewPager.setCurrentItem(1); + + final PagerSlidingTabStrip strip = PagerSlidingTabStrip.class.cast(rootView.findViewById(R.id.pts_main)); + + strip.setViewPager(mViewPager); + + return rootView; } - OnItemClickListener callClickListener = new OnItemClickListener() { - - @Override - public void onItemClick(AdapterView<?> arg0, View v, int arg2, long arg3) { - mCallbacks.selectedCall((Conference) v.getTag()); - } - }; - - private OnItemLongClickListener mItemLongClickListener = new OnItemLongClickListener() { - - @Override - public boolean onItemLongClick(AdapterView<?> adptv, View view, int pos, long arg3) { - final Vibrator vibe = (Vibrator) view.getContext().getSystemService(Context.VIBRATOR_SERVICE); - vibe.vibrate(80); - Intent i = new Intent(); - Bundle b = new Bundle(); - b.putParcelable("conference", (Conference) adptv.getAdapter().getItem(pos)); - i.putExtra("bconference", b); - - DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view); - ClipData data = ClipData.newIntent("conference", i); - view.startDrag(data, shadowBuilder, view, 0); - return false; - } - - }; - - public class CallListAdapter extends BaseAdapter implements Observer { - - private ArrayList<Conference> calls; - - private Context mContext; - - public CallListAdapter(Context act) { - super(); - mContext = act; - calls = new ArrayList<Conference>(); - - } - - public ArrayList<Conference> getDataset() { - return calls; - } - - public void remove(Conference transfer) { - - } - - public void updateDataset(ArrayList<Conference> list) { - calls.clear(); - calls.addAll(list); - notifyDataSetChanged(); - } - - @Override - public int getCount() { - return calls.size(); - } - - @Override - public Conference getItem(int position) { - return calls.get(position); - } - - @Override - public long getItemId(int position) { - return 0; - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - if (convertView == null) - convertView = LayoutInflater.from(mContext).inflate(R.layout.item_calllist, null); - - Conference call = calls.get(position); - if (call.getParticipants().size() == 1) { - ((TextView) convertView.findViewById(R.id.call_title)).setText(call.getParticipants().get(0).getContact().getmDisplayName()); - - long duration = System.currentTimeMillis() / 1000 - (call.getParticipants().get(0).getTimestamp_start()); - - ((TextView) convertView.findViewById(R.id.call_time)).setText(String.format("%d:%02d:%02d", duration / 3600, (duration % 3600) / 60, - (duration % 60))); - } else { -// String tmp = "Conference with " + call.getParticipants().size() + " participants"; - ((TextView) convertView.findViewById(R.id.call_title)).setText(getString(R.string.home_conf_item, call.getParticipants().size())); - } - // ((TextView) convertView.findViewById(R.id.num_participants)).setText("" + call.getParticipants().size()); - ((TextView) convertView.findViewById(R.id.call_status)).setText(call.getState()); - - convertView.setOnDragListener(dragListener); - convertView.setTag(call); - - return convertView; - } - - @Override - public void update(Observable observable, Object data) { - Log.i(TAG, "Updating views..."); - notifyDataSetChanged(); - } - - } - - OnDragListener dragListener = new OnDragListener() { - - @SuppressWarnings("deprecation") - // deprecated in API 16.... - @Override - public boolean onDrag(View v, DragEvent event) { - switch (event.getAction()) { - case DragEvent.ACTION_DRAG_STARTED: - // Do nothing - // Log.w(TAG, "ACTION_DRAG_STARTED"); - break; - case DragEvent.ACTION_DRAG_ENTERED: - // Log.w(TAG, "ACTION_DRAG_ENTERED"); - v.setBackgroundColor(Color.GREEN); - break; - case DragEvent.ACTION_DRAG_EXITED: - // Log.w(TAG, "ACTION_DRAG_EXITED"); - v.setBackgroundDrawable(getResources().getDrawable(R.drawable.item_generic_selector)); - break; - case DragEvent.ACTION_DROP: - // Log.w(TAG, "ACTION_DROP"); - View view = (View) event.getLocalState(); - - Item i = event.getClipData().getItemAt(0); - Intent intent = i.getIntent(); - intent.setExtrasClassLoader(Conference.class.getClassLoader()); - - Conference initial = (Conference) view.getTag(); - Conference target = (Conference) v.getTag(); - - if (initial == target) { - return true; - } - - DropActionsChoice dialog = DropActionsChoice.newInstance(); - Bundle b = new Bundle(); - b.putParcelable("call_initial", initial); - b.putParcelable("call_targeted", target); - dialog.setArguments(b); - dialog.setTargetFragment(HomeFragment.this, 0); - dialog.show(getFragmentManager(), "dialog"); - - // view.setBackgroundColor(Color.WHITE); - // v.setBackgroundColor(Color.BLACK); - break; - case DragEvent.ACTION_DRAG_ENDED: - // Log.w(TAG, "ACTION_DRAG_ENDED"); - View view1 = (View) event.getLocalState(); - view1.setVisibility(View.VISIBLE); - v.setBackgroundDrawable(getResources().getDrawable(R.drawable.item_generic_selector)); - default: - break; - } - return true; - } - - }; - @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); - Conference transfer = null; - if (requestCode == REQUEST_TRANSFER) { - switch (resultCode) { - case 0: - Conference c = data.getParcelableExtra("target"); - transfer = data.getParcelableExtra("transfer"); - try { - - mCallbacks.getService().attendedTransfer(transfer.getParticipants().get(0).getCallId(), c.getParticipants().get(0).getCallId()); - calls_adapter.remove(transfer); - calls_adapter.remove(c); - calls_adapter.notifyDataSetChanged(); - } catch (RemoteException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - Toast.makeText(getActivity(), getString(R.string.home_transfer_complet), Toast.LENGTH_LONG).show(); - break; - - case 1: - String to = data.getStringExtra("to_number"); - transfer = data.getParcelableExtra("transfer"); - try { - Toast.makeText(getActivity(), getString(R.string.home_transfering,transfer.getParticipants().get(0).getContact().getmDisplayName(),to), - Toast.LENGTH_SHORT).show(); - mCallbacks.getService().transfer(transfer.getParticipants().get(0).getCallId(), to); - mCallbacks.getService().hangUp(transfer.getParticipants().get(0).getCallId()); - } catch (RemoteException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - break; - - default: - break; - } - } else if (requestCode == REQUEST_CONF) { - switch (resultCode) { - case 0: - Conference call_to_add = data.getParcelableExtra("transfer"); - Conference call_target = data.getParcelableExtra("target"); - - bindCalls(call_to_add, call_target); - break; - - default: - break; - } - } } + + public class ZoomOutPageTransformer implements ViewPager.PageTransformer { + private static final float MIN_ALPHA = .6f; - private void bindCalls(Conference call_to_add, Conference call_target) { - try { - - if (call_target.hasMultipleParticipants() && !call_to_add.hasMultipleParticipants()) { - - mCallbacks.getService().addParticipant(call_to_add.getParticipants().get(0), call_target.getId()); - - } else if (call_target.hasMultipleParticipants() && call_to_add.hasMultipleParticipants()) { - - // We join two conferences - mCallbacks.getService().joinConference(call_to_add.getId(), call_target.getId()); - - } else if (!call_target.hasMultipleParticipants() && call_to_add.hasMultipleParticipants()) { - - mCallbacks.getService().addParticipant(call_target.getParticipants().get(0), call_to_add.getId()); - - } else { - // We join two single calls to create a conf - mCallbacks.getService().joinParticipant(call_to_add.getParticipants().get(0).getCallId(), - call_target.getParticipants().get(0).getCallId()); - } + public ZoomOutPageTransformer(float scalingStart) { + super(); + } - } catch (RemoteException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + @Override + public void transformPage(View page, float position) { + final float normalizedposition = Math.abs(Math.abs(position) - 1); + page.setAlpha(MIN_ALPHA + (1.f - MIN_ALPHA) * normalizedposition); } } -} +} \ No newline at end of file diff --git a/src/org/sflphone/fragments/IMFragment.java b/src/org/sflphone/fragments/IMFragment.java index bd93bea4627390c02de89a830d0c77e4a5cb46bc..777aaaf6f2bccedfd5ff55447483a0749465845f 100644 --- a/src/org/sflphone/fragments/IMFragment.java +++ b/src/org/sflphone/fragments/IMFragment.java @@ -23,7 +23,7 @@ import android.widget.TextView; import android.widget.TextView.OnEditorActionListener; public class IMFragment extends Fragment { - static final String TAG = CallListFragment.class.getSimpleName(); + static final String TAG = IMFragment.class.getSimpleName(); private Callbacks mCallbacks = sDummyCallbacks; diff --git a/src/org/sflphone/model/BubbleUser.java b/src/org/sflphone/model/BubbleUser.java index e0f306481193598dfd1275f157601fb7bbb58af7..ce7f0d855cac33cffc4619b44f9651209272e692 100644 --- a/src/org/sflphone/model/BubbleUser.java +++ b/src/org/sflphone/model/BubbleUser.java @@ -300,6 +300,5 @@ public class BubbleUser extends Bubble { public void setMute(boolean captureMuted) { mMuted = captureMuted; - } } diff --git a/src/org/sflphone/receivers/IncomingReceiver.java b/src/org/sflphone/receivers/IncomingReceiver.java index 92af380848b189624e13de8600386dffb879ad65..e41baae2d7e12328352f4eeed4f232e7c8a245f1 100644 --- a/src/org/sflphone/receivers/IncomingReceiver.java +++ b/src/org/sflphone/receivers/IncomingReceiver.java @@ -119,7 +119,7 @@ public class IncomingReceiver extends BroadcastReceiver { newCall.setTimestamp_start(Long.parseLong(callDetails.get(ServiceConstants.call.TIMESTAMP_START))); callback.getCurrent_calls().put(newCall.getCallId(), newCall); -// callback.sendBroadcast(toSend); + // callback.sendBroadcast(toSend); Bundle bundle = new Bundle(); Conference tmp = new Conference("-1"); @@ -129,7 +129,7 @@ public class IncomingReceiver extends BroadcastReceiver { toSend.putExtra("resuming", false); toSend.putExtras(bundle); callback.startActivity(toSend); - + callback.mediaManager.startRing(""); callback.mediaManager.obtainAudioFocus(true); } catch (RemoteException e1) { e1.printStackTrace(); @@ -158,7 +158,6 @@ public class IncomingReceiver extends BroadcastReceiver { callback.getCurrent_calls().get(b.getString("CallID")).setCallState(SipCall.state.CALL_STATE_RINGING); } catch (NullPointerException e) { if (callback.getCurrent_calls() == null) { - return; } if (callback.getCurrent_calls().get(b.getString("CallID")) == null) { @@ -183,10 +182,11 @@ public class IncomingReceiver extends BroadcastReceiver { } } else if (newState.equals("HUNGUP")) { - + if (callback.getCurrent_calls().get(b.getString("CallID")) != null) { - - if(callback.getCurrent_calls().get(b.getString("CallID")).isRinging()) + + if (callback.getCurrent_calls().get(b.getString("CallID")).isRinging() + && callback.getCurrent_calls().get(b.getString("CallID")).isIncoming()) callback.notificationManager.publishMissedCallNotification(callback.getCurrent_calls().get(b.getString("CallID"))); callback.getCurrent_calls().remove(b.getString("CallID")); } else { diff --git a/src/org/sflphone/service/SipService.java b/src/org/sflphone/service/SipService.java index f4e79ffcd1c7205a2c15c3557dbf56d214133832..c30162e690839ff82478e4f5626b2d45e615e6ac 100644 --- a/src/org/sflphone/service/SipService.java +++ b/src/org/sflphone/service/SipService.java @@ -31,11 +31,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.Random; -import org.sflphone.R; -import org.sflphone.client.CallActivity; -import org.sflphone.client.HomeActivity; import org.sflphone.model.Codec; import org.sflphone.model.Conference; import org.sflphone.model.SipCall; @@ -45,11 +41,7 @@ import org.sflphone.utils.MediaManager; import org.sflphone.utils.SipNotifications; import org.sflphone.utils.SwigNativeConverter; -import android.app.Notification; -import android.app.NotificationManager; -import android.app.PendingIntent; import android.app.Service; -import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; @@ -59,7 +51,6 @@ import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.RemoteException; -import android.support.v4.app.NotificationCompat; import android.support.v4.content.LocalBroadcastManager; import android.util.Log; @@ -350,6 +341,7 @@ public class SipService extends Service { @Override public void refuse(final String callID) { + getExecutor().execute(new SipRunnable() { @Override protected void doRun() throws SameThreadException { @@ -361,6 +353,7 @@ public class SipService extends Service { @Override public void accept(final String callID) { + mediaManager.stopRing(); getExecutor().execute(new SipRunnable() { @Override protected void doRun() throws SameThreadException { @@ -373,6 +366,7 @@ public class SipService extends Service { @Override public void hangUp(final String callID) { + mediaManager.stopRing(); getExecutor().execute(new SipRunnable() { @Override protected void doRun() throws SameThreadException { @@ -1140,43 +1134,14 @@ public class SipService extends Service { ***********************/ @Override public void createNotification() throws RemoteException { - makeNotification(); + notificationManager.makeNotification(getCurrent_calls()); } @Override public void destroyNotification() throws RemoteException { - removeNotification(); - - } - - private final int NOTIFICATION_ID = new Random().nextInt(1000); - - private void makeNotification() { - if (current_calls.size() == 0) { - return; - } - Intent notificationIntent = new Intent(getApplicationContext(), HomeActivity.class); - PendingIntent contentIntent = PendingIntent.getActivity(getApplicationContext(), 007, notificationIntent, - PendingIntent.FLAG_UPDATE_CURRENT); - - NotificationManager nm = (NotificationManager) getBaseContext().getSystemService(Context.NOTIFICATION_SERVICE); - nm.cancel(NOTIFICATION_ID); // clear previous notifications. - - NotificationCompat.Builder builder = new NotificationCompat.Builder(getBaseContext()); - - builder.setContentIntent(contentIntent).setOngoing(true).setSmallIcon(R.drawable.ic_launcher) - .setContentTitle(getCurrent_calls().size() + " ongoing calls").setTicker("Pending calls").setWhen(System.currentTimeMillis()) - .setAutoCancel(false); - builder.setPriority(NotificationCompat.PRIORITY_MAX); - Notification n = builder.build(); - - nm.notify(NOTIFICATION_ID, n); - } + notificationManager.removeNotification(); - public void removeNotification() { - NotificationManager nm = (NotificationManager) getBaseContext().getSystemService(Context.NOTIFICATION_SERVICE); - nm.cancel(NOTIFICATION_ID); } @Override diff --git a/src/org/sflphone/utils/MediaManager.java b/src/org/sflphone/utils/MediaManager.java index 82d7554d63ae9b3b3caebc0b9db5730d356b5eef..c42d6c4112af81086eb90ad441ed6df1310d2240 100644 --- a/src/org/sflphone/utils/MediaManager.java +++ b/src/org/sflphone/utils/MediaManager.java @@ -14,11 +14,14 @@ public class MediaManager implements OnAudioFocusChangeListener { private SipService mService; private SettingsContentObserver mSettingsContentObserver; AudioManager mAudioManager; + private Ringer ringer; public MediaManager(SipService aService) { mService = aService; mSettingsContentObserver = new SettingsContentObserver(mService, new Handler()); mAudioManager = (AudioManager) aService.getSystemService(Context.AUDIO_SERVICE); + + ringer = new Ringer(aService); } public void startService() { @@ -63,4 +66,30 @@ public class MediaManager implements OnAudioFocusChangeListener { public void RouteToInternalSpeaker() { mAudioManager.setSpeakerphoneOn(false); } + + + /** + * Start ringing announce for a given contact. + * It will also focus audio for us. + * @param remoteContact the contact to ring for. May resolve the contact ringtone if any. + */ + synchronized public void startRing(String remoteContact) { + + if(!ringer.isRinging()) { + ringer.ring(remoteContact, "USELESS"); + }else { + Log.d(TAG, "Already ringing ...."); + } + + } + + /** + * Stop all ringing. <br/> + * Warning, this will not unfocus audio. + */ + synchronized public void stopRing() { + if(ringer.isRinging()) { + ringer.stopRing(); + } + } } diff --git a/src/org/sflphone/utils/Ringer.java b/src/org/sflphone/utils/Ringer.java new file mode 100644 index 0000000000000000000000000000000000000000..075f790c43571410802d95f990c225afac809dc7 --- /dev/null +++ b/src/org/sflphone/utils/Ringer.java @@ -0,0 +1,153 @@ +package org.sflphone.utils; + +import android.content.Context; +import android.media.AudioManager; +import android.net.Uri; +import android.os.Vibrator; +import android.util.Log; + + +/** + * Ringer manager for the Phone app. + */ +public class Ringer { + private static final String THIS_FILE = "Ringer"; + + private static final int VIBRATE_LENGTH = 1000; // ms + private static final int PAUSE_LENGTH = 1000; // ms + + // Uri for the ringtone. + Uri customRingtoneUri; + + Vibrator vibrator; + VibratorThread vibratorThread; + Context context; + + public Ringer(Context aContext) { + context = aContext; + vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); + } + + /** + * Starts the ringtone and/or vibrator. + * + */ + public void ring(String remoteContact, String defaultRingtone) { + Log.d(THIS_FILE, "==> ring() called..."); + + synchronized (this) { + + AudioManager audioManager = + (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); + + //Save ringtone at the begining in case we raise vol +// ringtone = getRingtone(remoteContact, defaultRingtone); + + //No ring no vibrate + int ringerMode = audioManager.getRingerMode(); + if (ringerMode == AudioManager.RINGER_MODE_SILENT) { + Log.d(THIS_FILE, "skipping ring and vibrate because profile is Silent"); + return; + } + + // Vibrate + int vibrateSetting = audioManager.getVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER); + Log.d(THIS_FILE, "v=" + vibrateSetting + " rm=" + ringerMode); + if (vibratorThread == null && + (vibrateSetting == AudioManager.VIBRATE_SETTING_ON || + ringerMode == AudioManager.RINGER_MODE_VIBRATE)) { + vibratorThread = new VibratorThread(); + Log.d(THIS_FILE, "Starting vibrator..."); + vibratorThread.start(); + } + + // Vibrate only + if (ringerMode == AudioManager.RINGER_MODE_VIBRATE || + audioManager.getStreamVolume(AudioManager.STREAM_RING) == 0 ) { + Log.d(THIS_FILE, "skipping ring because profile is Vibrate OR because volume is zero"); + return; + } + + } + } + + /** + * @return true if we're playing a ringtone and/or vibrating + * to indicate that there's an incoming call. + * ("Ringing" here is used in the general sense. If you literally + * need to know if we're playing a ringtone or vibrating, use + * isRingtonePlaying() or isVibrating() instead.) + */ + public boolean isRinging() { + return (vibratorThread != null); + } + + /** + * Stops the ringtone and/or vibrator if any of these are actually + * ringing/vibrating. + */ + public void stopRing() { + synchronized (this) { + Log.d(THIS_FILE, "==> stopRing() called..."); + + stopVibrator(); + } + } + + + private void stopVibrator() { + + if (vibratorThread != null) { + vibratorThread.interrupt(); + try { + vibratorThread.join(250); // Should be plenty long (typ.) + } catch (InterruptedException e) { + } // Best efforts (typ.) + vibratorThread = null; + } + } + + public void updateRingerMode() { + + AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); + synchronized (this) { + int ringerMode = audioManager.getRingerMode(); + // Silent : stop everything + if (ringerMode == AudioManager.RINGER_MODE_SILENT) { + stopRing(); + return; + } + + // Vibrate + int vibrateSetting = audioManager.getVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER); + // If not already started restart it + if (vibratorThread == null && (vibrateSetting == AudioManager.VIBRATE_SETTING_ON || ringerMode == AudioManager.RINGER_MODE_VIBRATE)) { + vibratorThread = new VibratorThread(); + vibratorThread.start(); + } + + // Vibrate only + if (ringerMode == AudioManager.RINGER_MODE_VIBRATE || audioManager.getStreamVolume(AudioManager.STREAM_RING) == 0) { + return; + } + + } + } + + private class VibratorThread extends Thread { + public void run() { + try { + while (true) { + vibrator.vibrate(VIBRATE_LENGTH); + Thread.sleep(VIBRATE_LENGTH + PAUSE_LENGTH); + } + } catch (InterruptedException ex) { + Log.d(THIS_FILE, "Vibrator thread interrupt"); + } finally { + vibrator.cancel(); + } + Log.d(THIS_FILE, "Vibrator thread exiting"); + } + } + +} diff --git a/src/org/sflphone/utils/SipNotifications.java b/src/org/sflphone/utils/SipNotifications.java index 7ec35e413573c72dea1e2cbe4dd04314af5439db..0086c1eba854b809e79f81a6c306a9091acb193e 100644 --- a/src/org/sflphone/utils/SipNotifications.java +++ b/src/org/sflphone/utils/SipNotifications.java @@ -33,8 +33,8 @@ package org.sflphone.utils; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Random; import org.sflphone.R; import org.sflphone.client.HomeActivity; @@ -43,7 +43,6 @@ import org.sflphone.model.SipCall; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; -import android.content.ContentValues; import android.content.Context; import android.content.Intent; import android.graphics.BitmapFactory; @@ -55,21 +54,17 @@ import android.text.Spannable; import android.text.SpannableString; import android.text.TextUtils; import android.text.style.StyleSpan; -import android.util.Log; public class SipNotifications { private final NotificationManager notificationManager; private final Context context; - private Builder inCallNotification; - private Builder missedCallNotification; - private Builder messageNotification; - private Builder messageVoicemail; - private boolean resolveContacts = true; public static final String NOTIF_CREATION = "notif_creation"; public static final String NOTIF_DELETION = "notif_deletion"; + private final int NOTIFICATION_ID = new Random().nextInt(1000); + public static final int REGISTER_NOTIF_ID = 1; public static final int CALL_NOTIF_ID = REGISTER_NOTIF_ID + 1; public static final int CALLLOG_NOTIF_ID = REGISTER_NOTIF_ID + 2; @@ -90,86 +85,10 @@ public class SipNotifications { } - // Foreground api - - private static final Class<?>[] SET_FG_SIG = new Class[] { boolean.class }; - private static final Class<?>[] START_FG_SIG = new Class[] { int.class, Notification.class }; - private static final Class<?>[] STOP_FG_SIG = new Class[] { boolean.class }; private static final String THIS_FILE = "Notifications"; - private Method mSetForeground; - private Method mStartForeground; - private Method mStopForeground; - private Object[] mSetForegroundArgs = new Object[1]; - private Object[] mStartForegroundArgs = new Object[2]; - private Object[] mStopForegroundArgs = new Object[1]; - - private void invokeMethod(Method method, Object[] args) { - try { - method.invoke(context, args); - } catch (InvocationTargetException e) { - // Should not happen. - Log.w(THIS_FILE, "Unable to invoke method", e); - } catch (IllegalAccessException e) { - // Should not happen. - Log.w(THIS_FILE, "Unable to invoke method", e); - } - } - - /** - * This is a wrapper around the new startForeground method, using the older APIs if it is not available. - */ - private void startForegroundCompat(int id, Notification notification) { - // If we have the new startForeground API, then use it. - if (mStartForeground != null) { - mStartForegroundArgs[0] = Integer.valueOf(id); - mStartForegroundArgs[1] = notification; - invokeMethod(mStartForeground, mStartForegroundArgs); - return; - } - - // Fall back on the old API. - mSetForegroundArgs[0] = Boolean.TRUE; - invokeMethod(mSetForeground, mSetForegroundArgs); - notificationManager.notify(id, notification); - } - - /** - * This is a wrapper around the new stopForeground method, using the older APIs if it is not available. - */ - private void stopForegroundCompat(int id) { - // If we have the new stopForeground API, then use it. - if (mStopForeground != null) { - mStopForegroundArgs[0] = Boolean.TRUE; - invokeMethod(mStopForeground, mStopForegroundArgs); - return; - } - - // Fall back on the old API. Note to cancel BEFORE changing the - // foreground state, since we could be killed at that point. - notificationManager.cancel(id); - mSetForegroundArgs[0] = Boolean.FALSE; - invokeMethod(mSetForeground, mSetForegroundArgs); - } - - private boolean isServiceWrapper = false; - public void onServiceCreate() { - try { - mStartForeground = context.getClass().getMethod("startForeground", START_FG_SIG); - mStopForeground = context.getClass().getMethod("stopForeground", STOP_FG_SIG); - isServiceWrapper = true; - return; - } catch (NoSuchMethodException e) { - // Running on an older platform. - mStartForeground = mStopForeground = null; - } - try { - mSetForeground = context.getClass().getMethod("setForeground", SET_FG_SIG); - } catch (NoSuchMethodException e) { - throw new IllegalStateException("OS doesn't have Service.startForeground OR Service.setForeground!"); - } - isServiceWrapper = true; + } public void onServiceDestroy() { @@ -178,77 +97,6 @@ public class SipNotifications { cancelCalls(); } - // Announces - - // // Register - // public synchronized void notifyRegisteredAccounts(ArrayList<SipProfileState> activeAccountsInfos, boolean showNumbers) { - // if (!isServiceWrapper) { - // Log.e(THIS_FILE, "Trying to create a service notification from outside the service"); - // return; - // } - // int icon = R.drawable.ic_stat_sipok; - // CharSequence tickerText = context.getString(R.string.service_ticker_registered_text); - // long when = System.currentTimeMillis(); - // - // - // Builder nb = new NotificationCompat.Builder(context); - // nb.setSmallIcon(icon); - // nb.setTicker(tickerText); - // nb.setWhen(when); - // Intent notificationIntent = new Intent(SipManager.ACTION_SIP_DIALER); - // notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - // PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT); - // - // RegistrationNotification contentView = new RegistrationNotification(context.getPackageName()); - // contentView.clearRegistrations(); - // if(!Compatibility.isCompatible(9)) { - // contentView.setTextsColor(notificationPrimaryTextColor); - // } - // contentView.addAccountInfos(context, activeAccountsInfos); - // - // // notification.setLatestEventInfo(context, contentTitle, - // // contentText, contentIntent); - // nb.setOngoing(true); - // nb.setOnlyAlertOnce(true); - // nb.setContentIntent(contentIntent); - // nb.setContent(contentView); - // - // Notification notification = nb.build(); - // notification.flags |= Notification.FLAG_NO_CLEAR; - // // We have to re-write content view because getNotification setLatestEventInfo implicitly - // notification.contentView = contentView; - // if (showNumbers) { - // // This only affects android 2.3 and lower - // notification.number = activeAccountsInfos.size(); - // } - // startForegroundCompat(REGISTER_NOTIF_ID, notification); - // } - - /** - * Format the remote contact name for the call info - * - * @param callInfo - * the callinfo to format - * @return the name to display for the contact - */ - private String formatRemoteContactString(String remoteContact) { - String formattedRemoteContact = remoteContact; - // TODO - return formattedRemoteContact; - } - - /** - * Format the notification title for a call info - * - * @param title - * @param callInfo - * @return - */ - private String formatNotificationTitle(int title, long accId) { - // TODO - return null; - } - // Calls public void showNotificationForCall(SipCall callInfo) { // TODO @@ -258,12 +106,6 @@ public class SipNotifications { // TODO } - private static String viewingRemoteFrom = null; - - public void setViewingMessageFrom(String remoteFrom) { - viewingRemoteFrom = remoteFrom; - } - protected static CharSequence buildTickerMessage(Context context, String address, String body) { String displayAddress = address; @@ -283,15 +125,6 @@ public class SipNotifications { return spanText; } - // Cancels - public final void cancelRegisters() { - if (!isServiceWrapper) { - Log.e(THIS_FILE, "Trying to cancel a service notification from outside the service"); - return; - } - stopForegroundCompat(REGISTER_NOTIF_ID); - } - public final void cancelCalls() { notificationManager.cancel(CALL_NOTIF_ID); } @@ -309,11 +142,6 @@ public class SipNotifications { } public final void cancelAll() { - // Do not cancel calls notification since it's possible that there is - // still an ongoing call. - if (isServiceWrapper) { - cancelRegisters(); - } cancelMessages(); cancelMissedCalls(); cancelVoicemails(); @@ -333,7 +161,7 @@ public class SipNotifications { nb.setContentTitle(context.getString(R.string.notif_missed_call_title)); nb.setContentText(context.getString(R.string.notif_missed_call_content, sipCall.getContact().getmDisplayName())); Intent notificationIntent = new Intent(context, HomeActivity.class); - notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT); // notification.setLatestEventInfo(context, contentTitle, @@ -348,4 +176,29 @@ public class SipNotifications { // startForegroundCompat(CALL_NOTIF_ID, notification); notificationManager.notify(CALL_NOTIF_ID, notification); } + + public void makeNotification(HashMap<String, SipCall> calls) { + if (calls.size() == 0) { + return; + } + Intent notificationIntent = new Intent(context, HomeActivity.class); + PendingIntent contentIntent = PendingIntent.getActivity(context, 007, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT); + + NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + nm.cancel(NOTIFICATION_ID); // clear previous notifications. + + NotificationCompat.Builder builder = new NotificationCompat.Builder(context); + + builder.setContentIntent(contentIntent).setOngoing(true).setSmallIcon(R.drawable.ic_launcher) + .setContentTitle(calls.size() + " ongoing calls").setTicker("Pending calls").setWhen(System.currentTimeMillis()).setAutoCancel(false); + builder.setPriority(NotificationCompat.PRIORITY_MAX); + Notification n = builder.build(); + + nm.notify(NOTIFICATION_ID, n); + } + + public void removeNotification() { + NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + nm.cancel(NOTIFICATION_ID); + } } \ No newline at end of file