diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 34dc33fb97b09774c9400f42ea485fec6151eb00..6c6345f51d1df1879c81934fbb4090fa03bb0b4c 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -45,6 +45,7 @@ as that of the covered work. <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> + <uses-permission android:name="android.permission.VIBRATE" /> <application android:name=".client.SFLphoneApplication" diff --git a/bin/AndroidManifest.xml b/bin/AndroidManifest.xml index 34dc33fb97b09774c9400f42ea485fec6151eb00..6c6345f51d1df1879c81934fbb4090fa03bb0b4c 100644 --- a/bin/AndroidManifest.xml +++ b/bin/AndroidManifest.xml @@ -45,6 +45,7 @@ as that of the covered work. <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> + <uses-permission android:name="android.permission.VIBRATE" /> <application android:name=".client.SFLphoneApplication" diff --git a/res/drawable/ic_contact_picture.png b/res/drawable/ic_contact_picture.png new file mode 100644 index 0000000000000000000000000000000000000000..1a2bfde385b770deff8237c256c118c81effe5b5 Binary files /dev/null and b/res/drawable/ic_contact_picture.png differ diff --git a/res/layout/item_contact.xml b/res/layout/item_contact.xml index eed4505b541cdc43c45948d7223ee9d63477a246..423ab662bd049f23978a31f1807a64eeb2b74808 100644 --- a/res/layout/item_contact.xml +++ b/res/layout/item_contact.xml @@ -45,24 +45,17 @@ as that of the covered work. android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" - android:layout_alignTop="@+id/button2" android:background="#00000000" android:drawableLeft="@drawable/call_pause" android:gravity="left|center_vertical" android:src="@drawable/call_pause" android:visibility="gone" /> - <Button - android:id="@+id/button2" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignParentBottom="true" - android:layout_toRightOf="@+id/toggleButton1" - android:text="Button" - android:visibility="gone" /> + <ImageView android:id="@+id/photo" android:layout_width="70dp" android:layout_height="70dp" + android:scaleType="centerCrop" android:src="@drawable/box_border" /> <TextView android:id="@+id/display_name" @@ -70,9 +63,9 @@ as that of the covered work. android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_toRightOf="@+id/photo" + android:paddingLeft="@dimen/padding_small" android:paddingTop="@dimen/padding_small" - android:text="Contact Name" android:textAppearance="?android:attr/textAppearanceMedium" /> <TextView android:id="@+id/phones" diff --git a/src/com/savoirfairelinux/sflphone/adapters/CallElementAdapter.java b/src/com/savoirfairelinux/sflphone/adapters/CallElementAdapter.java index 5196cf894fc9b22f8cfc04462d84bbedf327e673..35b694ffc79368c261564e9e68d120aac6068bc9 100644 --- a/src/com/savoirfairelinux/sflphone/adapters/CallElementAdapter.java +++ b/src/com/savoirfairelinux/sflphone/adapters/CallElementAdapter.java @@ -9,8 +9,6 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; -import android.widget.Button; -import android.widget.ImageButton; import android.widget.ImageView; import android.widget.TextView; @@ -46,8 +44,6 @@ public class CallElementAdapter extends ArrayAdapter { // Hold the view objects in an object // so they don't need to be re-fetched entryView = new CallElementView(); - entryView.toggleButton = (ImageButton) rowView.findViewById(R.id.toggleButton1); - entryView.button = (Button) rowView.findViewById(R.id.button2); entryView.photo = (ImageView) rowView.findViewById(R.id.photo); entryView.displayName = (TextView) rowView.findViewById(R.id.display_name); entryView.phones = (TextView) rowView.findViewById(R.id.phones); @@ -75,8 +71,6 @@ public class CallElementAdapter extends ArrayAdapter { * ViewHolder Pattern *********************/ public class CallElementView { - protected ImageButton toggleButton; - protected Button button; protected ImageView photo; protected TextView displayName; protected TextView phones; diff --git a/src/com/savoirfairelinux/sflphone/client/CallActivity.java b/src/com/savoirfairelinux/sflphone/client/CallActivity.java index 3b0bfd5ab7fca67268b97846acc0376c942304c2..273ef5caaf92001ccb65eb379322f1cb1164bb70 100644 --- a/src/com/savoirfairelinux/sflphone/client/CallActivity.java +++ b/src/com/savoirfairelinux/sflphone/client/CallActivity.java @@ -33,14 +33,13 @@ package com.savoirfairelinux.sflphone.client; import android.app.Activity; import android.content.BroadcastReceiver; -import android.content.Context; import android.content.ComponentName; +import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; -import android.os.RemoteException; import android.support.v4.content.LocalBroadcastManager; import android.util.Log; import android.view.View; diff --git a/src/com/savoirfairelinux/sflphone/client/CallElementView.java b/src/com/savoirfairelinux/sflphone/client/CallElementView.java index 1031e09530a07ec059554fa38a3073d43562efd7..be580dee4fc5c674ec78cb2b9a45437c55e91d26 100644 --- a/src/com/savoirfairelinux/sflphone/client/CallElementView.java +++ b/src/com/savoirfairelinux/sflphone/client/CallElementView.java @@ -42,8 +42,6 @@ import android.view.animation.DecelerateInterpolator; import android.view.animation.Interpolator; import android.widget.FrameLayout; -import com.savoirfairelinux.sflphone.R; - public class CallElementView extends FrameLayout { private ViewGroup contactCard = null; private ViewGroup callCard = null; diff --git a/src/com/savoirfairelinux/sflphone/client/receiver/CallListReceiver.java b/src/com/savoirfairelinux/sflphone/client/receiver/CallListReceiver.java index ddf4efa6f0e1402cba8e0817a20580ca699f9edc..5b1dc16bde8103cf52dda1852b0ec3e3bff8a274 100644 --- a/src/com/savoirfairelinux/sflphone/client/receiver/CallListReceiver.java +++ b/src/com/savoirfairelinux/sflphone/client/receiver/CallListReceiver.java @@ -85,6 +85,10 @@ public class CallListReceiver extends BroadcastReceiver mHome = home; } + public CallListReceiver() { + // TODO Auto-generated constructor stub + } + @Override public void onReceive(Context context, Intent intent) { diff --git a/src/com/savoirfairelinux/sflphone/fragments/ButtonSectionFragment.java b/src/com/savoirfairelinux/sflphone/fragments/ButtonSectionFragment.java index 02c72e58fcd21213b6036e30d22750ba421c11d8..280f3dc63b17cd3226b3f2b7bb14bd300132155a 100644 --- a/src/com/savoirfairelinux/sflphone/fragments/ButtonSectionFragment.java +++ b/src/com/savoirfairelinux/sflphone/fragments/ButtonSectionFragment.java @@ -43,4 +43,8 @@ public class ButtonSectionFragment extends Fragment return view; } + + public void onClick(){ + Log.i(TAG,"onClik"); + } } diff --git a/src/com/savoirfairelinux/sflphone/fragments/ContactListFragment.java b/src/com/savoirfairelinux/sflphone/fragments/ContactListFragment.java index 18e8043df65d8ad62b3ed943aaa1cda41ee518b5..2cdca05040554bbcb258e0b46c7af8578e06bb61 100644 --- a/src/com/savoirfairelinux/sflphone/fragments/ContactListFragment.java +++ b/src/com/savoirfairelinux/sflphone/fragments/ContactListFragment.java @@ -77,15 +77,13 @@ import android.widget.SearchView.OnQueryTextListener; import android.widget.TextView; import com.savoirfairelinux.sflphone.R; -import com.savoirfairelinux.sflphone.account.AccountSelectionSpinner; import com.savoirfairelinux.sflphone.client.SFLPhoneHomeActivity; import com.savoirfairelinux.sflphone.client.SFLphoneApplication; import com.savoirfairelinux.sflphone.client.receiver.AccountListReceiver; import com.savoirfairelinux.sflphone.model.SipCall; import com.savoirfairelinux.sflphone.service.ISipService; -public class ContactListFragment extends ListFragment implements OnQueryTextListener, LoaderManager.LoaderCallbacks<Cursor> -{ +public class ContactListFragment extends ListFragment implements OnQueryTextListener, LoaderManager.LoaderCallbacks<Cursor> { final String TAG = "ContactListFragment"; ContactElementAdapter mAdapter; Activity mContext; @@ -96,8 +94,7 @@ public class ContactListFragment extends ListFragment implements OnQueryTextList private AccountListReceiver mAccountList; // These are the Contacts rows that we will retrieve. - static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] { Contacts._ID, Contacts.DISPLAY_NAME, - Contacts.PHOTO_ID, Contacts.LOOKUP_KEY }; + static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] { Contacts._ID, Contacts.DISPLAY_NAME, Contacts.PHOTO_ID, Contacts.LOOKUP_KEY }; static final String[] CONTACTS_PHONES_PROJECTION = new String[] { Phone.NUMBER, Phone.TYPE }; static final String[] CONTACTS_SIP_PROJECTION = new String[] { SipAddress.SIP_ADDRESS, SipAddress.TYPE }; @@ -112,21 +109,19 @@ public class ContactListFragment extends ListFragment implements OnQueryTextList Log.w(TAG, "onAttach() service=" + service + ", mAccountList=" + mAccountList); } - public static class InfosLoader implements Runnable - { - private View view; + public static class InfosLoader implements Runnable { + private ImageView view; private long cid; private ContentResolver cr; + private static final String TAG = InfosLoader.class.getSimpleName(); - public InfosLoader(Context context, View element, long contact_id) - { + public InfosLoader(Context context, ImageView element, long contact_id) { cid = contact_id; cr = context.getContentResolver(); view = element; } - public static Bitmap loadContactPhoto(ContentResolver cr, long id) - { + public static Bitmap loadContactPhoto(ContentResolver cr, long id) { Uri uri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, id); InputStream input = ContactsContract.Contacts.openContactPhotoInputStream(cr, uri); if (input == null) { @@ -136,14 +131,11 @@ public class ContactListFragment extends ListFragment implements OnQueryTextList } @Override - public void run() - { + public void run() { final Bitmap photo_bmp = loadContactPhoto(cr, cid); - Cursor phones = cr.query(CommonDataKinds.Phone.CONTENT_URI, - CONTACTS_PHONES_PROJECTION, CommonDataKinds.Phone.CONTACT_ID + " = ?", - new String[] { Long.toString(cid) }, - null); + Cursor phones = cr.query(CommonDataKinds.Phone.CONTENT_URI, CONTACTS_PHONES_PROJECTION, CommonDataKinds.Phone.CONTACT_ID + " = ?", + new String[] { Long.toString(cid) }, null); final List<String> numbers = new ArrayList<String>(); while (phones.moveToNext()) { @@ -154,28 +146,24 @@ public class ContactListFragment extends ListFragment implements OnQueryTextList phones.close(); final Bitmap bmp = photo_bmp; - view.post(new Runnable() - { + view.post(new Runnable() { @Override - public void run() - { + public void run() { + view.setImageBitmap(bmp); } }); } } - public static class ContactElementAdapter extends CursorAdapter - { + public static class ContactElementAdapter extends CursorAdapter { private ExecutorService infos_fetcher = Executors.newCachedThreadPool(); - - public ContactElementAdapter(Context context, Cursor c) - { + private static final String TAG = ContactElementAdapter.class.getSimpleName(); + public ContactElementAdapter(Context context, Cursor c) { super(context, c, 0); } @Override - public View newView(Context context, Cursor cursor, ViewGroup parent) - { + public View newView(Context context, Cursor cursor, ViewGroup parent) { LayoutInflater inflater = LayoutInflater.from(context); View v = inflater.inflate(R.layout.item_contact, parent, false); bindView(v, context, cursor); @@ -183,35 +171,33 @@ public class ContactListFragment extends ListFragment implements OnQueryTextList } @Override - public void bindView(final View view, Context context, Cursor cursor) - { + public void bindView(final View view, Context context, Cursor cursor) { final long contact_id = cursor.getLong(cursor.getColumnIndex(BaseColumns._ID)); final String display_name = cursor.getString(cursor.getColumnIndex(Contacts.DISPLAY_NAME)); - // final long photo_uri_string = cursor.getLong(cursor.getColumnIndex(Contacts.PHOTO_ID)); - // final String photo_uri_string = cursor.getString(cursor.getColumnIndex(Contacts.PHOTO_THUMBNAIL_URI)); + final long photo_id = cursor.getLong(cursor.getColumnIndex(Contacts.PHOTO_ID)); + Log.i(TAG,"photo_id "+photo_id); +// final String photo_uri_thumb_string = cursor.getString(cursor.getColumnIndex(Contacts.PHOTO_THUMBNAIL_URI)); TextView display_name_txt = (TextView) view.findViewById(R.id.display_name); display_name_txt.setText(display_name); ImageView photo_view = (ImageView) view.findViewById(R.id.photo); - photo_view.setVisibility(View.GONE); + // photo_view.setVisibility(View.GONE); - infos_fetcher.execute(new InfosLoader(context, view, contact_id)); + if (photo_id != 0) { + infos_fetcher.execute(new InfosLoader(context, photo_view, contact_id)); + } else { + photo_view.setImageDrawable(context.getResources().getDrawable(R.drawable.ic_contact_picture)); + } } }; - public ContactListFragment() - { - super(); - } - @Override - public void onActivityCreated(Bundle savedInstanceState) - { + public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); mContext = getActivity(); - // In order to onCreateOptionsMenu be called + // In order to onCreateOptionsMenu be called setHasOptionsMenu(true); mAdapter = new ContactElementAdapter(mContext, null); @@ -224,7 +210,7 @@ public class ContactListFragment extends ListFragment implements OnQueryTextList @Override public boolean onItemLongClick(AdapterView<?> av, View v, int pos, long id) { Log.i(TAG, "On Long Click"); - final CharSequence[] items = {"Make Call", "Send Message", "Add to Conference"}; + final CharSequence[] items = { "Make Call", "Send Message", "Add to Conference" }; final SipCall.CallInfo info = new SipCall.CallInfo(); info.mDisplayName = (String) ((TextView) v.findViewById(R.id.display_name)).getText(); info.mPhone = (String) ((TextView) v.findViewById(R.id.phones)).getText(); @@ -234,30 +220,29 @@ public class ContactListFragment extends ListFragment implements OnQueryTextList // FIXME service = sflphoneApplication.getSipService(); AlertDialog.Builder builder = new AlertDialog.Builder(mContext); - builder.setTitle("Action to perform with " + call.mCallInfo.mDisplayName) - .setCancelable(true) - .setItems(items, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int item) { - Log.i(TAG, "Selected " + items[item]); - switch (item) { - case 0: - call.placeCallUpdateUi(); - break; - case 1: - call.sendTextMessage(); - // Need to hangup this call immediately since no way to do it after this action - call.notifyServiceHangup(service); - break; - case 2: - call.addToConference(); - // Need to hangup this call immediately since no way to do it after this action - call.notifyServiceHangup(service); - break; - default: - break; - } - } - }); + builder.setTitle("Action to perform with " + call.mCallInfo.mDisplayName).setCancelable(true) + .setItems(items, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int item) { + Log.i(TAG, "Selected " + items[item]); + switch (item) { + case 0: + call.placeCallUpdateUi(); + break; + case 1: + call.sendTextMessage(); + // Need to hangup this call immediately since no way to do it after this action + call.notifyServiceHangup(service); + break; + case 2: + call.addToConference(); + // Need to hangup this call immediately since no way to do it after this action + call.notifyServiceHangup(service); + break; + default: + break; + } + } + }); AlertDialog alert = builder.create(); alert.show(); @@ -279,19 +264,17 @@ public class ContactListFragment extends ListFragment implements OnQueryTextList } @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) - { + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View inflatedView = inflater.inflate(R.layout.frag_contact_list, container, false); return inflatedView; } @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) - { + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { // Place an action bar item for searching MenuItem item = menu.add("Search"); item.setIcon(R.drawable.ic_menu_search); - + item.setShowAsAction(MenuItemCompat.SHOW_AS_ACTION_IF_ROOM | MenuItemCompat.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW); SearchView sv = new SearchView(getActivity()); sv.setOnQueryTextListener(this); @@ -299,8 +282,7 @@ public class ContactListFragment extends ListFragment implements OnQueryTextList } @Override - public void onListItemClick(ListView l, View v, int position, long id) - { + public void onListItemClick(ListView l, View v, int position, long id) { // Insert desired behavior here. SipCall.CallInfo callInfo = new SipCall.CallInfo(); callInfo.mDisplayName = (String) ((TextView) v.findViewById(R.id.display_name)).getText(); @@ -315,38 +297,39 @@ public class ContactListFragment extends ListFragment implements OnQueryTextList SipCall call = new SipCall(callInfo); // if(nbCallAfter > nbCallBefore) - // call.placeCall(); + // call.placeCall(); } @Override - public boolean onQueryTextChange(String newText) - { + public boolean onQueryTextChange(String newText) { // Called when the action bar search text has changed. Update // the search filter, and restart the loader to do a new query // with this filter. String newFilter = !TextUtils.isEmpty(newText) ? newText : null; // Don't do anything if the filter hasn't actually changed. // Prefents restarting the loader when restoring state. - if (mCurFilter == null && newFilter == null) { return true; } - if (mCurFilter != null && mCurFilter.equals(newFilter)) { return true; } + if (mCurFilter == null && newFilter == null) { + return true; + } + if (mCurFilter != null && mCurFilter.equals(newFilter)) { + return true; + } mCurFilter = newFilter; getLoaderManager().restartLoader(0, null, this); - return true; + return true; } @Override - public boolean onQueryTextSubmit(String query) - { + public boolean onQueryTextSubmit(String query) { // Return false to let the SearchView perform the default action return false; } @Override - public Loader<Cursor> onCreateLoader(int id, Bundle args) - { + public Loader<Cursor> onCreateLoader(int id, Bundle args) { Uri baseUri; - if(mCurFilter != null) { + if (mCurFilter != null) { baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, Uri.encode(mCurFilter)); } else { baseUri = Contacts.CONTENT_URI; @@ -354,28 +337,21 @@ public class ContactListFragment extends ListFragment implements OnQueryTextList // Now create and return a CursorLoader that will take care of // creating a Cursor for the data being displayed. - String select = "((" + Contacts.DISPLAY_NAME - + " NOTNULL) AND (" - + Contacts.HAS_PHONE_NUMBER - + "=1) AND (" - + Contacts.DISPLAY_NAME - + " != '' ))"; - - return new CursorLoader(getActivity(), baseUri, CONTACTS_SUMMARY_PROJECTION, - select, null, Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"); + String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND (" + Contacts.HAS_PHONE_NUMBER + "=1) AND (" + Contacts.DISPLAY_NAME + + " != '' ))"; + + return new CursorLoader(getActivity(), baseUri, CONTACTS_SUMMARY_PROJECTION, select, null, Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"); } @Override - public void onLoadFinished(Loader<Cursor> loader, Cursor data) - { + public void onLoadFinished(Loader<Cursor> loader, Cursor data) { // Swap the new cursor in. mAdapter.swapCursor(data); } @Override - public void onLoaderReset(Loader<Cursor> loader) - { - // Thi is called when the last Cursor provided to onLoadFinished + public void onLoaderReset(Loader<Cursor> loader) { + // Thi is called when the last Cursor provided to onLoadFinished mAdapter.swapCursor(null); } } diff --git a/src/com/savoirfairelinux/sflphone/service/SipService.java b/src/com/savoirfairelinux/sflphone/service/SipService.java index e0600065a809a8abc2b957f5cc4592bcd7d5e0f4..ec1f0b6d127b6e0049cbc1ee4528834244dbbbd0 100644 --- a/src/com/savoirfairelinux/sflphone/service/SipService.java +++ b/src/com/savoirfairelinux/sflphone/service/SipService.java @@ -24,26 +24,29 @@ package com.savoirfairelinux.sflphone.service; import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; import android.app.Service; +import android.content.BroadcastReceiver; +import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.os.Binder; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; import android.os.Looper; import android.os.Message; +import android.os.Vibrator; +import android.support.v4.content.LocalBroadcastManager; import android.util.Log; import android.widget.Toast; -import com.savoirfairelinux.sflphone.service.ManagerImpl; import com.savoirfairelinux.sflphone.account.AccountDetailsHandler; import com.savoirfairelinux.sflphone.client.SFLphoneApplication; -import com.savoirfairelinux.sflphone.service.ISipService; - -import java.util.Map; -import java.util.HashMap; -import java.util.ArrayList; +import com.savoirfairelinux.sflphone.client.receiver.CallListReceiver; public class SipService extends Service { @@ -60,6 +63,7 @@ public class SipService extends Service { private ConfigurationManagerCallback configurationManagerCallback; private ManagerImpl managerImpl; private boolean isPjSipStackStarted = false; + public CallListReceiver mCallList; /* Implement public interface for the service */ @@ -250,6 +254,16 @@ public class SipService extends Service { }); } }; + private BroadcastReceiver IncomingReceiver = new BroadcastReceiver() { + + @Override + public void onReceive(Context context, Intent intent) { + Log.i(TAG, "Received"+ intent.getAction()); + // Get instance of Vibrator from current Context + Vibrator mVibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); + mVibrator.vibrate(300); + } + }; /** * Class used for the client Binder. Because we know this service always @@ -269,6 +283,11 @@ public class SipService extends Service { super.onCreate(); sflphoneApp = (SFLphoneApplication) getApplication(); sipServiceThread = new SipServiceThread(); + mCallList = new CallListReceiver(); + + IntentFilter callFilter = new IntentFilter(CallManagerCallBack.NEW_CALL_CREATED); + callFilter.addAction(CallManagerCallBack.INCOMING_CALL); + LocalBroadcastManager.getInstance(this).registerReceiver(IncomingReceiver , callFilter); getExecutor().execute(new StartRunnable()); }