* Changed process of call creation
* Modified Fly-in menu layout
* Added SearchView in ContactList handle
diff --git a/src/com/savoirfairelinux/sflphone/adapters/CallPagerAdapter.java b/src/com/savoirfairelinux/sflphone/adapters/CallPagerAdapter.java
new file mode 100644
index 0000000..8daa9f1
--- /dev/null
+++ b/src/com/savoirfairelinux/sflphone/adapters/CallPagerAdapter.java
@@ -0,0 +1,127 @@
+package com.savoirfairelinux.sflphone.adapters;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.content.Context;
+import android.support.v13.app.FragmentStatePagerAdapter;
+import android.util.Log;
+
+import com.savoirfairelinux.sflphone.R;
+import com.savoirfairelinux.sflphone.fragments.CallElementListFragment;
+import com.savoirfairelinux.sflphone.fragments.CallFragment;
+import com.savoirfairelinux.sflphone.fragments.DialingFragment;
+import com.savoirfairelinux.sflphone.fragments.HistoryFragment;
+
+public class CallPagerAdapter extends FragmentStatePagerAdapter {
+
+ private static final String TAG = SectionsPagerAdapter.class.getSimpleName();
+ Context mContext;
+
+
+
+ HashMap<String,Fragment> calls;
+
+ public CallPagerAdapter(Context c, FragmentManager fm) {
+ super(fm);
+ mContext = c;
+ calls = new HashMap<String,Fragment>();
+ }
+
+ @Override
+ public Fragment getItem(int i) {
+
+ for(int j = 0 ; j <= i ; ++j){
+ calls.entrySet().iterator().next();
+ }
+
+
+ return calls.entrySet().iterator().next().getValue();
+ }
+
+// public Fragment getFragment(int i) {
+// Fragment fragment;
+//
+// switch (i) {
+// case 0:
+// fragment = new DialingFragment();
+// break;
+// case 1:
+// fragment = new CallElementListFragment();
+// break;
+// case 2:
+// fragment = new HistoryFragment();
+// break;
+// default:
+// Log.e(TAG, "getClassName: unknown fragment position " + i);
+// fragment = null;
+// }
+
+ // Log.w(TAG, "getFragment: fragment=" + fragment);
+// return fragment;
+// }
+
+ public String getClassName(int i) {
+ String name;
+
+ switch (i) {
+ case 0:
+ name = DialingFragment.class.getName();
+ break;
+ case 1:
+ name = CallElementListFragment.class.getName();
+ break;
+ case 2:
+ name = HistoryFragment.class.getName();
+ break;
+
+ default:
+ Log.e(TAG, "getClassName: unknown fragment position " + i);
+ return null;
+ }
+
+ // Log.w(TAG, "getClassName: name=" + name);
+ return name;
+ }
+
+ @Override
+ public int getCount() {
+ return calls.size();
+ }
+
+ @Override
+ public CharSequence getPageTitle(int position) {
+ switch (position) {
+ case 0:
+ return mContext.getString(R.string.title_section0).toUpperCase();
+ case 1:
+ return mContext.getString(R.string.title_section1).toUpperCase();
+ case 2:
+ return mContext.getString(R.string.title_section2).toUpperCase();
+ default:
+ Log.e(TAG, "getPageTitle: unknown tab position " + position);
+ break;
+ }
+ return null;
+ }
+
+ public void addCall(String mCallID, CallFragment newCall) {
+ Log.w(TAG, "Put "+mCallID);
+ calls.put(mCallID,newCall);
+ notifyDataSetChanged();
+ }
+
+ public Fragment getCall(String callID) {
+ Log.w(TAG, "Get "+callID);
+ return calls.get(callID);
+
+ }
+
+ public void remove(String callID) {
+// calls.remove(callID);
+// notifyDataSetChanged();
+
+ }
+}
\ No newline at end of file
diff --git a/src/com/savoirfairelinux/sflphone/adapters/ContactPictureLoader.java b/src/com/savoirfairelinux/sflphone/adapters/ContactPictureLoader.java
index 5e358b0..b020e50 100644
--- a/src/com/savoirfairelinux/sflphone/adapters/ContactPictureLoader.java
+++ b/src/com/savoirfairelinux/sflphone/adapters/ContactPictureLoader.java
@@ -19,67 +19,67 @@
import com.savoirfairelinux.sflphone.R;
-public class ContactPictureLoader implements Runnable
-{
- private ImageView view;
- private long cid;
- private ContentResolver cr;
- private final String TAG = ContactPictureLoader.class.getSimpleName();
+public class ContactPictureLoader implements Runnable {
+ private ImageView view;
+ private long cid;
+ private ContentResolver cr;
+ private final String TAG = ContactPictureLoader.class.getSimpleName();
- public ContactPictureLoader(Context context, ImageView element, long contact_id)
- {
- cid = contact_id;
- cr = context.getContentResolver();
- view = element;
- }
+ public ContactPictureLoader(Context context, ImageView element, long contact_id) {
+ cid = contact_id;
+ cr = context.getContentResolver();
+ view = element;
+ }
- 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) {
- return null;
- }
- return BitmapFactory.decodeStream(input);
- }
+ 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) {
+ return null;
+ }
+ return BitmapFactory.decodeStream(input);
+ }
- @Override
- public void run()
- {
- Bitmap photo_bmp = loadContactPhoto(cr, cid);
+ @Override
+ public void run() {
+ Bitmap photo_bmp = loadContactPhoto(cr, cid);
- if (photo_bmp == null) {
- photo_bmp = BitmapFactory.decodeResource(view.getResources(), R.drawable.ic_contact_picture);
- }
+ if (photo_bmp == null) {
+ photo_bmp = BitmapFactory.decodeResource(view.getResources(), R.drawable.ic_contact_picture);
+ }
- int w = photo_bmp.getWidth(), h = photo_bmp.getHeight();
+ int w = photo_bmp.getWidth(), h = photo_bmp.getHeight();
+ if (w > h) {
+ w = h;
+ } else if (h > w) {
+ h = w;
+ }
- final Bitmap externalBMP = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
+ final Bitmap externalBMP = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
- int radius = externalBMP.getWidth() / 2;
- Path path = new Path();
+ int radius = externalBMP.getWidth() / 2;
+ Path path = new Path();
- path.addCircle(radius, radius, radius, Path.Direction.CW);
- Paint mPaintPath = new Paint(Paint.ANTI_ALIAS_FLAG);
- mPaintPath.setStyle(Paint.Style.FILL);
- mPaintPath.setAntiAlias(true);
- Bitmap circle = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
- Canvas circle_drawer = new Canvas(circle);
- circle_drawer.drawOval(new RectF(0, 0, w, h), mPaintPath);
- mPaintPath.setFilterBitmap(false);
+ path.addCircle(radius, radius, radius, Path.Direction.CW);
+ Paint mPaintPath = new Paint(Paint.ANTI_ALIAS_FLAG);
+ mPaintPath.setStyle(Paint.Style.FILL);
+ mPaintPath.setAntiAlias(true);
+ Bitmap circle = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
+ Canvas circle_drawer = new Canvas(circle);
+ circle_drawer.drawOval(new RectF(0, 0, w, h), mPaintPath);
+ mPaintPath.setFilterBitmap(false);
- Canvas internalCanvas = new Canvas(externalBMP);
- internalCanvas.drawBitmap(photo_bmp, 0, 0, mPaintPath);
- mPaintPath.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
- internalCanvas.drawBitmap(circle, 0, 0, mPaintPath);
+ Canvas internalCanvas = new Canvas(externalBMP);
+ internalCanvas.drawBitmap(photo_bmp, 0, 0, mPaintPath);
+ mPaintPath.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
+ internalCanvas.drawBitmap(circle, 0, 0, mPaintPath);
- view.post(new Runnable() {
- @Override
- public void run()
- {
- view.setImageBitmap(externalBMP);
- view.invalidate();
- }
- });
- }
+ view.post(new Runnable() {
+ @Override
+ public void run() {
+ view.setImageBitmap(externalBMP);
+ view.invalidate();
+ }
+ });
+ }
}
diff --git a/src/com/savoirfairelinux/sflphone/adapters/MenuAdapter.java b/src/com/savoirfairelinux/sflphone/adapters/MenuAdapter.java
index 2f9ac3f..bf4a807 100644
--- a/src/com/savoirfairelinux/sflphone/adapters/MenuAdapter.java
+++ b/src/com/savoirfairelinux/sflphone/adapters/MenuAdapter.java
@@ -1,53 +1,117 @@
package com.savoirfairelinux.sflphone.adapters;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
import android.content.Context;
-import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.Adapter;
+import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
-import android.widget.TextView;
import com.savoirfairelinux.sflphone.R;
-public class MenuAdapter extends BaseAdapter{
-
- private static final String TAG = MenuAdapter.class.getSimpleName();
- private Context mContext;
- String categories[];
+public class MenuAdapter extends BaseAdapter {
+ public final Map<String, Adapter> sections = new LinkedHashMap<String, Adapter>();
+ public final ArrayAdapter<String> headers;
+ public final static int TYPE_SECTION_HEADER = 0;
- public MenuAdapter(Context c, String[] cat) {
- mContext = c;
- categories = cat;
+ public MenuAdapter(Context context) {
+ headers = new ArrayAdapter<String>(context, R.layout.item_menu_header);
}
- @Override
- public View getView(int pos, View convertView, ViewGroup parent) {
- View v = convertView;
+ public void addSection(String section, Adapter adapter) {
+ this.headers.add(section);
+ this.sections.put(section, adapter);
+ }
- LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- if (v == null) {
- v = inflater.inflate(R.layout.item_menu, null);
+ public Object getItem(int position) {
+ for (Object section : this.sections.keySet()) {
+ Adapter adapter = sections.get(section);
+ int size = adapter.getCount() + 1;
+
+ // check if position inside this section
+ if (position == 0)
+ return section;
+ if (position < size)
+ return adapter.getItem(position - 1);
+
+ // otherwise jump into next section
+ position -= size;
}
-
- ((TextView) v.findViewById(R.id.menu_title_categorie)).setText(categories[pos]);
-
- return v;
+ return null;
}
- @Override
public int getCount() {
- return categories.length;
+ // total together all sections, plus one for each section header
+ int total = 0;
+ for (Adapter adapter : this.sections.values())
+ total += adapter.getCount() + 1;
+ return total;
}
@Override
- public String getItem(int pos) {
- return categories[pos];
+ public int getViewTypeCount() {
+ // assume that headers count as one, then total all sections
+ int total = 1;
+ for (Adapter adapter : this.sections.values())
+ total += adapter.getViewTypeCount();
+ return total;
}
@Override
- public long getItemId(int arg0) {
- return 0;
- }
-
+ public int getItemViewType(int position) {
+ int type = 1;
+ for (Object section : this.sections.keySet()) {
+ Adapter adapter = sections.get(section);
+ int size = adapter.getCount() + 1;
-}
+ // check if position inside this section
+ if (position == 0)
+ return TYPE_SECTION_HEADER;
+ if (position < size)
+ return type + adapter.getItemViewType(position - 1);
+
+ // otherwise jump into next section
+ position -= size;
+ type += adapter.getViewTypeCount();
+ }
+ return -1;
+ }
+
+ public boolean areAllItemsSelectable() {
+ return false;
+ }
+
+ @Override
+ public boolean isEnabled(int position) {
+ return (getItemViewType(position) != TYPE_SECTION_HEADER);
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ int sectionnum = 0;
+ for (Object section : this.sections.keySet()) {
+ Adapter adapter = sections.get(section);
+ int size = adapter.getCount() + 1;
+
+ // check if position inside this section
+ if (position == 0)
+ return headers.getView(sectionnum, convertView, parent);
+ if (position < size)
+ return adapter.getView(position - 1, convertView, parent);
+
+ // otherwise jump into next section
+ position -= size;
+ sectionnum++;
+ }
+ return null;
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+
+}
\ No newline at end of file
diff --git a/src/com/savoirfairelinux/sflphone/client/CallActivity.java b/src/com/savoirfairelinux/sflphone/client/CallActivity.java
index 122ee33..1f39852 100644
--- a/src/com/savoirfairelinux/sflphone/client/CallActivity.java
+++ b/src/com/savoirfairelinux/sflphone/client/CallActivity.java
@@ -32,8 +32,6 @@
package com.savoirfairelinux.sflphone.client;
-import java.util.HashMap;
-import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -41,48 +39,37 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.ServiceConnection;
-import android.graphics.Bitmap;
-import android.graphics.PointF;
import android.os.Bundle;
import android.os.IBinder;
-import android.os.Parcelable;
import android.os.RemoteException;
-import android.util.DisplayMetrics;
+import android.support.v4.view.ViewPager;
import android.util.Log;
import android.widget.Toast;
import com.savoirfairelinux.sflphone.R;
-import com.savoirfairelinux.sflphone.adapters.ContactPictureLoader;
-import com.savoirfairelinux.sflphone.client.receiver.CallListReceiver;
-import com.savoirfairelinux.sflphone.model.Attractor;
-import com.savoirfairelinux.sflphone.model.Bubble;
-import com.savoirfairelinux.sflphone.model.BubbleModel;
-import com.savoirfairelinux.sflphone.model.BubblesView;
-import com.savoirfairelinux.sflphone.model.CallContact;
+import com.savoirfairelinux.sflphone.adapters.CallPagerAdapter;
+import com.savoirfairelinux.sflphone.client.receiver.CallReceiver;
+import com.savoirfairelinux.sflphone.fragments.CallFragment;
+import com.savoirfairelinux.sflphone.interfaces.CallInterface;
import com.savoirfairelinux.sflphone.model.SipCall;
-import com.savoirfairelinux.sflphone.service.ISipClient;
+import com.savoirfairelinux.sflphone.service.CallManagerCallBack;
import com.savoirfairelinux.sflphone.service.ISipService;
import com.savoirfairelinux.sflphone.service.SipService;
-public class CallActivity extends Activity {
+public class CallActivity extends Activity implements CallInterface, CallFragment.Callbacks {
static final String TAG = "CallActivity";
private ISipService service;
+
private String pendingAction = null;
- private SipCall mCall;
-
- private BubblesView view;
- private BubbleModel model;
- private PointF screenCenter;
- private DisplayMetrics metrics;
-
- private HashMap<CallContact, Bubble> contacts = new HashMap<CallContact, Bubble>();
private ExecutorService infos_fetcher = Executors.newCachedThreadPool();
+ CallReceiver receiver;
- public interface CallFragment {
- void setCall(SipCall c);
- }
+ ViewPager vp;
+ private CallPagerAdapter mCallPagerAdapter;
+ private ViewPager mViewPager;
/*
* private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
@@ -93,140 +80,50 @@
* if (signalName.equals(CallManagerCallBack.NEW_CALL_CREATED)) { } else if (signalName.equals(CallManagerCallBack.CALL_STATE_CHANGED)) {
* processCallStateChangedSignal(intent); } else if (signalName.equals(CallManagerCallBack.INCOMING_CALL)) { } } };
*/
- private ISipClient callback = new ISipClient.Stub() {
-
- @Override
- public void incomingCall(Intent call) throws RemoteException {
- Log.i(TAG, "Incoming call transfered from Service");
- SipCall.CallInfo infos = new SipCall.CallInfo(call);
- SipCall c = new SipCall(infos);
- //
- }
-
- @Override
- public void callStateChanged(Intent callState) throws RemoteException {
- Bundle b = callState.getBundleExtra("com.savoirfairelinux.sflphone.service.newstate");
- String cID = b.getString("CallID");
- String state = b.getString("State");
- Log.i(TAG, "callStateChanged" + cID + " " + state);
- processCallStateChangedSignal(cID, state);
- }
-
- @Override
- public void incomingText(Intent msg) throws RemoteException {
- Bundle b = msg.getBundleExtra("com.savoirfairelinux.sflphone.service.newtext");
- b.getString("CallID");
- String from = b.getString("From");
- String mess = b.getString("Msg");
- Toast.makeText(getApplicationContext(), "text from " + from + " : " + mess, Toast.LENGTH_LONG).show();
- }
- };
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.bubbleview_layout);
+ setContentView(R.layout.activity_call_layout);
- model = new BubbleModel(getResources().getDisplayMetrics().density);
- metrics = getResources().getDisplayMetrics();
- screenCenter = new PointF(metrics.widthPixels / 2, metrics.heightPixels / 3);
- // radiusCalls = metrics.widthPixels / 2 - 150;
- // model.listBubbles.add(new Bubble(this, metrics.widthPixels / 2, metrics.heightPixels / 4, 150, R.drawable.me));
- // model.listBubbles.add(new Bubble(this, metrics.widthPixels / 2, metrics.heightPixels / 4 * 3, 150, R.drawable.callee));
+ receiver = new CallReceiver(this);
- view = (BubblesView) findViewById(R.id.main_view);
- view.setModel(model);
+ if (mCallPagerAdapter == null) {
+ mCallPagerAdapter = new CallPagerAdapter(this, getFragmentManager());
+ }
+
+ mViewPager = (ViewPager) findViewById(R.id.pager);
+
+ mViewPager.setAdapter(mCallPagerAdapter);
Bundle b = getIntent().getExtras();
-
- SipCall.CallInfo info = b.getParcelable("CallInfo");
- Log.i(TAG, "Starting activity for call " + info.mCallID);
- mCall = new SipCall(info);
-
Intent intent = new Intent(this, SipService.class);
// setCallStateDisplay(mCall.getCallStateString());
- pendingAction = b.getString("action");
- if (pendingAction != null && pendingAction.equals("call")) {
- CallContact contact = b.getParcelable("CallContact");
-
- Log.i(TAG, "Calling " + contact.getmDisplayName());
- callContact(contact);
- // SipCall.CallInfo info = new SipCall.CallInfo();
- // Random random = new Random();
- // String callID = Integer.toString(random.nextInt());
- // Phone phone = contact.getSipPhone();
-
- // info.mCallID = callID;
- // info.mAccountID = ""+contact.getId();
- // info.mDisplayName = contact.getmDisplayName();
- // info.mPhone = phone==null?null:phone.toString();
- // info.mEmail = contact.getmEmail();
- // info.mCallType = SipCall.CALL_TYPE_OUTGOING;
-
- // mCall = CallListReceiver.getCallInstance(info);
-
- // mCallbacks.onCallSelected(call);
-
- /*
- * try { service.placeCall(info.mAccountID, info.mCallID, info.mPhone); } catch (RemoteException e) { Log.e(TAG,
- * "Cannot call service method", e); }
- */
-
- } else if (pendingAction.equals("incoming")) {
- callIncoming();
- }
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
- /*
- * LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, new IntentFilter(CallManagerCallBack.NEW_CALL_CREATED));
- * LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, new IntentFilter(CallManagerCallBack.CALL_STATE_CHANGED));
- * LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, new IntentFilter(CallManagerCallBack.INCOMING_CALL));
- */
}
- private void callContact(final CallContact contact) {
- // TODO off-thread image loading
- Bubble contact_bubble;
- if (contact.getPhoto_id() > 0) {
- Bitmap photo = ContactPictureLoader.loadContactPhoto(getContentResolver(), contact.getId());
- contact_bubble = new Bubble(this, screenCenter.x, screenCenter.y, 150, photo);
- } else {
- contact_bubble = new Bubble(this, screenCenter.x, screenCenter.y, 150, R.drawable.ic_contact_picture);
- }
-
- model.attractors.clear();
- model.attractors.add(new Attractor(new PointF(metrics.widthPixels / 2, metrics.heightPixels * .8f), new Attractor.Callback() {
- @Override
- public void onBubbleSucked(Bubble b) {
- Log.w(TAG, "Bubble sucked ! ");
- onCallEnded();
- }
- }));
-
- contact_bubble.contact = contact;
- model.listBubbles.add(contact_bubble);
- contacts.put(contact, contact_bubble);
+ /* activity gets back to the foreground and user input */
+ @Override
+ protected void onResume() {
+ Log.i(TAG, "onResume");
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(CallManagerCallBack.INCOMING_CALL);
+ intentFilter.addAction(CallManagerCallBack.INCOMING_TEXT);
+ intentFilter.addAction(CallManagerCallBack.CALL_STATE_CHANGED);
+ registerReceiver(receiver, intentFilter);
+ super.onResume();
}
- private void callIncoming() {
- model.attractors.clear();
- model.attractors.add(new Attractor(new PointF(3 * metrics.widthPixels / 4, metrics.heightPixels / 4), new Attractor.Callback() {
- @Override
- public void onBubbleSucked(Bubble b) {
- onCallAccepted();
- }
- }));
- model.attractors.add(new Attractor(new PointF(metrics.widthPixels / 4, metrics.heightPixels / 4), new Attractor.Callback() {
- @Override
- public void onBubbleSucked(Bubble b) {
- onCallRejected();
- }
- }));
-
+ /* activity no more in foreground */
+ @Override
+ protected void onPause() {
+ super.onPause();
+ unregisterReceiver(receiver);
}
@Override
@@ -243,30 +140,13 @@
@Override
public void onServiceConnected(ComponentName className, IBinder binder) {
service = ISipService.Stub.asInterface(binder);
- try {
- service.registerClient(callback);
- if (pendingAction != null && pendingAction.contentEquals("call")) {
+ Log.i(TAG, "Placing call");
+ CallFragment newCall = new CallFragment();
+ newCall.setArguments(getIntent().getExtras());
+ getIntent().getExtras();
+ SipCall.CallInfo info = getIntent().getExtras().getParcelable("CallInfo");
+ mCallPagerAdapter.addCall(info.mCallID, newCall);
- Log.i(TAG, "Placing call");
- CallContact contact = model.listBubbles.get(0).contact;
-
- String callID = Integer.toString(new Random().nextInt());
- SipCall.CallInfo info = new SipCall.CallInfo();
- info.mCallID = callID;
- info.mAccountID = service.getAccountList().get(0).toString();
- info.mDisplayName = contact.getmDisplayName();
- info.mPhone = contact.getSipPhone().getNumber();
- info.mEmail = contact.getmEmail();
- info.mCallType = SipCall.CALL_TYPE_OUTGOING;
-
- mCall = CallListReceiver.getCallInstance(info);
-
- service.placeCall(info.mAccountID, info.mCallID, info.mPhone);
- pendingAction = null;
- }
- } catch (RemoteException e) {
- Log.e(TAG, e.toString());
- }
}
@Override
@@ -274,104 +154,73 @@
}
};
- private void processCallStateChangedSignal(String callID, String newState) {
+ @Override
+ public void incomingCall(Intent call) {
+ Toast.makeText(this, "New Call incoming", Toast.LENGTH_LONG).show();
+
+ // TODO Handle multicall here
+
+ }
+
+ @Override
+ public void callStateChanged(Intent callState) {
+
+ Bundle b = callState.getBundleExtra("com.savoirfairelinux.sflphone.service.newstate");
+ processCallStateChangedSignal(b.getString("CallID"), b.getString("State"));
+
+ }
+
+ public void processCallStateChangedSignal(String callID, String newState) {
/*
* Bundle bundle = intent.getBundleExtra("com.savoirfairelinux.sflphone.service.newstate"); String callID = bundle.getString("CallID"); String
* newState = bundle.getString("State");
*/
+ CallFragment fr = (CallFragment) mCallPagerAdapter.getCall(callID);
if (newState.equals("INCOMING")) {
- mCall.setCallState(SipCall.CALL_STATE_INCOMING);
- setCallStateDisplay(newState);
+ fr.changeCallState(SipCall.CALL_STATE_INCOMING);
+
} else if (newState.equals("RINGING")) {
- mCall.setCallState(SipCall.CALL_STATE_RINGING);
- setCallStateDisplay(newState);
+ fr.changeCallState(SipCall.CALL_STATE_RINGING);
+
} else if (newState.equals("CURRENT")) {
- mCall.setCallState(SipCall.CALL_STATE_CURRENT);
- setCallStateDisplay(newState);
+ fr.changeCallState(SipCall.CALL_STATE_CURRENT);
+
} else if (newState.equals("HUNGUP")) {
- mCall.setCallState(SipCall.CALL_STATE_HUNGUP);
- setCallStateDisplay(newState);
- finish();
+// mCallPagerAdapter.remove(callID);
+
} else if (newState.equals("BUSY")) {
- mCall.setCallState(SipCall.CALL_STATE_BUSY);
- setCallStateDisplay(newState);
+// mCallPagerAdapter.remove(callID);
+
} else if (newState.equals("FAILURE")) {
- mCall.setCallState(SipCall.CALL_STATE_FAILURE);
- setCallStateDisplay(newState);
+// mCallPagerAdapter.remove(callID);
+
} else if (newState.equals("HOLD")) {
- mCall.setCallState(SipCall.CALL_STATE_HOLD);
- setCallStateDisplay(newState);
+ fr.changeCallState(SipCall.CALL_STATE_HOLD);
+
} else if (newState.equals("UNHOLD")) {
- mCall.setCallState(SipCall.CALL_STATE_CURRENT);
- setCallStateDisplay("CURRENT");
+ fr.changeCallState(SipCall.CALL_STATE_CURRENT);
+
} else {
- mCall.setCallState(SipCall.CALL_STATE_NONE);
- setCallStateDisplay(newState);
+ fr.changeCallState(SipCall.CALL_STATE_NONE);
+
}
Log.w(TAG, "processCallStateChangedSignal " + newState);
}
- private void setCallStateDisplay(String newState) {
- if (newState == null || newState.equals("NULL")) {
- newState = "INCOMING";
- }
+ @Override
+ public void incomingText(Intent msg) {
+ Toast.makeText(this, "New Call incoming", Toast.LENGTH_LONG).show();
- Log.w(TAG, "setCallStateDisplay " + newState);
-
- /*
- * mCall.printCallInfo();
- *
- * FragmentManager fm = getFragmentManager(); Fragment newf, f = fm.findFragmentByTag("call_fragment"); boolean replace = true; if
- * (newState.equals("INCOMING") && !(f instanceof IncomingCallFragment)) { newf = new IncomingCallFragment(); } else if
- * (!newState.equals("INCOMING") && !(f instanceof OngoingCallFragment)) { newf = new OngoingCallFragment(); } else { replace = false; newf =
- * f; }
- *
- * ((CallFragment) newf).setCall(mCall);
- *
- * if (replace) { FragmentTransaction ft = fm.beginTransaction(); if(f != null) // do not animate if there is no previous fragment
- * ft.setCustomAnimations(R.animator.slide_in, R.animator.slide_out); //ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
- * ft.replace(R.id.fragment_layout, newf, "call_fragment").commit(); }
- */
- }
-
- public void onCallAccepted() {
- mCall.notifyServiceAnswer(service);
- }
-
- public void onCallRejected() {
- if (mCall.notifyServiceHangup(service))
- finish();
- }
-
- public void onCallEnded() {
- if (mCall.notifyServiceHangup(service))
- finish();
- }
-
- public void onCallSuspended() {
- mCall.notifyServiceHold(service);
- }
-
- public void onCallResumed() {
- mCall.notifyServiceUnhold(service);
- }
-
- public void onCalltransfered(String to) {
- mCall.notifyServiceTransfer(service, to);
+ // TODO link text message to associate call and display it at the right place
}
- public void onRecordCall() {
- mCall.notifyServiceRecord(service);
-
- }
-
- public void onSendMessage(String msg) {
- mCall.notifyServiceSendMsg(service, msg);
-
+ @Override
+ public ISipService getService() {
+ return service;
}
}
diff --git a/src/com/savoirfairelinux/sflphone/client/SFLPhoneHomeActivity.java b/src/com/savoirfairelinux/sflphone/client/SFLPhoneHomeActivity.java
index 1a26b15..c0b9409 100644
--- a/src/com/savoirfairelinux/sflphone/client/SFLPhoneHomeActivity.java
+++ b/src/com/savoirfairelinux/sflphone/client/SFLPhoneHomeActivity.java
@@ -30,6 +30,8 @@
*/
package com.savoirfairelinux.sflphone.client;
+import java.util.Random;
+
import android.app.ActionBar;
import android.app.Activity;
import android.app.Fragment;
@@ -37,6 +39,7 @@
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;
@@ -48,28 +51,31 @@
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
-import android.view.View.OnClickListener;
import android.widget.ImageButton;
import android.widget.RelativeLayout;
import android.widget.Toast;
import com.savoirfairelinux.sflphone.R;
import com.savoirfairelinux.sflphone.adapters.SectionsPagerAdapter;
+import com.savoirfairelinux.sflphone.client.receiver.CallReceiver;
import com.savoirfairelinux.sflphone.fragments.CallElementListFragment;
import com.savoirfairelinux.sflphone.fragments.ContactListFragment;
import com.savoirfairelinux.sflphone.fragments.DialingFragment;
import com.savoirfairelinux.sflphone.fragments.HistoryFragment;
import com.savoirfairelinux.sflphone.fragments.MenuFragment;
+import com.savoirfairelinux.sflphone.interfaces.CallInterface;
+import com.savoirfairelinux.sflphone.model.CallContact;
+import com.savoirfairelinux.sflphone.model.CallContact.ContactBuilder;
import com.savoirfairelinux.sflphone.model.SipCall;
-import com.savoirfairelinux.sflphone.service.ISipClient;
+import com.savoirfairelinux.sflphone.service.CallManagerCallBack;
import com.savoirfairelinux.sflphone.service.ISipService;
import com.savoirfairelinux.sflphone.service.SipService;
import com.savoirfairelinux.sflphone.views.CustomSlidingDrawer;
-public class SFLPhoneHomeActivity extends Activity implements ActionBar.TabListener, DialingFragment.Callbacks, CallElementListFragment.Callbacks,
- HistoryFragment.Callbacks {
+public class SFLPhoneHomeActivity extends Activity implements ActionBar.TabListener, DialingFragment.Callbacks, ContactListFragment.Callbacks,
+ CallElementListFragment.Callbacks, HistoryFragment.Callbacks, CallInterface {
SectionsPagerAdapter mSectionsPagerAdapter = null;
- static final String TAG = "SFLPhoneHome";
+ static final String TAG = "SFLPhoneHomeActivity";
ImageButton buttonCall, buttonHangup;
private ContactListFragment mContactsFragment = null;
@@ -94,15 +100,15 @@
RelativeLayout mSliderButton;
CustomSlidingDrawer mDrawer;
-
private DrawerLayout mDrawerLayout;
-
private ActionBarDrawerToggle mDrawerToggle;
/**
* The {@link ViewPager} that will host the section contents.
*/
ViewPager mViewPager;
+ CallReceiver receiver;
+
final private int[] icon_res_id = { R.drawable.ic_tab_call, R.drawable.ic_tab_call, R.drawable.ic_tab_history };
// public SFLPhoneHome extends Activity implements ActionBar.TabListener, OnClickListener
@@ -127,6 +133,8 @@
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ receiver = new CallReceiver(this);
+
String libraryPath = getApplicationInfo().dataDir + "/lib";
Log.i(TAG, libraryPath);
@@ -175,17 +183,9 @@
}
mDrawer = (CustomSlidingDrawer) findViewById(R.id.custom_sliding_drawer);
- mSliderButton = (RelativeLayout) findViewById(R.id.slider_button);
- ((ImageButton) mSliderButton.findViewById(R.id.contact_search)).setTag(R.id.contact_search, false);
- ((ImageButton) mSliderButton.findViewById(R.id.contact_search)).setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- Log.i(TAG, "Click on serach");
- mDrawer.toggle();
+ mContactsFragment.setHandleView((RelativeLayout) findViewById(R.id.slider_button));
- }
- });
mDrawer.setmTrackHandle(findViewById(R.id.handle_title));
final ActionBar actionBar = getActionBar();
@@ -262,6 +262,11 @@
@Override
protected void onResume() {
Log.i(TAG, "onResume");
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(CallManagerCallBack.INCOMING_CALL);
+ intentFilter.addAction(CallManagerCallBack.INCOMING_TEXT);
+ intentFilter.addAction(CallManagerCallBack.CALL_STATE_CHANGED);
+ registerReceiver(receiver, intentFilter);
super.onResume();
}
@@ -269,6 +274,7 @@
@Override
protected void onPause() {
super.onPause();
+ unregisterReceiver(receiver);
}
/* activity is no longer visible */
@@ -287,63 +293,23 @@
mBound = false;
}
- /* unregister broadcast receiver */
- // LocalBroadcastManager.getInstance(this).unregisterReceiver(mCallList);
- // LocalBroadcastManager.getInstance(this).unregisterReceiver(mAccountList);
-
super.onDestroy();
}
- public void launchCallActivity(SipCall.CallInfo infos) {
+ public void launchCallActivity(SipCall.CallInfo infos, String action) {
Log.i(TAG, "Launch Call Activity");
Bundle bundle = new Bundle();
- bundle.putString("action", "incoming");
+ bundle.putString("action", action);
// bundle.putParcelable("CallContact", mListAdapter.getItem(pos));
bundle.putParcelable("CallInfo", infos);
Intent intent = new Intent().setClass(this, CallActivity.class);
intent.putExtras(bundle);
startActivityForResult(intent, REQUEST_CODE_CALL);
}
-
- private ISipClient callback = new ISipClient.Stub() {
-
- @Override
- public void incomingCall(Intent call) throws RemoteException {
- Log.i(TAG, "Incoming call transfered from Service");
- SipCall.CallInfo infos = new SipCall.CallInfo(call);
-
- SipCall c = new SipCall(infos);
- mCallElementList.addCall(c);
-
- launchCallActivity(infos);
- }
-
- @Override
- public void callStateChanged(Intent callState) throws RemoteException {
- Bundle b = callState.getBundleExtra("com.savoirfairelinux.sflphone.service.newstate");
- String cID = b.getString("CallID");
- String state = b.getString("State");
- Log.i(TAG, "callStateChanged" + cID + " " + state);
- mCallElementList.updateCall(cID, state);
-
- }
-
- @Override
- public void incomingText(Intent msg) throws RemoteException {
- Bundle b = msg.getBundleExtra("com.savoirfairelinux.sflphone.service.newtext");
- b.getString("CallID");
- String from = b.getString("From");
- String mess = b.getString("Msg");
- Toast.makeText(getApplicationContext(), "text from " + from + " : " + mess, Toast.LENGTH_LONG).show();
-
- }
- };
/** Defines callbacks for service binding, passed to bindService() */
private ServiceConnection mConnection = new ServiceConnection() {
-
-
@Override
public void onServiceConnected(ComponentName className, IBinder binder) {
service = ISipService.Stub.asInterface(binder);
@@ -354,11 +320,6 @@
mDialingFragment.onServiceSipBinded(service);
Log.d(TAG, "Service connected service=" + service);
- try {
- service.registerClient(callback);
- } catch (RemoteException e) {
- Log.e(TAG, e.toString());
- }
}
@Override
@@ -376,16 +337,6 @@
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
- // switch(item.getItemId()){
- // case R.id.menu_settings :
- // Intent launchPreferencesIntent = new Intent().setClass(this, SFLPhonePreferenceActivity.class);
- // startActivityForResult(launchPreferencesIntent, REQUEST_CODE_PREFERENCES);
- // break;
- // case R.id.menu_custom_draw:
- // Intent launchNewInterfaceIntent = new Intent().setClass(this, BubblesViewActivity.class);
- // startActivityForResult(launchNewInterfaceIntent, 0);
- // break;
- // }
return super.onOptionsItemSelected(item);
}
@@ -393,17 +344,13 @@
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
-
- switch (requestCode){
+
+ switch (requestCode) {
case REQUEST_CODE_PREFERENCES:
mCallElementList.onServiceSipBinded(service);
break;
case REQUEST_CODE_CALL:
- try {
- service.registerClient(callback);
- } catch (RemoteException e) {
- Log.e(TAG,e.toString());
- }
+
break;
}
@@ -438,7 +385,7 @@
@Override
public void onCallSelected(SipCall c) {
- launchCallActivity(c.mCallInfo);
+ // launchCallActivity(c.mCallInfo);
}
@@ -447,11 +394,81 @@
return service;
}
+ /**
+ * Interface implemented to handle incoming events
+ */
@Override
- public void onCallCreated(SipCall c) {
+ public void incomingCall(Intent call) {
+ Toast.makeText(this, "New Call incoming", Toast.LENGTH_LONG).show();
+ SipCall.CallInfo infos = new SipCall.CallInfo(call);
+ SipCall c = new SipCall(infos);
mCallElementList.addCall(c);
- launchCallActivity(c.mCallInfo);
+
+ CallContact.ContactBuilder builder = new ContactBuilder();
+ infos.contact = builder.buildUnknownContact(infos.mPhone);
+ launchCallActivity(infos, CallManagerCallBack.INCOMING_CALL);
+
+ }
+
+ @Override
+ public void callStateChanged(Intent callState) {
+ Bundle b = callState.getBundleExtra("com.savoirfairelinux.sflphone.service.newstate");
+ String cID = b.getString("CallID");
+ String state = b.getString("State");
+ Log.i(TAG, "callStateChanged" + cID + " " + state);
+ mCallElementList.updateCall(cID, state);
+
+ }
+
+ @Override
+ public void incomingText(Intent msg) {
+ Bundle b = msg.getBundleExtra("com.savoirfairelinux.sflphone.service.newtext");
+ b.getString("CallID");
+ String from = b.getString("From");
+ String mess = b.getString("Msg");
+ Toast.makeText(getApplicationContext(), "text from " + from + " : " + mess, Toast.LENGTH_LONG).show();
+ }
+
+ @Override
+ public void onContactSelected(CallContact c) {
+ String callID = Integer.toString(new Random().nextInt());
+ SipCall.CallInfo info = new SipCall.CallInfo();
+ info.mCallID = callID;
+ try {
+ info.mAccountID = service.getAccountList().get(1).toString();
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ info.mDisplayName = c.getmDisplayName();
+ info.mPhone = c.getSipPhone().getNumber();
+ info.mEmail = c.getmEmail();
+ info.mCallType = SipCall.CALL_TYPE_OUTGOING;
+ info.contact = c;
+
+ launchCallActivity(info, "call");
+
+ }
+
+ @Override
+ public void onCallDialed(String accountID, String to) {
+ Random random = new Random();
+ String callID = Integer.toString(random.nextInt());
+ SipCall.CallInfo info = new SipCall.CallInfo();
+
+ info.mCallID = callID;
+ info.mAccountID = accountID;
+ info.mDisplayName = "Username";
+ info.mPhone = to;
+ info.mEmail = "username@xxxx.com";
+ info.mCallType = SipCall.CALL_TYPE_OUTGOING;
+
+ CallContact.ContactBuilder builder = new ContactBuilder();
+
+ info.contact = builder.buildUnknownContact(to);
+
+ launchCallActivity(info, "call");
+
}
}
diff --git a/src/com/savoirfairelinux/sflphone/client/receiver/CallReceiver.java b/src/com/savoirfairelinux/sflphone/client/receiver/CallReceiver.java
new file mode 100644
index 0000000..f014e70
--- /dev/null
+++ b/src/com/savoirfairelinux/sflphone/client/receiver/CallReceiver.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2004-2012 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 com.savoirfairelinux.sflphone.client.receiver;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+
+import com.savoirfairelinux.sflphone.interfaces.CallInterface;
+import com.savoirfairelinux.sflphone.service.CallManagerCallBack;
+
+public class CallReceiver extends BroadcastReceiver{
+
+ static final String TAG = CallReceiver.class.getSimpleName();
+
+ CallInterface callback;
+
+ public CallReceiver(CallInterface client){
+ callback = client;
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent)
+ {
+ if( intent.getAction().contentEquals(CallManagerCallBack.INCOMING_CALL)){
+ callback.incomingCall(intent);
+ } else if (intent.getAction().contentEquals(CallManagerCallBack.INCOMING_TEXT)){
+ callback.incomingText(intent);
+ } else if(intent.getAction().contentEquals(CallManagerCallBack.CALL_STATE_CHANGED)){
+ callback.callStateChanged(intent);
+ } else {
+ Log.e(TAG, "Unknown action: "+intent.getAction());
+ }
+
+ }
+
+
+
+}
diff --git a/src/com/savoirfairelinux/sflphone/fragments/CallFragment.java b/src/com/savoirfairelinux/sflphone/fragments/CallFragment.java
new file mode 100644
index 0000000..5596565
--- /dev/null
+++ b/src/com/savoirfairelinux/sflphone/fragments/CallFragment.java
@@ -0,0 +1,203 @@
+package com.savoirfairelinux.sflphone.fragments;
+
+import java.util.HashMap;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.graphics.Bitmap;
+import android.graphics.PointF;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import com.savoirfairelinux.sflphone.R;
+import com.savoirfairelinux.sflphone.adapters.ContactPictureLoader;
+import com.savoirfairelinux.sflphone.model.Attractor;
+import com.savoirfairelinux.sflphone.model.Bubble;
+import com.savoirfairelinux.sflphone.model.BubbleModel;
+import com.savoirfairelinux.sflphone.model.BubblesView;
+import com.savoirfairelinux.sflphone.model.CallContact;
+import com.savoirfairelinux.sflphone.model.SipCall;
+import com.savoirfairelinux.sflphone.service.CallManagerCallBack;
+import com.savoirfairelinux.sflphone.service.ISipService;
+
+public class CallFragment extends Fragment {
+ static final String TAG = "CallFragment";
+
+ private SipCall mCall;
+
+ private BubblesView view;
+ private BubbleModel model;
+ private PointF screenCenter;
+ private DisplayMetrics metrics;
+
+ private Callbacks mCallbacks = sDummyCallbacks;
+
+ private HashMap<CallContact, Bubble> contacts = new HashMap<CallContact, Bubble>();
+
+ private TextView contact_name_txt;
+
+ @Override
+ public void onCreate(Bundle savedBundle) {
+ super.onCreate(savedBundle);
+ model = new BubbleModel(getResources().getDisplayMetrics().density);
+ metrics = getResources().getDisplayMetrics();
+ screenCenter = new PointF(metrics.widthPixels / 2, metrics.heightPixels / 3);
+ }
+
+ /**
+ * A dummy implementation of the {@link Callbacks} interface that does nothing. Used only when this fragment is not attached to an activity.
+ */
+ private static Callbacks sDummyCallbacks = new Callbacks() {
+
+ @Override
+ public ISipService getService() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ };
+
+ /**
+ * The Activity calling this fragment has to implement this interface
+ *
+ */
+ public interface Callbacks {
+ public ISipService getService();
+
+ }
+
+ @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;
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.frag_call, container, false);
+
+ view = (BubblesView) rootView.findViewById(R.id.main_view);
+ view.setModel(model);
+
+ Bundle b = getArguments();
+
+ SipCall.CallInfo info = b.getParcelable("CallInfo");
+ Log.i(TAG, "Starting fragment for call " + info.mCallID);
+ mCall = new SipCall(info);
+
+ String pendingAction = b.getString("action");
+ if (pendingAction != null && pendingAction.contentEquals("call")) {
+ callContact(info);
+ } else if (pendingAction.equals(CallManagerCallBack.INCOMING_CALL)) {
+ callIncoming();
+ }
+
+ return rootView;
+ }
+
+ private void callContact(SipCall.CallInfo infos) {
+ // TODO off-thread image loading
+ Bubble contact_bubble;
+ if (infos.contact.getPhoto_id() > 0) {
+ Bitmap photo = ContactPictureLoader.loadContactPhoto(getActivity().getContentResolver(), infos.contact.getId());
+ contact_bubble = new Bubble(getActivity(), screenCenter.x, screenCenter.y, 150, photo);
+ } else {
+ contact_bubble = new Bubble(getActivity(), screenCenter.x, screenCenter.y, 150, R.drawable.ic_contact_picture);
+ }
+
+ model.attractors.clear();
+ model.attractors.add(new Attractor(new PointF(metrics.widthPixels / 2, metrics.heightPixels * .8f), new Attractor.Callback() {
+ @Override
+ public void onBubbleSucked(Bubble b) {
+ Log.w(TAG, "Bubble sucked ! ");
+ onCallEnded();
+ }
+ }));
+
+ contact_bubble.contact = infos.contact;
+ model.listBubbles.add(contact_bubble);
+ contacts.put(infos.contact, contact_bubble);
+
+ try {
+ mCallbacks.getService().placeCall(infos.mAccountID, infos.mCallID, infos.mPhone);
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ }
+
+ private void callIncoming() {
+ model.attractors.clear();
+ model.attractors.add(new Attractor(new PointF(3 * metrics.widthPixels / 4, metrics.heightPixels / 4), new Attractor.Callback() {
+ @Override
+ public void onBubbleSucked(Bubble b) {
+ onCallAccepted();
+ }
+ }));
+ model.attractors.add(new Attractor(new PointF(metrics.widthPixels / 4, metrics.heightPixels / 4), new Attractor.Callback() {
+ @Override
+ public void onBubbleSucked(Bubble b) {
+ onCallRejected();
+ }
+ }));
+
+ }
+
+
+
+ public void onCallAccepted() {
+
+ mCall.notifyServiceAnswer(mCallbacks.getService());
+ }
+
+ public void onCallRejected() {
+ if (mCall.notifyServiceHangup(mCallbacks.getService()))
+ ;
+
+ }
+
+ public void onCallEnded() {
+ if (mCall.notifyServiceHangup(mCallbacks.getService()))
+ ;
+
+ }
+
+ public void onCallSuspended() {
+ mCall.notifyServiceHold(mCallbacks.getService());
+ }
+
+ public void onCallResumed() {
+ mCall.notifyServiceUnhold(mCallbacks.getService());
+ }
+
+ public void onCalltransfered(String to) {
+ mCall.notifyServiceTransfer(mCallbacks.getService(), to);
+
+ }
+
+ public void onRecordCall() {
+ mCall.notifyServiceRecord(mCallbacks.getService());
+
+ }
+
+ public void onSendMessage(String msg) {
+ mCall.notifyServiceSendMsg(mCallbacks.getService(), msg);
+
+ }
+
+ public void changeCallState(int callState) {
+ mCall.setCallState(callState);
+ }
+
+
+
+}
diff --git a/src/com/savoirfairelinux/sflphone/fragments/ContactListFragment.java b/src/com/savoirfairelinux/sflphone/fragments/ContactListFragment.java
index 2f6eed6..a330843 100644
--- a/src/com/savoirfairelinux/sflphone/fragments/ContactListFragment.java
+++ b/src/com/savoirfairelinux/sflphone/fragments/ContactListFragment.java
@@ -50,26 +50,32 @@
import android.view.MenuItem;
import android.view.View;
import android.view.View.DragShadowBuilder;
+import android.view.View.OnClickListener;
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.ImageButton;
import android.widget.ListView;
+import android.widget.RelativeLayout;
import android.widget.SearchView;
import android.widget.SearchView.OnQueryTextListener;
+import android.widget.ViewSwitcher;
import com.savoirfairelinux.sflphone.R;
import com.savoirfairelinux.sflphone.adapters.ContactsAdapter;
import com.savoirfairelinux.sflphone.adapters.StarredContactsAdapter;
import com.savoirfairelinux.sflphone.client.CallActivity;
+import com.savoirfairelinux.sflphone.fragments.HistoryFragment.Callbacks;
import com.savoirfairelinux.sflphone.loaders.ContactsLoader;
import com.savoirfairelinux.sflphone.model.CallContact;
import com.savoirfairelinux.sflphone.model.SipCall;
+import com.savoirfairelinux.sflphone.service.ISipService;
import com.savoirfairelinux.sflphone.views.TACGridView;
public class ContactListFragment extends Fragment implements OnQueryTextListener, LoaderManager.LoaderCallbacks<Bundle> {
- final String TAG = "ContactListFragment";
+ private static final String TAG = "ContactListFragment";
ContactsAdapter mListAdapter;
StarredContactsAdapter mGridAdapter;
@@ -84,9 +90,38 @@
mGridAdapter = new StarredContactsAdapter(getActivity());
}
+ private Callbacks mCallbacks = sDummyCallbacks;
+ /**
+ * A dummy implementation of the {@link Callbacks} interface that does nothing. Used only when this fragment is not attached to an activity.
+ */
+ private static Callbacks sDummyCallbacks = new Callbacks() {
+ @Override
+ public void onContactSelected(CallContact c) {
+ }
+
+ @Override
+ public ISipService getService() {
+ Log.i(TAG, "Dummy");
+ return null;
+ }
+
+ };
+
+ public interface Callbacks {
+ void onContactSelected(CallContact c);
+
+ public ISipService getService();
+
+ }
+
@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;
}
@Override
@@ -112,15 +147,15 @@
};
- private void launchCallActivity(CallContact c) {
- Log.i(TAG, "Launch Call Activity");
- Bundle bundle = new Bundle();
- bundle.putString("action", "call");
- bundle.putParcelable("CallContact", c);
- Intent intent = new Intent().setClass(getActivity(), CallActivity.class);
- intent.putExtras(bundle);
- getActivity().startActivity(intent);
- }
+// private void launchCallActivity(CallContact c) {
+// Log.i(TAG, "Launch Call Activity");
+// Bundle bundle = new Bundle();
+// bundle.putString("action", "call");
+// bundle.putParcelable("CallContact", c);
+// Intent intent = new Intent().setClass(getActivity(), CallActivity.class);
+// intent.putExtras(bundle);
+// getActivity().startActivity(intent);
+// }
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
@@ -132,7 +167,7 @@
@Override
public void onItemClick(AdapterView<?> arg0, View v, int pos, long arg3) {
- launchCallActivity(mListAdapter.getItem(pos));
+ mCallbacks.onContactSelected(mListAdapter.getItem(pos));
}
});
@@ -152,8 +187,8 @@
@Override
public void onItemClick(AdapterView<?> arg0, View v, int pos, long arg3) {
- launchCallActivity(mGridAdapter.getItem(pos));
-
+// launchCallActivity(mGridAdapter.getItem(pos));
+ mCallbacks.onContactSelected(mGridAdapter.getItem(pos));
}
});
grid.setOnItemLongClickListener(mItemLongClickListener);
@@ -187,15 +222,16 @@
}
};
+ private RelativeLayout mHandle;
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// Place an action bar item for searching
- inflater.inflate(R.menu.contact_list_menu, menu);
- MenuItem item = menu.findItem(R.id.menu_search);
- SearchView sv = new SearchView(getActivity());
- sv.setOnQueryTextListener(this);
- item.setActionView(sv);
+// inflater.inflate(R.menu.contact_list_menu, menu);
+// MenuItem item = menu.findItem(R.id.menu_search);
+// SearchView sv = new SearchView(getActivity());
+// sv.setOnQueryTextListener(this);
+// item.setActionView(sv);
}
@Override
@@ -256,4 +292,26 @@
// Thi is called when the last Cursor provided to onLoadFinished
// mListAdapter.swapCursor(null);
}
+
+ public void setHandleView(RelativeLayout handle) {
+ mHandle = handle;
+
+// ((ImageButton) handle.findViewById(R.id.contact_search)).setTag(R.id.contact_search, false);
+
+ ((SearchView)mHandle.findViewById(R.id.contact_search_text)).setOnQueryTextListener(this);
+
+
+// ((ImageButton) mHandle.findViewById(R.id.contact_search)).setOnClickListener(new OnClickListener() {
+//
+// @Override
+// public void onClick(View v) {
+// Log.i(TAG, "Click on serach");
+//// ((ViewSwitcher)mHandle.findViewById(R.id.view_switcher)).showNext();
+//// ((SearchView)mHandle.findViewById(R.id.contact_search_text)).
+//
+//
+// }
+// });
+
+ }
}
diff --git a/src/com/savoirfairelinux/sflphone/fragments/DialingFragment.java b/src/com/savoirfairelinux/sflphone/fragments/DialingFragment.java
index 1ab198a..724e2f9 100644
--- a/src/com/savoirfairelinux/sflphone/fragments/DialingFragment.java
+++ b/src/com/savoirfairelinux/sflphone/fragments/DialingFragment.java
@@ -42,7 +42,7 @@
*/
private static Callbacks sDummyCallbacks = new Callbacks() {
@Override
- public void onCallCreated(SipCall c) {
+ public void onCallDialed(String account, String to) {
}
@Override
@@ -57,7 +57,7 @@
*
*/
public interface Callbacks {
- public void onCallCreated(SipCall c);
+ void onCallDialed(String account, String to);
public ISipService getService();
@@ -95,7 +95,10 @@
((ImageButton) inflatedView.findViewById(R.id.buttonCall)).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
- processingNewCallAction();
+
+ String accountID = mAccountSelectionSpinner.getAccount();
+ String to = textField.getText().toString();
+ mCallbacks.onCallDialed(accountID, to);
}
});
@@ -133,33 +136,6 @@
}
- public void processingNewCallAction() {
- // String accountID = mAccountList.currentAccountID;
- String accountID = mAccountSelectionSpinner.getAccount();
-
- String to = textField.getText().toString();
-
- Random random = new Random();
- String callID = Integer.toString(random.nextInt());
- SipCall.CallInfo info = new SipCall.CallInfo();
-
- info.mCallID = callID;
- info.mAccountID = accountID;
- info.mDisplayName = "Cool Guy!";
- info.mPhone = to;
- info.mEmail = "coolGuy@coolGuy.com";
- info.mCallType = SipCall.CALL_TYPE_OUTGOING;
-
- SipCall call = CallListReceiver.getCallInstance(info);
- mCallbacks.onCallCreated(call);
-
- try {
- service.placeCall(info.mAccountID, info.mCallID, info.mPhone);
- } catch (RemoteException e) {
- Log.e(TAG, "Cannot call service method", e);
- }
-
- }
public String getSelectedAccount() {
return mAccountSelectionSpinner.getAccount();
diff --git a/src/com/savoirfairelinux/sflphone/fragments/MenuFragment.java b/src/com/savoirfairelinux/sflphone/fragments/MenuFragment.java
index f8a206c..93ab1e5 100644
--- a/src/com/savoirfairelinux/sflphone/fragments/MenuFragment.java
+++ b/src/com/savoirfairelinux/sflphone/fragments/MenuFragment.java
@@ -6,23 +6,23 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
import android.widget.ListView;
import com.savoirfairelinux.sflphone.R;
import com.savoirfairelinux.sflphone.adapters.MenuAdapter;
-public class MenuFragment extends Fragment{
-
+public class MenuFragment extends Fragment {
+
private static final String TAG = MenuFragment.class.getSimpleName();
public static final String ARG_SECTION_NUMBER = "section_number";
MenuAdapter mAdapter;
-
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
-
+
}
@Override
@@ -33,8 +33,20 @@
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-
- mAdapter = new MenuAdapter(getActivity(),getResources().getStringArray(R.array.menu_categories));
+
+ mAdapter = new MenuAdapter(getActivity());
+
+ String[] categories = getResources().getStringArray(R.array.menu_categories);
+ ArrayAdapter<String> paramAdapter = new ArrayAdapter<String>(getActivity(), R.layout.item_menu, getResources().getStringArray(
+ R.array.menu_items_param));
+ ArrayAdapter<String> helpAdapter = new ArrayAdapter<String>(getActivity(), R.layout.item_menu, getResources().getStringArray(
+ R.array.menu_items_help));
+
+ // Add Sections
+
+ mAdapter.addSection(categories[0], paramAdapter);
+ mAdapter.addSection(categories[1], helpAdapter);
+
}
@Override
@@ -51,5 +63,4 @@
}
-
}
diff --git a/src/com/savoirfairelinux/sflphone/interfaces/CallInterface.java b/src/com/savoirfairelinux/sflphone/interfaces/CallInterface.java
new file mode 100644
index 0000000..bf50872
--- /dev/null
+++ b/src/com/savoirfairelinux/sflphone/interfaces/CallInterface.java
@@ -0,0 +1,13 @@
+package com.savoirfairelinux.sflphone.interfaces;
+
+import android.content.Intent;
+
+public interface CallInterface {
+
+ public void incomingCall(Intent call);
+
+ public void callStateChanged(Intent callState);
+
+ public void incomingText(Intent msg);
+
+}
diff --git a/src/com/savoirfairelinux/sflphone/model/CallContact.java b/src/com/savoirfairelinux/sflphone/model/CallContact.java
index c658b8a..4a69012 100644
--- a/src/com/savoirfairelinux/sflphone/model/CallContact.java
+++ b/src/com/savoirfairelinux/sflphone/model/CallContact.java
@@ -155,6 +155,13 @@
return new ContactBuilder();
}
+ public CallContact buildUnknownContact(String to) {
+ phones = new ArrayList<Phone>();
+ phones.add(new Phone(to, 0));
+
+ return new CallContact(-1, to, 0, phones, new ArrayList<CallContact.Phone>(), "");
+ }
+
}
@Override
diff --git a/src/com/savoirfairelinux/sflphone/model/SipCall.java b/src/com/savoirfairelinux/sflphone/model/SipCall.java
index fcd826e..c00f757 100644
--- a/src/com/savoirfairelinux/sflphone/model/SipCall.java
+++ b/src/com/savoirfairelinux/sflphone/model/SipCall.java
@@ -76,6 +76,7 @@
public String mPhone = "";
public String mEmail = "";
public String mRemoteContact = "";
+ public CallContact contact = null;
public int mCallType = CALL_TYPE_UNDETERMINED;
public int mCallState = CALL_STATE_NONE;
public int mMediaState = MEDIA_STATE_NONE;
@@ -98,6 +99,7 @@
list.add(mRemoteContact);
out.writeStringList(list);
+ out.writeParcelable(contact, 0);
out.writeInt(mCallType);
out.writeInt(mCallState);
out.writeInt(mMediaState);
@@ -126,6 +128,7 @@
mEmail = list.get(4);
mRemoteContact = list.get(5);
+ contact = in.readParcelable(CallContact.class.getClassLoader());
mCallType = in.readInt();
mCallState = in.readInt();
mMediaState = in.readInt();
diff --git a/src/com/savoirfairelinux/sflphone/service/ISipService.aidl b/src/com/savoirfairelinux/sflphone/service/ISipService.aidl
index 25ac69c..b57b81d 100644
--- a/src/com/savoirfairelinux/sflphone/service/ISipService.aidl
+++ b/src/com/savoirfairelinux/sflphone/service/ISipService.aidl
@@ -1,6 +1,5 @@
package com.savoirfairelinux.sflphone.service;
-import com.savoirfairelinux.sflphone.service.ISipClient;
interface ISipService {
void placeCall(String accountID, in String callID, in String to);
@@ -29,9 +28,7 @@
/* IM */
void sendTextMessage(in String callID, in String message, in String from);
-
- void registerClient(in ISipClient callback);
-
+
void transfer(in String callID, in String to);
void attendedTransfer(in String transferID, in String targetID);
diff --git a/src/com/savoirfairelinux/sflphone/service/SipService.java b/src/com/savoirfairelinux/sflphone/service/SipService.java
index c8b5d3d..094bb8c 100644
--- a/src/com/savoirfairelinux/sflphone/service/SipService.java
+++ b/src/com/savoirfairelinux/sflphone/service/SipService.java
@@ -66,7 +66,6 @@
private ConfigurationManagerCallback configurationManagerCallback;
private ManagerImpl managerImpl;
private boolean isPjSipStackStarted = false;
- ISipClient client;
int clients = 0;
@@ -76,31 +75,23 @@
public void onReceive(Context context, Intent intent) {
// Get instance of Vibrator from current Context
- if (client != null) {
- try {
- if (intent.getAction().contentEquals(ConfigurationManagerCallback.ACCOUNT_STATE_CHANGED)) {
- Log.i(TAG, "Received" + intent.getAction());
- } else if (intent.getAction().contentEquals(ConfigurationManagerCallback.ACCOUNTS_LOADED)) {
- Log.i(TAG, "Received" + intent.getAction());
- } else if (intent.getAction().contentEquals(ConfigurationManagerCallback.ACCOUNTS_CHANGED)) {
- Log.i(TAG, "Received" + intent.getAction());
- } else if(intent.getAction().contentEquals(CallManagerCallBack.INCOMING_TEXT)) {
- Log.i(TAG, "Received" + intent.getAction());
- client.incomingText(intent);
- } else if (intent.getAction().contentEquals(CallManagerCallBack.INCOMING_CALL)) {
- Log.i(TAG, "Received" + intent.getAction());
- client.incomingCall(intent);
- } else if (intent.getAction().contentEquals(CallManagerCallBack.CALL_STATE_CHANGED)) {
- Log.i(TAG, "Received" + intent.getAction());
- client.callStateChanged(intent);
- } else if (intent.getAction().contentEquals(CallManagerCallBack.NEW_CALL_CREATED)) {
- Log.i(TAG, "Received" + intent.getAction());
- Vibrator mVibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
- mVibrator.vibrate(300);
- }
- } catch (RemoteException e) {
- Log.e(TAG, e.toString());
- }
+ if (intent.getAction().contentEquals(ConfigurationManagerCallback.ACCOUNT_STATE_CHANGED)) {
+ Log.i(TAG, "Received" + intent.getAction());
+ } else if (intent.getAction().contentEquals(ConfigurationManagerCallback.ACCOUNTS_LOADED)) {
+ Log.i(TAG, "Received" + intent.getAction());
+ } else if (intent.getAction().contentEquals(ConfigurationManagerCallback.ACCOUNTS_CHANGED)) {
+ Log.i(TAG, "Received" + intent.getAction());
+ } else if (intent.getAction().contentEquals(CallManagerCallBack.INCOMING_TEXT)) {
+ Log.i(TAG, "Received" + intent.getAction());
+ sendBroadcast(intent);
+ } else if (intent.getAction().contentEquals(CallManagerCallBack.INCOMING_CALL)) {
+ sendBroadcast(intent);
+ } else if (intent.getAction().contentEquals(CallManagerCallBack.CALL_STATE_CHANGED)) {
+ sendBroadcast(intent);
+ } else if (intent.getAction().contentEquals(CallManagerCallBack.NEW_CALL_CREATED)) {
+ Log.i(TAG, "Received" + intent.getAction());
+ Vibrator mVibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
+ mVibrator.vibrate(300);
}
}
@@ -442,7 +433,7 @@
CurrentAudioPlugin runInstance = new CurrentAudioPlugin();
getExecutor().execute(runInstance);
while (!runInstance.isDone()) {
-// Log.e(TAG, "Waiting for Nofing");
+ // Log.e(TAG, "Waiting for Nofing");
}
return (String) runInstance.getVal();
}
@@ -460,7 +451,7 @@
AccountList runInstance = new AccountList();
getExecutor().execute(runInstance);
while (!runInstance.isDone()) {
-// Log.e(TAG, "Waiting for Nofing");
+ // Log.e(TAG, "Waiting for Nofing");
}
StringVect swigvect = (StringVect) runInstance.getVal();
@@ -538,7 +529,7 @@
AddAccount runInstance = new AddAccount(swigmap);
getExecutor().execute(runInstance);
while (!runInstance.isDone()) {
-// Log.e(TAG, "Waiting for Nofing");
+ // Log.e(TAG, "Waiting for Nofing");
}
String accountId = (String) runInstance.getVal();
@@ -556,11 +547,7 @@
});
}
- @Override
- public void registerClient(ISipClient callback) throws RemoteException {
- client = callback;
- }
-
+
@Override
public ArrayList<HashMap<String, String>> getHistory() throws RemoteException {
class History extends SipRunnableWithReturn {
@@ -576,7 +563,7 @@
History runInstance = new History();
getExecutor().execute(runInstance);
while (!runInstance.isDone()) {
-// Log.w(TAG, "Waiting for getHistory");
+ // Log.w(TAG, "Waiting for getHistory");
}
VectMap swigmap = (VectMap) runInstance.getVal();
@@ -602,7 +589,7 @@
Intent intent = new Intent(CallManagerCallBack.CALL_STATE_CHANGED);
intent.putExtra(CallManagerCallBack.SIGNAL_NAME, CallManagerCallBack.CALL_STATE_CHANGED);
intent.putExtra("com.savoirfairelinux.sflphone.service.newstate", bundle);
- client.callStateChanged(intent);
+ sendBroadcast(intent);
} else
Log.i(TAG, "NOT OK");
}
@@ -762,7 +749,7 @@
ConfList runInstance = new ConfList();
getExecutor().execute(runInstance);
while (!runInstance.isDone()) {
-// Log.w(TAG, "Waiting for getConferenceList");
+ // Log.w(TAG, "Waiting for getConferenceList");
}
StringVect swigvect = (StringVect) runInstance.getVal();
@@ -806,7 +793,7 @@
RecordPath runInstance = new RecordPath();
getExecutor().execute(runInstance);
while (!runInstance.isDone()) {
-// Log.w(TAG, "Waiting for getRecordPath");
+ // Log.w(TAG, "Waiting for getRecordPath");
}
String path = (String) runInstance.getVal();
@@ -888,7 +875,7 @@
Log.w(TAG, "Waiting for getAudioCodecList");
}
StringVect swigmap = (StringVect) runInstance.getVal();
-
+
ArrayList<String> nativemap = new ArrayList<String>();
for (int i = 0; i < swigmap.size(); ++i) {