diff --git a/.gitmodules b/.gitmodules index dd5edd758..9019ecea7 100644 --- a/.gitmodules +++ b/.gitmodules @@ -50,6 +50,7 @@ [submodule "submodules/externals/antlr3"] path = submodules/externals/antlr3 url = git://git.linphone.org/antlr3.git + ignore = dirty [submodule "submodules/externals/libxml2"] path = submodules/externals/libxml2 url = git://git.gnome.org/libxml2.git @@ -86,6 +87,7 @@ [submodule "submodules/externals/mbedtls"] path = submodules/externals/mbedtls url = git://git.linphone.org/mbedtls.git + ignore = dirty [submodule "submodules/cmake-builder"] path = submodules/cmake-builder url = git://git.linphone.org/linphone-cmake-builder.git diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 34ec2f6ef..0a7549aca 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -169,6 +169,7 @@ + @@ -224,8 +225,8 @@ - + diff --git a/README b/README index 779491944..743d12b6b 100644 --- a/README +++ b/README @@ -9,7 +9,11 @@ To build liblinphone for Android, you must: ------------------------------------------- 0) download the Android sdk with platform-tools and tools updated to latest revision (at least API 16 is needed), then add both 'tools' and 'platform-tools' folders in your path. 1) download the Android ndk (=r10c) from google and add it to your path (no symlink !!!). -2) install yasm, nasm, ant, python, cmake +2) install yasm, nasm, ant, python, cmake, and gas-precessor.pl + gas-preprocessor.pl is a simple perl script that can be downloaded from + https://git.libav.org/?p=gas-preprocessor.git;a=blob_plain;f=gas-preprocessor.pl;hb=HEAD + After copying it into /usr/local/bin, don't forget to give it exec permission with chmod +x gas-preprocessor.pl + On 64 bits linux systems you'll need the ia32-libs package With the latest Debian (multiarch), you need this: dpkg --add-architecture i386 diff --git a/jni/Android.mk b/jni/Android.mk index 256939495..f44ba5cc0 100755 --- a/jni/Android.mk +++ b/jni/Android.mk @@ -15,7 +15,6 @@ endif ifeq ($(_BUILD_VIDEO),0) ifeq (,$(DUMP_VAR)) -$(info $(TARGET_ARCH_ABI): Video is disabled for targets other than armeabi-v7a and x86) endif endif @@ -86,7 +85,6 @@ endif ifeq ($(BUILD_SILK), 1) ifeq (,$(DUMP_VAR)) -$(info $(TARGET_ARCH_ABI): Build proprietary SILK plugin for mediastreamer2) endif include $(linphone-root-dir)/submodules/mssilk/Android.mk endif @@ -100,7 +98,6 @@ ifeq ($(_BUILD_VIDEO),1) ifeq ($(_BUILD_X264),1) ifeq (,$(DUMP_VAR)) -$(info $(TARGET_ARCH_ABI): Build X264 plugin for mediastreamer2) endif include $(linphone-root-dir)/submodules/msx264/Android.mk include $(linphone-root-dir)/submodules/externals/build/x264/Android.mk @@ -108,7 +105,6 @@ endif ifeq ($(_BUILD_OPENH264),1) ifeq (,$(DUMP_VAR)) -$(info $(TARGET_ARCH_ABI): Build OpenH264 plugin for mediastreamer2) endif include $(linphone-root-dir)/submodules/msopenh264/Android.mk include $(linphone-root-dir)/submodules/externals/build/openh264/Android.mk @@ -123,7 +119,6 @@ endif #_BUILD_VIDEO ifeq ($(BUILD_ZRTP), 1) ifeq (,$(DUMP_VAR)) -$(info $(TARGET_ARCH_ABI): Build ZRTP support) endif include $(linphone-root-dir)/submodules/bzrtp/Android.mk endif @@ -166,11 +161,9 @@ WEBRTC_BUILD_NEON_LIBS=false # AECM ifneq ($(BUILD_WEBRTC_AECM),0) ifeq ($(TARGET_ARCH_ABI), armeabi-v7a) -$(info $(TARGET_ARCH_ABI): Build NEON modules for AECM) WEBRTC_BUILD_NEON_LIBS=true endif -$(info $(TARGET_ARCH_ABI): Build AECM from WebRTC) include $(linphone-root-dir)/submodules/mswebrtc/build/android/system_wrappers/Android.mk include $(linphone-root-dir)/submodules/mswebrtc/build/android/modules/audio_processing/utility/Android.mk include $(linphone-root-dir)/submodules/mswebrtc/build/android/modules/audio_processing/aecm/Android.mk @@ -180,18 +173,15 @@ endif ifneq ($(BUILD_WEBRTC_ISAC),0) # don't build for neon in x86 ifeq ($(TARGET_ARCH_ABI), armeabi-v7a) -$(info $(TARGET_ARCH_ABI): Build NEON modules for ISAC) WEBRTC_BUILD_NEON_LIBS=true endif -$(info $(TARGET_ARCH_ABI): Build iSAC and ilbc plugin for mediastreamer2) include $(linphone-root-dir)/submodules/mswebrtc/build/android/modules/audio_coding/codecs/isac/fix/source/Android.mk include $(linphone-root-dir)/submodules/mswebrtc/build/android/modules/audio_coding/codecs/ilbc/Android.mk endif # common modules for ISAC and AECM ifneq ($(BUILD_WEBRTC_AECM)$(BUILD_WEBRTC_ISAC)$(BUILD_ILBC),000) -$(info $(TARGET_ARCH_ABI): Build common modules for iSAC, ilbc and AECM ($(BUILD_WEBRTC_AECM)$(BUILD_WEBRTC_ISAC))) include $(linphone-root-dir)/submodules/mswebrtc/build/android/common_audio/signal_processing/Android.mk include $(linphone-root-dir)/submodules/mswebrtc/Android.mk endif diff --git a/res/raw-sw600dp/linphonerc_default b/res/raw-sw600dp/linphonerc_default index e05864072..bb1ff0146 100644 --- a/res/raw-sw600dp/linphonerc_default +++ b/res/raw-sw600dp/linphonerc_default @@ -14,6 +14,7 @@ size=vga [app] tunnel=disabled push_notification=1 +debug=0 [tunnel] host= diff --git a/res/raw/linphonerc_default b/res/raw/linphonerc_default index 4b03491b1..61e812811 100644 --- a/res/raw/linphonerc_default +++ b/res/raw/linphonerc_default @@ -14,6 +14,8 @@ size=qvga [app] tunnel=disabled push_notification=1 +auto_start=1 +debug=0 [tunnel] host= diff --git a/res/raw/linphonerc_factory b/res/raw/linphonerc_factory index 7c468dac1..abafd63eb 100644 --- a/res/raw/linphonerc_factory +++ b/res/raw/linphonerc_factory @@ -9,7 +9,6 @@ mtu=1300 animations=0 show_login_view=1 debug_popup_magic=#1234 -debug=1 server_url=http://85.233.205.218:443/xmlrpc [sip] @@ -37,6 +36,5 @@ dtmf_player_amp=0.1 #remove this property for any application that is not Linphone public version itself ec_calibrator_cool_tones=1 - [misc] -max_calls=10 +max_calls=10 \ No newline at end of file diff --git a/res/values/non_localizable_custom.xml b/res/values/non_localizable_custom.xml index 9eefcb82f..f8851d0da 100644 --- a/res/values/non_localizable_custom.xml +++ b/res/values/non_localizable_custom.xml @@ -60,7 +60,7 @@ false false false - true + false false false linphone-android@belledonne-communications.com diff --git a/src/org/linphone/AboutFragment.java b/src/org/linphone/AboutFragment.java index a2501193a..77a5f516f 100644 --- a/src/org/linphone/AboutFragment.java +++ b/src/org/linphone/AboutFragment.java @@ -93,7 +93,7 @@ public class AboutFragment extends Fragment implements OnClickListener { lc.resetLogCollection(); } } else if (v == cancel) { - LinphoneActivity.instance().displayDialer(); + getFragmentManager().popBackStackImmediate(); } } } diff --git a/src/org/linphone/AccountPreferencesFragment.java b/src/org/linphone/AccountPreferencesFragment.java index 2a36f0156..84c0ca59a 100644 --- a/src/org/linphone/AccountPreferencesFragment.java +++ b/src/org/linphone/AccountPreferencesFragment.java @@ -23,6 +23,7 @@ import java.util.List; import org.linphone.LinphonePreferences.AccountBuilder; import org.linphone.core.LinphoneCoreException; +import org.linphone.mediastream.Log; import org.linphone.ui.PreferencesListFragment; import android.os.Bundle; @@ -455,7 +456,7 @@ public class AccountPreferencesFragment extends PreferencesListFragment { builder.saveNewAccount(); } } catch (LinphoneCoreException e) { - e.printStackTrace(); + Log.e(e); } LinphoneActivity.instance().isNewProxyConfig(); LinphoneManager.getLc().refreshRegisters(); diff --git a/src/org/linphone/BluetoothManager.java b/src/org/linphone/BluetoothManager.java index d4ad16cfe..0b183f6bb 100644 --- a/src/org/linphone/BluetoothManager.java +++ b/src/org/linphone/BluetoothManager.java @@ -269,7 +269,7 @@ public class BluetoothManager extends BroadcastReceiver { Log.d("Bluetooth receiver stopped"); } catch (Exception e) {} } catch (Exception e) { - e.printStackTrace(); + Log.e(e); } } diff --git a/src/org/linphone/BootReceiver.java b/src/org/linphone/BootReceiver.java index aa2b1082c..f19591445 100644 --- a/src/org/linphone/BootReceiver.java +++ b/src/org/linphone/BootReceiver.java @@ -18,8 +18,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package org.linphone; +import org.linphone.core.LinphoneCore; import org.linphone.core.LinphoneCoreFactory; import org.linphone.core.LpConfig; +import org.linphone.mediastream.Log; import android.content.BroadcastReceiver; import android.content.Context; @@ -29,13 +31,20 @@ public class BootReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { - - String path = context.getFilesDir().getAbsolutePath() + "/.linphonerc"; - LpConfig lpConfig = LinphoneCoreFactory.instance().createLpConfig(path); - if (lpConfig.getBool("app", "auto_start", false)) { - Intent lLinphoneServiceIntent = new Intent(Intent.ACTION_MAIN); - lLinphoneServiceIntent.setClass(context, LinphoneService.class); - context.startService(lLinphoneServiceIntent); + if (intent.getAction().equalsIgnoreCase(Intent.ACTION_SHUTDOWN)) { + LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull(); + if (lc != null) { + Log.w("Device is shutting down, destroying LinphoneCore to unregister"); + lc.destroy(); + } + } else { + String path = context.getFilesDir().getAbsolutePath() + "/.linphonerc"; + LpConfig lpConfig = LinphoneCoreFactory.instance().createLpConfig(path); + if (lpConfig.getBool("app", "auto_start", false)) { + Intent lLinphoneServiceIntent = new Intent(Intent.ACTION_MAIN); + lLinphoneServiceIntent.setClass(context, LinphoneService.class); + context.startService(lLinphoneServiceIntent); + } } } } diff --git a/src/org/linphone/CallActivity.java b/src/org/linphone/CallActivity.java index a1f159d69..94ff385f0 100644 --- a/src/org/linphone/CallActivity.java +++ b/src/org/linphone/CallActivity.java @@ -733,7 +733,7 @@ public class CallActivity extends Activity implements OnClickListener, SensorEve } if (isVideoEnabled) { - LinphoneCallParams params = call.getCurrentParamsCopy(); + LinphoneCallParams params = LinphoneManager.getLc().createCallParams(call); params.setVideoEnabled(false); LinphoneManager.getLc().updateCall(call, params); } else { @@ -1331,7 +1331,7 @@ public class CallActivity extends Activity implements OnClickListener, SensorEve return; } - LinphoneCallParams params = call.getCurrentParamsCopy(); + LinphoneCallParams params = LinphoneManager.getLc().createCallParams(call); if (accept) { params.setVideoEnabled(true); LinphoneManager.getLc().enableVideo(true, true); @@ -1340,7 +1340,7 @@ public class CallActivity extends Activity implements OnClickListener, SensorEve try { LinphoneManager.getLc().acceptCallUpdate(call, params); } catch (LinphoneCoreException e) { - e.printStackTrace(); + Log.e(e); } } diff --git a/src/org/linphone/ChatFragment.java b/src/org/linphone/ChatFragment.java index 3ae6e60f1..d1ced9283 100644 --- a/src/org/linphone/ChatFragment.java +++ b/src/org/linphone/ChatFragment.java @@ -22,6 +22,7 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Locale; @@ -86,8 +87,6 @@ import android.widget.Toast; public class ChatFragment extends Fragment implements OnClickListener, LinphoneChatMessage.LinphoneChatMessageListener { - private static ChatFragment instance; - private static final int ADD_PHOTO = 1337; private static final int MENU_DELETE_MESSAGE = 0; private static final int MENU_PICTURE_SMALL = 2; @@ -125,14 +124,9 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC private ByteArrayInputStream mUploadingImageStream; private boolean newChatConversation = false; - public static boolean isInstanciated() { - return instance != null; - } - @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { super.onCreate(savedInstanceState); - instance = this; final View view = inflater.inflate(R.layout.chat, container, false); LinphoneManager.addListener(this); @@ -151,6 +145,7 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC //Initialize UI contactName = (TextView) view.findViewById(R.id.contact_name); messagesList = (ListView) view.findViewById(R.id.chat_message_list); + messagesList.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE); searchContactField = (EditText) view.findViewById(R.id.search_contact_field); resultContactsSearch = (ListView) view.findViewById(R.id.result_contacts); @@ -216,8 +211,16 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC public void messageReceived(LinphoneCore lc, LinphoneChatRoom cr, LinphoneChatMessage message) { LinphoneAddress from = cr.getPeerAddress(); if (from.asStringUriOnly().equals(sipUri)) { + LinphoneService.instance().removeMessageNotification(); + cr.markAsRead(); invalidate(); messagesList.setSelection(adapter.getCount()-1); + + String externalBodyUrl = message.getExternalBodyUrl(); + LinphoneContent fileTransferContent = message.getFileTransferInformation(); + if (externalBodyUrl != null || fileTransferContent != null) { + LinphoneActivity.instance().checkAndRequestExternalStoragePermission(); + } } } @@ -248,14 +251,6 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC return view; } - public static ChatFragment instance() { - return instance; - } - - public String getSipUri() { - return sipUri; - } - @Override public void onSaveInstanceState(Bundle outState) { if (message != null) { @@ -326,66 +321,67 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC } class ChatMessageAdapter extends BaseAdapter { - LinphoneChatMessage[] history; + ArrayList history; Context context; - public ChatMessageAdapter(Context context, LinphoneChatMessage[] history) { - this.history = history; - this.context = context; + public ChatMessageAdapter(Context c) { + context = c; + history = new ArrayList(); + refreshHistory(); } public void destroy() { - this.history = null; + if (history != null) { + history.clear(); + } } public void refreshHistory() { - this.history = null; - this.history = chatRoom.getHistory(); + history.clear(); + LinphoneChatMessage[] messages = chatRoom.getHistory(); + history.addAll(Arrays.asList(messages)); + notifyDataSetChanged(); } public void addMessage(LinphoneChatMessage message) { - LinphoneChatMessage[] newHist = new LinphoneChatMessage[getCount() +1]; - for(int i=0; i< getCount(); i++){ - newHist[i] = this.history[i]; - } - newHist[getCount()] = message; - this.history = newHist; - } - - public void removeMessage(LinphoneChatMessage message) { - LinphoneChatMessage[] newHist = new LinphoneChatMessage[getCount() -1]; - for(int i=0; i< getCount(); i++){ - if(this.history[i].getStorageId() != newHist[i].getStorageId()) - newHist[i] = this.history[i]; - } - newHist[getCount()] = message; - this.history = newHist; + history.add(message); + notifyDataSetChanged(); } @Override public int getCount() { - return history.length; + return history.size(); } @Override public LinphoneChatMessage getItem(int position) { - return history[position]; + return history.get(position); } @Override public long getItemId(int position) { - return history[position].getStorageId(); + return history.get(position).getStorageId(); } @Override public View getView(final int position, View convertView, ViewGroup parent) { - LinphoneChatMessage message = history[position]; + LinphoneChatMessage message = history.get(position); + RelativeLayout rlayout; + if (convertView != null) { + rlayout = (RelativeLayout) convertView; + View bbv = rlayout.getChildAt(0); + rlayout.removeAllViews(); + BubbleChat bbc = (BubbleChat) bbv.getTag(); + bbc.destroy(); + } else { + rlayout = new RelativeLayout(context); + } BubbleChat bubble = new BubbleChat(context, message, contact); View v = bubble.getView(); + v.setTag(bubble); registerForContextMenu(v); - RelativeLayout rlayout = new RelativeLayout(context); CheckBox deleteChatBubble = (CheckBox) v.findViewById(R.id.delete_message); @@ -476,12 +472,14 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC } public void dispayMessageList() { - messagesList.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE); if(chatRoom != null) { - if (adapter != null) adapter.destroy(); - adapter = new ChatMessageAdapter(getActivity(), chatRoom.getHistory()); - messagesList.setAdapter(adapter); + if (adapter != null) { + adapter.refreshHistory(); + } else { + adapter = new ChatMessageAdapter(getActivity().getApplicationContext()); + } } + messagesList.setAdapter(adapter); } private void displayChatHeader(LinphoneAddress address) { @@ -557,10 +555,6 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC LinphoneService.instance().removeMessageNotification(); - if (LinphoneActivity.isInstanciated()) { - LinphoneActivity.instance().updateChatFragment(null); - } - LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull(); if (lc != null) { lc.removeListener(mListener); @@ -572,12 +566,23 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC //Hide keybord InputMethodManager imm = (InputMethodManager)getActivity().getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(message.getWindowToken(), 0); + super.onPause(); } + + @Override + public void onDestroy() { + if (adapter != null) { + adapter.destroy(); + } + super.onDestroy(); + } @SuppressLint("UseSparseArrays") @Override public void onResume() { + super.onResume(); + message.addTextChangedListener(textWatcher); addVirtualKeyboardVisiblityListener(); @@ -588,7 +593,6 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC if (LinphoneActivity.isInstanciated()) { LinphoneActivity.instance().selectMenu(FragmentsAvailable.CHAT); - LinphoneActivity.instance().updateChatFragment(this); } if(LinphoneManager.getLc().isIncall()){ @@ -615,7 +619,6 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC resultContactsSearch.setVisibility(View.GONE); remoteComposing.setVisibility(chatRoom.isRemoteComposing() ? View.VISIBLE : View.GONE); } - super.onResume(); } private void selectAllList(boolean isSelectAll){ @@ -746,7 +749,7 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC if (newChatConversation) { exitNewConversationMode(lAddress.asStringUriOnly()); } else { - invalidate(); + displayBubbleChat(message); } Log.i("Sent message current status: " + message.getStatus()); @@ -797,7 +800,6 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC private void invalidate() { adapter.refreshHistory(); - adapter.notifyDataSetChanged(); chatRoom.markAsRead(); } @@ -895,7 +897,7 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC bm = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true); } } catch (Exception e) { - e.printStackTrace(); + Log.e(e); } ByteArrayOutputStream stream = new ByteArrayOutputStream(); diff --git a/src/org/linphone/ChatListFragment.java b/src/org/linphone/ChatListFragment.java index 94cab9717..c914087e8 100644 --- a/src/org/linphone/ChatListFragment.java +++ b/src/org/linphone/ChatListFragment.java @@ -22,23 +22,18 @@ import java.util.List; import org.linphone.core.LinphoneAddress; import org.linphone.core.LinphoneChatMessage; import org.linphone.core.LinphoneChatRoom; +import org.linphone.core.LinphoneCore; import org.linphone.core.LinphoneCoreException; import org.linphone.core.LinphoneCoreFactory; +import org.linphone.core.LinphoneCoreListenerBase; import org.linphone.core.LinphoneFriend; import org.linphone.mediastream.Log; import org.linphone.ui.AvatarWithPresenceImage; import android.app.Dialog; -import android.app.ProgressDialog; -import android.content.Context; -import android.content.SharedPreferences; -import android.content.pm.PackageManager.NameNotFoundException; -import android.graphics.Bitmap; +import android.app.Fragment; import android.graphics.Typeface; import android.os.Bundle; -import android.os.Environment; -import android.preference.PreferenceManager; -import android.app.Fragment; import android.view.ContextMenu; import android.view.ContextMenu.ContextMenuInfo; import android.view.LayoutInflater; @@ -70,6 +65,7 @@ public class ChatListFragment extends Fragment implements OnClickListener, OnIte private ImageView edit, selectAll, deselectAll, delete, newDiscussion, cancel, backInCall; private LinearLayout editList, topbar; private boolean isEditMode = false; + private LinphoneCoreListenerBase mListener; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, @@ -106,6 +102,13 @@ public class ChatListFragment extends Fragment implements OnClickListener, OnIte delete = (ImageView) view.findViewById(R.id.delete); delete.setOnClickListener(this); + + mListener = new LinphoneCoreListenerBase() { + @Override + public void messageReceived(LinphoneCore lc, LinphoneChatRoom cr, LinphoneChatMessage message) { + refresh(); + } + }; return view; } @@ -203,12 +206,25 @@ public class ChatListFragment extends Fragment implements OnClickListener, OnIte if (LinphoneActivity.isInstanciated()) { LinphoneActivity.instance().selectMenu(FragmentsAvailable.CHAT_LIST); - LinphoneActivity.instance().updateChatListFragment(this); LinphoneActivity.instance().hideTabBar(false); } + LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull(); + if (lc != null) { + lc.addListener(mListener); + } + refresh(); } + + @Override + public void onPause() { + LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull(); + if (lc != null) { + lc.removeListener(mListener); + } + super.onPause(); + } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { @@ -359,7 +375,7 @@ public class ChatListFragment extends Fragment implements OnClickListener, OnIte return view; } - LinphoneContact contact = ContactsManager.getInstance().findContactFromAddress(address); //findContactWithAddress(getActivity().getContentResolver(), address); + LinphoneContact contact = ContactsManager.getInstance().findContactFromAddress(address); String message = ""; Long time; @@ -387,13 +403,13 @@ public class ChatListFragment extends Fragment implements OnClickListener, OnIte if(msg.getFileTransferInformation() != null || msg.getExternalBodyUrl() != null || msg.getAppData() != null ){ lastMessageView.setBackgroundResource(R.drawable.chat_file_message); time = msg.getTime(); - date.setText(LinphoneUtils.timestampToHumanDate(getActivity(),time,getString(R.string.messages_list_date_format),true)); + date.setText(LinphoneUtils.timestampToHumanDate(getActivity(),time,getString(R.string.messages_list_date_format), true)); lastMessageView.setText(""); } else if (msg.getText() != null && msg.getText().length() > 0 ){ message = msg.getText(); lastMessageView.setBackgroundResource(0); time = msg.getTime(); - date.setText(LinphoneUtils.timestampToHumanDate(getActivity(),time,getString(R.string.messages_list_date_format),true)); + date.setText(LinphoneUtils.timestampToHumanDate(getActivity(),time,getString(R.string.messages_list_date_format), true)); lastMessageView.setText(message); } @@ -401,8 +417,10 @@ public class ChatListFragment extends Fragment implements OnClickListener, OnIte displayName.setText(contact == null ? LinphoneUtils.getAddressDisplayName(address) : contact.getFullName()); - /*if(contact != null){ + /*if (contact != null) { LinphoneUtils.setImagePictureFromUri(view.getContext(), contactPicture, contact.getPhotoUri(), contact.getThumbnailUri()); + } else { + contactPicture.setImageResource(R.drawable.avatar); }*/ if (unreadMessagesCount > 0) { diff --git a/src/org/linphone/ChatStorage.java b/src/org/linphone/ChatStorage.java index c7a5a36bc..370f366cc 100644 --- a/src/org/linphone/ChatStorage.java +++ b/src/org/linphone/ChatStorage.java @@ -71,7 +71,7 @@ public class ChatStorage { try { return context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionCode >= 2200; } catch (NameNotFoundException e) { - e.printStackTrace(); + Log.e(e); } return true; } @@ -110,7 +110,7 @@ public class ChatStorage { try { id = c.getString(c.getColumnIndex("id")); } catch (Exception e) { - e.printStackTrace(); + Log.e(e); } } c.close(); @@ -250,7 +250,7 @@ public class ChatStorage { try { message = c.getString(c.getColumnIndex("message")); } catch (Exception e) { - e.printStackTrace(); + Log.e(e); } } c.close(); @@ -271,7 +271,7 @@ public class ChatStorage { String to = c.getString(c.getColumnIndex("remoteContact")); drafts.add(to); } catch (Exception e) { - e.printStackTrace(); + Log.e(e); } } c.close(); @@ -280,64 +280,14 @@ public class ChatStorage { return drafts; } - public List getMessages(String correspondent) { - List chatMessages = new ArrayList(); - - if (!useNativeAPI) { - Cursor c = db.query(TABLE_NAME, null, "remoteContact LIKE \"" + correspondent + "\"", null, null, null, "id ASC"); - - while (c.moveToNext()) { - try { - String message, timestamp, url; - int id = c.getInt(c.getColumnIndex("id")); - int direction = c.getInt(c.getColumnIndex("direction")); - message = c.getString(c.getColumnIndex("message")); - timestamp = c.getString(c.getColumnIndex("time")); - int status = c.getInt(c.getColumnIndex("status")); - byte[] rawImage = c.getBlob(c.getColumnIndex("image")); - int read = c.getInt(c.getColumnIndex("read")); - url = c.getString(c.getColumnIndex("url")); - - ChatMessage chatMessage = new ChatMessage(id, message, rawImage, timestamp, direction == INCOMING, status, read == READ); - chatMessage.setUrl(url); - chatMessages.add(chatMessage); - } catch (Exception e) { - e.printStackTrace(); - } - } - c.close(); - } else { - LinphoneChatRoom room = LinphoneManager.getLc().getOrCreateChatRoom(correspondent); - LinphoneChatMessage[] history = room.getHistory(); - for (int i = 0; i < history.length; i++) { - LinphoneChatMessage message = history[i]; - - Bitmap bm = null; - String url = message.getExternalBodyUrl(); - if (url != null && !url.startsWith("http")) { - bm = BitmapFactory.decodeFile(url); - } - ChatMessage chatMessage = new ChatMessage(i+1, message.getText(), bm, - String.valueOf(message.getTime()), !message.isOutgoing(), - message.getStatus().toInt(), message.isRead()); - chatMessage.setUrl(url); - chatMessages.add(chatMessage); - } - } - - return chatMessages; - } - public String getTextMessageForId(LinphoneChatRoom chatroom, int id) { String message = null; if (useNativeAPI) { - LinphoneChatMessage[] history = chatroom.getHistory(); - for (LinphoneChatMessage msg : history) { - if (msg.getStorageId() == id) { - message = msg.getText(); - break; - } + LinphoneChatMessage msg = getMessage(chatroom, id); + + if (msg != null) { + message = msg.getText(); } } else { Cursor c = db.query(TABLE_NAME, null, "id LIKE " + id, null, null, null, null); @@ -346,7 +296,7 @@ public class ChatStorage { try { message = c.getString(c.getColumnIndex("message")); } catch (Exception e) { - e.printStackTrace(); + Log.e(e); } } c.close(); @@ -410,12 +360,9 @@ public class ChatStorage { public void deleteMessage(LinphoneChatRoom chatroom, int id) { if (useNativeAPI) { - LinphoneChatMessage[] history = chatroom.getHistory(); - for (LinphoneChatMessage message : history) { - if (message.getStorageId() == id) { - chatroom.deleteMessage(message); - break; - } + LinphoneChatMessage msg = getMessage(chatroom, id); + if (msg != null){ + chatroom.deleteMessage(msg); } } else { db.delete(TABLE_NAME, "id LIKE " + id, null); diff --git a/src/org/linphone/ContactDetailsFragment.java b/src/org/linphone/ContactDetailsFragment.java index 6c3e7d8bf..6d51e6ea1 100644 --- a/src/org/linphone/ContactDetailsFragment.java +++ b/src/org/linphone/ContactDetailsFragment.java @@ -87,11 +87,11 @@ public class ContactDetailsFragment extends Fragment implements OnClickListener displayChatAddressOnly = getArguments().getBoolean("ChatAddressOnly"); } -// editContact = (ImageView) view.findViewById(R.id.editContact); -// editContact.setOnClickListener(this); + //editContact = (ImageView) view.findViewById(R.id.editContact); + //editContact.setOnClickListener(this); -// deleteContact = (ImageView) view.findViewById(R.id.deleteContact); -// deleteContact.setOnClickListener(this); + //deleteContact = (ImageView) view.findViewById(R.id.deleteContact); + //deleteContact.setOnClickListener(this); back = (ImageView) view.findViewById(R.id.back); if(getResources().getBoolean(R.bool.isTablet)){ @@ -138,15 +138,15 @@ public class ContactDetailsFragment extends Fragment implements OnClickListener displayednumberOrAddress = displayednumberOrAddress.replace("sip:", ""); } - /* TextView label = (TextView) v.findViewById(R.id.address_label); + /*TextView label = (TextView) v.findViewById(R.id.address_label); if (noa.isSIPAddress()) { label.setText(R.string.sip_address); skip |= getResources().getBoolean(R.bool.hide_contact_sip_addresses); } else { label.setText(R.string.phone_number); skip |= getResources().getBoolean(R.bool.hide_contact_phone_numbers); - } - */ + }*/ + TextView tv = (TextView) v.findViewById(R.id.numeroOrAddress); tv.setText(displayednumberOrAddress); tv.setSelected(true); @@ -234,7 +234,7 @@ public class ContactDetailsFragment extends Fragment implements OnClickListener public void onClick(View v) { int id = v.getId(); - /* if (id == R.id.editContact) { + /*if (id == R.id.editContact) { LinphoneActivity.instance().editContact(contact); } if (id == R.id.deleteContact) { @@ -259,10 +259,9 @@ public class ContactDetailsFragment extends Fragment implements OnClickListener } }); dialog.show(); + }*/ + if (id == R.id.back) { + getFragmentManager().popBackStackImmediate(); } - */ if (id == R.id.back) { - LinphoneActivity.instance().displayContacts(false); - } - } } diff --git a/src/org/linphone/ContactEditorFragment.java b/src/org/linphone/ContactEditorFragment.java index 5d54edeb7..4ebda09bb 100644 --- a/src/org/linphone/ContactEditorFragment.java +++ b/src/org/linphone/ContactEditorFragment.java @@ -25,6 +25,7 @@ import java.io.Serializable; import java.util.ArrayList; import java.util.List; +import org.linphone.mediastream.Log; import org.linphone.mediastream.Version; import android.annotation.SuppressLint; @@ -143,14 +144,6 @@ public class ContactEditorFragment extends Fragment { contact.addOrUpdateNumberOrAddress(numberOrAddress); } contact.save(); - - if (!isNewContact) { - if (LinphoneActivity.instance().getResources().getBoolean(R.bool.isTablet)) { - if(ContactsListFragment.isInstanciated()) { - ContactsListFragment.instance().invalidate(); - } - } - } getFragmentManager().popBackStackImmediate(); } }); @@ -354,7 +347,7 @@ public class ContactEditorFragment extends Fragment { Bitmap selectedImage = MediaStore.Images.Media.getBitmap(LinphoneManager.getInstance().getContext().getContentResolver(), selectedImageUri); selectedImage = Bitmap.createScaledBitmap(selectedImage, PHOTO_SIZE, PHOTO_SIZE, false); editContactPicture(null, selectedImage); - } catch (IOException e) { e.printStackTrace(); } + } catch (IOException e) { Log.e(e); } } else if (pickedPhotoForContactUri != null) { String filePath = pickedPhotoForContactUri.getPath(); diff --git a/src/org/linphone/ContactsListFragment.java b/src/org/linphone/ContactsListFragment.java index 4c4b82fa2..be50698cb 100644 --- a/src/org/linphone/ContactsListFragment.java +++ b/src/org/linphone/ContactsListFragment.java @@ -25,13 +25,6 @@ import java.util.List; import java.util.Locale; import java.util.Map; -import org.linphone.core.LinphoneCore; -import org.linphone.core.LinphoneFriend; -import org.linphone.core.OnlineStatus; -import org.linphone.core.PresenceActivityType; -import org.linphone.core.PresenceBasicStatus; -import org.linphone.core.PresenceModel; -import org.linphone.mediastream.Log; import org.linphone.ui.AvatarWithPresenceImage; import android.app.Dialog; @@ -49,7 +42,6 @@ import android.widget.AdapterView.OnItemClickListener; import android.widget.BaseAdapter; import android.widget.Button; import android.widget.CheckBox; -import android.widget.CompoundButton; import android.widget.EditText; import android.widget.ImageView; import android.widget.LinearLayout; @@ -74,16 +66,6 @@ public class ContactsListFragment extends Fragment implements OnClickListener, O private ImageView clearSearchField; private EditText searchField; - private static ContactsListFragment instance; - - static final boolean isInstanciated() { - return instance != null; - } - - public static final ContactsListFragment instance() { - return instance; - } - @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { mInflater = inflater; @@ -98,13 +80,44 @@ public class ContactsListFragment extends Fragment implements OnClickListener, O noSipContact = (TextView) view.findViewById(R.id.noSipContact); noContact = (TextView) view.findViewById(R.id.noContact); - + contactsList = (ListView) view.findViewById(R.id.contactsList); contactsList.setOnItemClickListener(this); + /*allContacts = (ImageView) view.findViewById(R.id.all_contacts); + allContacts.setOnClickListener(this); + + linphoneContacts = (ImageView) view.findViewById(R.id.linphone_contacts); + linphoneContacts.setOnClickListener(this); + + allContactsSelected = view.findViewById(R.id.all_contacts_select); + linphoneContactsSelected = view.findViewById(R.id.linphone_contacts_select); + + newContact = (ImageView) view.findViewById(R.id.newContact); + newContact.setOnClickListener(this); + newContact.setEnabled(LinphoneManager.getLc().getCallsNb() == 0);*/ + + /*allContacts.setEnabled(onlyDisplayLinphoneContacts); + linphoneContacts.setEnabled(!allContacts.isEnabled());*/ + + /*selectAll = (ImageView) view.findViewById(R.id.select_all); + selectAll.setOnClickListener(this); + + deselectAll = (ImageView) view.findViewById(R.id.deselect_all); + deselectAll.setOnClickListener(this); + + delete = (ImageView) view.findViewById(R.id.delete); + delete.setOnClickListener(this);*/ + editList = (LinearLayout) view.findViewById(R.id.edit_list); topbar = (LinearLayout) view.findViewById(R.id.top_bar); + /*cancel = (ImageView) view.findViewById(R.id.cancel); + cancel.setOnClickListener(this); + + edit = (ImageView) view.findViewById(R.id.edit); + edit.setOnClickListener(this);*/ + clearSearchField = (ImageView) view.findViewById(R.id.clearSearchField); clearSearchField.setOnClickListener(this); @@ -206,6 +219,22 @@ public class ContactsListFragment extends Fragment implements OnClickListener, O enabledDeleteButton(false); isEditMode = true; } + + /*if (id == R.id.all_contacts) { + onlyDisplayLinphoneContacts = false; + allContactsSelected.setVisibility(View.VISIBLE); + allContacts.setEnabled(false); + linphoneContacts.setEnabled(true); + linphoneContactsSelected.setVisibility(View.INVISIBLE); + } + else if (id == R.id.linphone_contacts) { + allContactsSelected.setVisibility(View.INVISIBLE); + linphoneContactsSelected.setVisibility(View.VISIBLE); + linphoneContacts.setEnabled(false); + allContacts.setEnabled(true); + onlyDisplayLinphoneContacts = true; + + }*/ if(isEditMode){ deselectAll.setVisibility(View.GONE); @@ -218,10 +247,14 @@ public class ContactsListFragment extends Fragment implements OnClickListener, O changeContactsAdapter(); } - if (id == R.id.clearSearchField) { + /*if (id == R.id.newContact) { + editConsumed = true; + LinphoneActivity.instance().addContact(null, sipAddressToAdd); + } + else */if (id == R.id.clearSearchField) { searchField.setText(""); } - } + } private void selectAllList(boolean isSelectAll){ int size = contactsList.getAdapter().getCount(); @@ -277,7 +310,8 @@ public class ContactsListFragment extends Fragment implements OnClickListener, O return; } changeContactsToggle(); - if (onlyDisplayLinphoneContacts) { + + if (onlyDisplayLinphoneContacts) { contactsList.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE); contactsList.setAdapter(new ContactsListAdapter(ContactsManager.getInstance().getSIPContacts(search))); } else { @@ -296,17 +330,17 @@ public class ContactsListFragment extends Fragment implements OnClickListener, O if (onlyDisplayLinphoneContacts) { contactsList.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE); contactsList.setAdapter(new ContactsListAdapter(ContactsManager.getInstance().getSIPContacts())); -// edit.setEnabled(true); + //edit.setEnabled(true); } else { contactsList.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE); contactsList.setAdapter(new ContactsListAdapter(ContactsManager.getInstance().getContacts())); -// edit.setEnabled(true); + //edit.setEnabled(true); } ContactsManager.getInstance().setLinphoneContactsPrefered(onlyDisplayLinphoneContacts); } private void changeContactsToggle() { - /* if (onlyDisplayLinphoneContacts) { + /*if (onlyDisplayLinphoneContacts) { allContacts.setEnabled(true); allContactsSelected.setVisibility(View.INVISIBLE); linphoneContacts.setEnabled(false); @@ -316,9 +350,8 @@ public class ContactsListFragment extends Fragment implements OnClickListener, O allContactsSelected.setVisibility(View.VISIBLE); linphoneContacts.setEnabled(true); linphoneContactsSelected.setVisibility(View.INVISIBLE); - } -*/ - } + }*/ + } @Override public void onItemClick(AdapterView adapter, View view, int position, long id) { @@ -334,7 +367,6 @@ public class ContactsListFragment extends Fragment implements OnClickListener, O @Override public void onResume() { - instance = this; ContactsManager.addContactsListener(this); super.onResume(); @@ -354,9 +386,7 @@ public class ContactsListFragment extends Fragment implements OnClickListener, O @Override public void onPause() { - instance = null; ContactsManager.removeContactsListener(this); - //LinphoneManager.getInstance().removePresenceUpdatedListener(); super.onPause(); } @@ -387,7 +417,11 @@ public class ContactsListFragment extends Fragment implements OnClickListener, O String prevLetter = null; for (int i = 0; i < contacts.size(); i++) { LinphoneContact contact = contacts.get(i); - String firstLetter = contact.getFullName().substring(0, 1).toUpperCase(Locale.getDefault()); + String fullName = contact.getFullName(); + if (fullName == null || fullName.isEmpty()) { + continue; + } + String firstLetter = fullName.substring(0, 1).toUpperCase(Locale.getDefault()); if (!firstLetter.equals(prevLetter)) { prevLetter = firstLetter; map.put(firstLetter, i); @@ -412,37 +446,102 @@ public class ContactsListFragment extends Fragment implements OnClickListener, O } public View getView(final int position, View convertView, ViewGroup parent) { - View view = null; - LinphoneContact contact = (LinphoneContact) getItem(position); - if (contact == null) return null; - contact.refresh(); + View view = null; + LinphoneContact contact = (LinphoneContact) getItem(position); + if (contact == null) return null; + + if (convertView != null) { + view = convertView; + } else { + view = mInflater.inflate(R.layout.contact_cell, parent, false); + } - if (convertView != null) { - view = convertView; - } else { - view = mInflater.inflate(R.layout.contact_cell, parent, false); - } + //CheckBox delete = (CheckBox) view.findViewById(R.id.delete); + + TextView name = (TextView) view.findViewById(R.id.name); + name.setText(contact.getFullName()); - //CheckBox delete = (CheckBox) view.findViewById(R.id.delete); - TextView name = (TextView) view.findViewById(R.id.name); - name.setText(contact.getFullName()); + TextView separator = (TextView) view.findViewById(R.id.separator); + //TextView separatorText = (TextView) view.findViewById(R.id.separator_text); + if (getPositionForSection(getSectionForPosition(position)) != position) { + separator.setVisibility(View.GONE); + } else { + separator.setVisibility(View.VISIBLE); + /*String fullName = contact.getFullName(); + if (fullName != null && !fullName.isEmpty()) { + separatorText.setText(String.valueOf(fullName.charAt(0))); + }*/ + } - TextView separatorText = (TextView) view.findViewById(R.id.separator); - if (getPositionForSection(getSectionForPosition(position)) != position) { - separatorText.setVisibility(View.GONE); - } else { - separatorText.setVisibility(View.VISIBLE); - } + AvatarWithPresenceImage avatarWithPresenceImage = (AvatarWithPresenceImage) view.findViewById(R.id.avatar_with_presence); + if(contact != null && contact.isLinphoneFriend()) { + avatarWithPresenceImage.setLinphoneContact(contact); + LinphoneManager.getInstance().addPresenceUpdatedListener(avatarWithPresenceImage); + } + + /*ImageView icon = (ImageView) view.findViewById(R.id.contact_picture); + if (contact.hasPhoto()) { + LinphoneUtils.setImagePictureFromUri(getActivity(), icon, contact.getPhotoUri(), contact.getThumbnailUri()); + } else if (contact.getPhotoUri() != null) { + icon.setImageURI(contact.getPhotoUri()); + } else { + icon.setImageResource(R.drawable.avatar); + }*/ - AvatarWithPresenceImage avatarWithPresenceImage = (AvatarWithPresenceImage) view.findViewById(R.id.avatar_with_presence); - if(contact != null && contact.isLinphoneFriend()) { - avatarWithPresenceImage.setLinphoneContact(contact); - LinphoneManager.getInstance().addPresenceUpdatedListener(avatarWithPresenceImage); - } + /*if (isEditMode) { + delete.setVisibility(View.VISIBLE); + delete.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton compoundButton, boolean b) { + contactsList.setItemChecked(position, b); + if(getNbItemsChecked() == getCount()){ + deselectAll.setVisibility(View.VISIBLE); + selectAll.setVisibility(View.GONE); + enabledDeleteButton(true); + } else { + if(getNbItemsChecked() == 0){ + deselectAll.setVisibility(View.GONE); + selectAll.setVisibility(View.VISIBLE); + enabledDeleteButton(false); + } else { + deselectAll.setVisibility(View.GONE); + selectAll.setVisibility(View.VISIBLE); + enabledDeleteButton(true); + } + } + } + }); + if (contactsList.isItemChecked(position)) { + delete.setChecked(true); + } else { + delete.setChecked(false); + } + } else { + delete.setVisibility(View.GONE); + } + + ImageView friendStatus = (ImageView) view.findViewById(R.id.friendStatus); + LinphoneFriend[] friends = LinphoneManager.getLc().getFriendList(); + if (!ContactsManager.getInstance().isContactPresenceDisabled() && friends != null) { + friendStatus.setVisibility(View.VISIBLE); + PresenceActivityType presenceActivity = friends[0].getPresenceModel().getActivity().getType(); + if (presenceActivity == PresenceActivityType.Online) { + friendStatus.setImageResource(R.drawable.led_connected); + } else if (presenceActivity == PresenceActivityType.Busy) { + friendStatus.setImageResource(R.drawable.led_error); + } else if (presenceActivity == PresenceActivityType.Away) { + friendStatus.setImageResource(R.drawable.led_inprogress); + } else if (presenceActivity == PresenceActivityType.Offline) { + friendStatus.setImageResource(R.drawable.led_disconnected); + } else { + friendStatus.setImageResource(R.drawable.call_quality_indicator_0); + } + }*/ + return view; } - @Override + @Override public Object[] getSections() { return sections; } @@ -461,7 +560,11 @@ public class ContactsListFragment extends Fragment implements OnClickListener, O return 0; } LinphoneContact contact = contacts.get(position); - String letter = contact.getFullName().substring(0, 1); + String fullName = contact.getFullName(); + if (fullName == null || fullName.isEmpty()) { + return 0; + } + String letter = fullName.substring(0, 1); return sectionsList.indexOf(letter); } } diff --git a/src/org/linphone/DialerFragment.java b/src/org/linphone/DialerFragment.java index a25c36e8a..121f732a7 100644 --- a/src/org/linphone/DialerFragment.java +++ b/src/org/linphone/DialerFragment.java @@ -53,7 +53,6 @@ public class DialerFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - instance = this; View view = inflater.inflate(R.layout.dialer, container, false); mAddress = (AddressText) view.findViewById(R.id.address); @@ -142,9 +141,16 @@ public class DialerFragment extends Fragment { return isCallTransferOngoing; } + @Override + public void onPause() { + instance = null; + super.onPause(); + } + @Override public void onResume() { super.onResume(); + instance = this; if (LinphoneActivity.isInstanciated()) { LinphoneActivity.instance().selectMenu(FragmentsAvailable.DIALER); diff --git a/src/org/linphone/HistoryDetailFragment.java b/src/org/linphone/HistoryDetailFragment.java index 5b833d91e..78a72c64e 100644 --- a/src/org/linphone/HistoryDetailFragment.java +++ b/src/org/linphone/HistoryDetailFragment.java @@ -17,18 +17,15 @@ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -import java.text.SimpleDateFormat; -import java.util.Calendar; - import org.linphone.core.LinphoneAddress; import org.linphone.core.LinphoneCoreException; import org.linphone.core.LinphoneCoreFactory; +import org.linphone.mediastream.Log; import org.linphone.ui.AvatarWithPresenceImage; -import android.annotation.SuppressLint; +import android.app.Fragment; import android.net.Uri; import android.os.Bundle; -import android.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; @@ -74,9 +71,9 @@ public class HistoryDetailFragment extends Fragment implements OnClickListener { if (getResources().getBoolean(R.bool.disable_chat)) view.findViewById(R.id.chat).setVisibility(View.GONE); - // addToContacts = (ImageView) view.findViewById(R.id.add_contact); - // addToContacts.setOnClickListener(this); - + //addToContacts = (ImageView) view.findViewById(R.id.add_contact); + //addToContacts.setOnClickListener(this); + contactPicture = (ImageView) view.findViewById(R.id.contact_picture); contactName = (TextView) view.findViewById(R.id.contact_name); @@ -98,13 +95,6 @@ public class HistoryDetailFragment extends Fragment implements OnClickListener { } private void displayHistory(String status, String callTime, String callDate) { - contactName.setText(displayName == null ? sipUri : displayName); - if (displayName == null) { - contactAddress.setText(LinphoneUtils.getUsernameFromAddress(sipUri)); - } else { - contactAddress.setText(sipUri); - } - if (status.equals(getResources().getString(R.string.missed))) { callDirection.setImageResource(R.drawable.call_status_missed); } else if (status.equals(getResources().getString(R.string.incoming))) { @@ -115,19 +105,36 @@ public class HistoryDetailFragment extends Fragment implements OnClickListener { time.setText(callTime == null ? "" : callTime); Long longDate = Long.parseLong(callDate); - date.setText(LinphoneUtils.timestampToHumanDate(getActivity(), longDate, getString(R.string.history_detail_date_format), false)); + date.setText(LinphoneUtils.timestampToHumanDate(getActivity(),longDate,getString(R.string.history_detail_date_format), false)); + LinphoneAddress lAddress = null; try { - LinphoneAddress lAddress = LinphoneCoreFactory.instance().createLinphoneAddress(sipUri); + lAddress = LinphoneCoreFactory.instance().createLinphoneAddress(sipUri); LinphoneContact contact = ContactsManager.getInstance().findContactFromAddress(lAddress); if (contact != null && contact.isLinphoneFriend() ) { avatarWithPresenceImage.setLinphoneContact(contact); LinphoneManager.getInstance().addPresenceUpdatedListener(avatarWithPresenceImage); } - } catch(LinphoneCoreException e) { - e.printStackTrace(); + } catch (LinphoneCoreException e) { + Log.e(e); } - + + /*if(lAddress != null) { + contactAddress.setText(lAddress.asStringUriOnly()); + LinphoneContact contact = ContactsManager.getInstance().findContactFromAddress(lAddress); + if (contact != null) { + contactName.setText(contact.getFullName()); + LinphoneUtils.setImagePictureFromUri(view.getContext(),contactPicture,contact.getPhotoUri(),contact.getThumbnailUri()); + addToContacts.setVisibility(View.INVISIBLE); + } else { + contactName.setText(displayName == null ? LinphoneUtils.getAddressDisplayName(sipUri) : displayName); + contactPicture.setImageResource(R.drawable.avatar); + addToContacts.setVisibility(View.VISIBLE); + } + } else { + contactAddress.setText(sipUri); + contactName.setText(displayName == null ? LinphoneUtils.getAddressDisplayName(sipUri) : displayName); + }*/ } public void changeDisplayedHistory(String sipUri, String displayName, String pictureUri, String status, String callTime, String callDate) { @@ -161,11 +168,15 @@ public class HistoryDetailFragment extends Fragment implements OnClickListener { LinphoneActivity.instance().setAddresGoToDialerAndCall(sipUri, displayName, pictureUri == null ? null : Uri.parse(pictureUri)); } else if (id == R.id.chat) { LinphoneActivity.instance().displayChat(sipUri); - } - /*else if (id == R.id.add_contact) { - String uriToAdd = sipUri; - LinphoneActivity.instance().displayContactsForEdition(uriToAdd); - } - */ + } /*else if (id == R.id.add_contact) { + String uri = sipUri; + try { + LinphoneAddress addr = LinphoneCoreFactory.instance().createLinphoneAddress(sipUri); + uri = addr.asStringUriOnly(); + } catch (LinphoneCoreException e) { + Log.e(e); + } + LinphoneActivity.instance().displayContactsForEdition(uri); + }*/ } } diff --git a/src/org/linphone/HistoryListFragment.java b/src/org/linphone/HistoryListFragment.java index 1f3385c0c..d2d31b29c 100644 --- a/src/org/linphone/HistoryListFragment.java +++ b/src/org/linphone/HistoryListFragment.java @@ -205,7 +205,7 @@ public class HistoryListFragment extends Fragment implements OnClickListener, On mLogs = Arrays.asList(LinphoneManager.getLc().getCallLogs()); if (!hideHistoryListAndDisplayMessageIfEmpty()) { historyList.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE); - historyList.setAdapter(new CallHistoryAdapter(getActivity())); + historyList.setAdapter(new CallHistoryAdapter(getActivity().getApplicationContext())); } } diff --git a/src/org/linphone/KeepAliveHandler.java b/src/org/linphone/KeepAliveHandler.java index 5f674893d..7c3ec6fee 100644 --- a/src/org/linphone/KeepAliveHandler.java +++ b/src/org/linphone/KeepAliveHandler.java @@ -28,7 +28,7 @@ public class KeepAliveHandler extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { - Log.i("Keep alive handler invoked"); + //Log.i("Keep alive handler invoked"); //TODO FIXME Crash since the log rework if (LinphoneManager.getLcIfManagerNotDestroyedOrNull() != null) { //first refresh registers LinphoneManager.getLc().refreshRegisters(); @@ -36,7 +36,7 @@ public class KeepAliveHandler extends BroadcastReceiver { try { Thread.sleep(2000); } catch (InterruptedException e) { - Log.e("Cannot sleep for 2s", e); + //Log.e("Cannot sleep for 2s", e); //TODO FIXME Crash since the log rework } } diff --git a/src/org/linphone/LinphoneActivity.java b/src/org/linphone/LinphoneActivity.java index a8aee640f..34fd64900 100644 --- a/src/org/linphone/LinphoneActivity.java +++ b/src/org/linphone/LinphoneActivity.java @@ -70,7 +70,6 @@ import android.net.Uri; import android.os.Bundle; import android.support.v4.app.ActivityCompat; import android.support.v4.widget.DrawerLayout; -import android.transition.ChangeTransform; import android.view.Gravity; import android.view.KeyEvent; import android.view.LayoutInflater; @@ -106,6 +105,7 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta private static final int PERMISSIONS_REQUEST_READ_CONTACTS = 200; private static final int PERMISSIONS_REQUEST_RECORD_AUDIO = 201; private static final int PERMISSIONS_REQUEST_RECORD_AUDIO_INCOMING_CALL = 203; + private static final int PERMISSIONS_REQUEST_EXTERNAL_FILE_STORAGE = 204; private static LinphoneActivity instance; @@ -113,16 +113,14 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta private TextView missedCalls, missedChats; private ImageView contacts, dialer, historyImage, chatImage; private RelativeLayout history, chat; - private FragmentsAvailable currentFragment, nextFragment; + private FragmentsAvailable pendingFragmentTransaction, currentFragment, nextFragment; private List fragmentsHistory; - private Fragment dialerFragment, chatListFragment, historyListFragment, contactListFragment; - private ChatFragment chatFragment; private Fragment.SavedState dialerSavedState; private boolean newProxyConfig; - private boolean isAnimationDisabled = false, preferLinphoneContacts = false, emptyFragment = false, permissionAsked = false; + private boolean isAnimationDisabled = false, emptyFragment = false, permissionAsked = false; private OrientationEventListener mOrientationHelper; private LinphoneCoreListenerBase mListener; - private LinearLayout mTabBar; + private LinearLayout mTabBar; private DrawerLayout sideMenu; private String[] sideMenuItems; @@ -182,7 +180,6 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta } } - //TODO rework if (getResources().getBoolean(R.bool.use_linphone_tag) && getPackageManager().checkPermission(Manifest.permission.WRITE_SYNC_SETTINGS, getPackageName()) == PackageManager.PERMISSION_GRANTED) { ContactsManager.getInstance().initializeSyncAccount(getApplicationContext(), getContentResolver()); @@ -193,31 +190,20 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta setContentView(R.layout.main); instance = this; fragmentsHistory = new ArrayList(); + pendingFragmentTransaction = FragmentsAvailable.UNKNOW; initButtons(); initSideMenu(); - currentFragment = nextFragment = FragmentsAvailable.DIALER; - fragmentsHistory.add(currentFragment); + currentFragment = nextFragment = FragmentsAvailable.EMPTY; if (savedInstanceState == null) { - if (findViewById(R.id.fragmentContainer) != null) { - dialerFragment = new DialerFragment(); - dialerFragment.setArguments(getIntent().getExtras()); - getFragmentManager().beginTransaction().add(R.id.fragmentContainer, dialerFragment, currentFragment.toString()).commit(); - selectMenu(FragmentsAvailable.DIALER); - } + changeCurrentFragment(FragmentsAvailable.DIALER, getIntent().getExtras()); } - mListener = new LinphoneCoreListenerBase(){ + mListener = new LinphoneCoreListenerBase(){ @Override public void messageReceived(LinphoneCore lc, LinphoneChatRoom cr, LinphoneChatMessage message) { - if(!displayChatMessageNotification(message.getFrom().asStringUriOnly())) { - cr.markAsRead(); - } displayMissedChats(getUnreadMessageCount()); - if (chatListFragment != null && chatListFragment.isVisible()) { - ((ChatListFragment) chatListFragment).refresh(); - } } @Override @@ -327,18 +313,7 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta lc.removeListener(mListener); } - mListener = new LinphoneCoreListenerBase(){ - @Override - public void messageReceived(LinphoneCore lc, LinphoneChatRoom cr, LinphoneChatMessage message) { - if(!displayChatMessageNotification(message.getFrom().asStringUriOnly())) { - cr.markAsRead(); - } - displayMissedChats(getUnreadMessageCount()); - if (chatListFragment != null && chatListFragment.isVisible()) { - ((ChatListFragment) chatListFragment).refresh(); - } - } - + mListener = new LinphoneCoreListenerBase() { @Override public void registrationState(LinphoneCore lc, LinphoneProxyConfig proxy, LinphoneCore.RegistrationState state, String smessage) { if (state.equals(RegistrationState.RegistrationCleared)) { @@ -462,6 +437,7 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta if (currentFragment == FragmentsAvailable.DIALER) { try { + DialerFragment dialerFragment = DialerFragment.instance(); dialerSavedState = getFragmentManager().saveFragmentInstanceState(dialerFragment); } catch (Exception e) { } @@ -472,14 +448,18 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta switch (newFragmentType) { case HISTORY_LIST: newFragment = new HistoryListFragment(); - historyListFragment = newFragment; + if (isTablet()) { + ((HistoryListFragment) newFragment).displayFirstLog(); + } break; case HISTORY_DETAIL: newFragment = new HistoryDetailFragment(); break; case CONTACTS_LIST: newFragment = new ContactsListFragment(); - contactListFragment = newFragment; + if (isTablet()) { + ((ContactsListFragment) newFragment).displayFirstContact(); + } break; case CONTACT_DETAIL: newFragment = new ContactDetailsFragment(); @@ -492,7 +472,6 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta if (extras == null) { newFragment.setInitialSavedState(dialerSavedState); } - dialerFragment = newFragment; break; case SETTINGS: newFragment = new SettingsFragment(); @@ -508,7 +487,9 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta break; case CHAT_LIST: newFragment = new ChatListFragment(); - chatListFragment = newFragment; + if (isTablet()) { + ((ChatListFragment) newFragment).displayFirstChat(); + } break; case CHAT: newFragment = new ChatFragment(); @@ -536,7 +517,8 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta } private void changeFragment(Fragment newFragment, FragmentsAvailable newFragmentType, boolean withoutAnimation) { - FragmentTransaction transaction = getFragmentManager().beginTransaction(); + FragmentManager fm = getFragmentManager(); + FragmentTransaction transaction = fm.beginTransaction(); /*if (!withoutAnimation && !isAnimationDisabled && currentFragment.shouldAnimate()) { if (newFragmentType.isRightOf(currentFragment)) { @@ -553,14 +535,19 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta }*/ if (newFragmentType != FragmentsAvailable.DIALER - || newFragmentType != FragmentsAvailable.CONTACTS_LIST - || newFragmentType != FragmentsAvailable.CHAT_LIST - || newFragmentType != FragmentsAvailable.HISTORY_LIST) { + && newFragmentType != FragmentsAvailable.CONTACTS_LIST + && newFragmentType != FragmentsAvailable.CHAT_LIST + && newFragmentType != FragmentsAvailable.HISTORY_LIST) { transaction.addToBackStack(newFragmentType.toString()); + } else { + while (fm.getBackStackEntryCount() > 0) { + fm.popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); + } } + transaction.replace(R.id.fragmentContainer, newFragment, newFragmentType.toString()); - transaction.commitAllowingStateLoss(); - getFragmentManager().executePendingTransactions(); + transaction.commit(); + fm.executePendingTransactions(); currentFragment = newFragmentType; } @@ -582,7 +569,7 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta ll.setVisibility(View.VISIBLE); emptyFragment = true; transaction.replace(R.id.fragmentContainer2, newFragment); - transaction.commitAllowingStateLoss(); + transaction.commit(); getFragmentManager().executePendingTransactions(); } else { if (newFragmentType.shouldAddItselfToTheRightOf(currentFragment)) { @@ -618,7 +605,7 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta }*/ transaction.replace(R.id.fragmentContainer, newFragment); } - transaction.commitAllowingStateLoss(); + transaction.commit(); getFragmentManager().executePendingTransactions(); currentFragment = newFragmentType; @@ -715,11 +702,6 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta changeCurrentFragment(FragmentsAvailable.CONTACTS_LIST, extras); } - public void displayChatList() { - Bundle extras = new Bundle(); - changeCurrentFragment(FragmentsAvailable.CHAT_LIST, extras); - } - public void displayContactsForEdition(String sipAddress) { Bundle extras = new Bundle(); extras.putBoolean("EditOnClick", true); @@ -735,15 +717,6 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta startActivity(new Intent(LinphoneActivity.this, AssistantActivity.class)); } - public boolean displayChatMessageNotification(String address){ - if(chatFragment != null) { - if(chatFragment.getSipUri().equals(address)) { - return false; - } - } - return true; - } - public int getUnreadMessageCount() { int count = 0; LinphoneChatRoom[] chats = LinphoneManager.getLc().getChatRooms(); @@ -811,10 +784,6 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta } } - if (chatListFragment != null && chatListFragment.isVisible()) { - ((ChatListFragment) chatListFragment).refresh(); - } - LinphoneService.instance().resetMessageNotifCount(); LinphoneService.instance().removeMessageNotification(); displayMissedChats(getUnreadMessageCount()); @@ -823,38 +792,35 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta @Override public void onClick(View v) { int id = v.getId(); + resetSelection(); if (id == R.id.history) { changeCurrentFragment(FragmentsAvailable.HISTORY_LIST, null); + //history_selected.setVisibility(View.VISIBLE); LinphoneManager.getLc().resetMissedCallsCount(); displayMissedCalls(0); - if(isTablet()) { - if (historyListFragment != null && historyListFragment.isVisible()) { - ((HistoryListFragment) historyListFragment).displayFirstLog(); - } - } } else if (id == R.id.contacts) { changeCurrentFragment(FragmentsAvailable.CONTACTS_LIST, null); - if(isTablet()) { - if (contactListFragment != null && contactListFragment.isVisible()) { - ((ContactsListFragment) contactListFragment).displayFirstContact(); - } - } + //contacts_selected.setVisibility(View.VISIBLE); } else if (id == R.id.dialer) { changeCurrentFragment(FragmentsAvailable.DIALER, null); + //dialer_selected.setVisibility(View.VISIBLE); } else if (id == R.id.chat) { changeCurrentFragment(FragmentsAvailable.CHAT_LIST, null); - if(isTablet()) { - if (chatListFragment != null && chatListFragment.isVisible()) { - ((ChatListFragment) chatListFragment).displayFirstChat(); - } - } + //chat_selected.setVisibility(View.VISIBLE); } else if (id == R.id.cancel){ hideTopBar(); displayDialer(); } } + private void resetSelection() { + /*history_selected.setVisibility(View.GONE); + contacts_selected.setVisibility(View.GONE); + dialer_selected.setVisibility(View.GONE); + chat_selected.setVisibility(View.GONE);*/ + } + public void hideTabBar(Boolean hide) { if(hide){ mTabBar.setVisibility(View.GONE); @@ -905,19 +871,10 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta } public void updateDialerFragment(DialerFragment fragment) { - dialerFragment = fragment; // Hack to maintain soft input flags getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN | WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); } - public void updateChatFragment(ChatFragment fragment) { - chatFragment = fragment; - } - - public void updateChatListFragment(ChatListFragment fragment) { - chatListFragment = fragment; - } - public void updateStatusFragment(StatusFragment fragment) { statusFragment = fragment; } @@ -955,10 +912,6 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta return getChatStorage().getDrafts(); } - public List getChatMessages(String correspondent) { - return getChatStorage().getMessages(correspondent); - } - public void removeFromChatList(String sipUri) { getChatStorage().removeDiscussion(sipUri); } @@ -967,18 +920,12 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta getChatStorage().deleteDraft(sipUri); } - - public void updateMissedChatCount() { displayMissedChats(getUnreadMessageCount()); } public int onMessageSent(String to, String message) { getChatStorage().deleteDraft(to); - if (chatListFragment != null && chatListFragment.isVisible()) { - ((ChatListFragment) chatListFragment).refresh(); - } - return getChatStorage().saveTextMessage("", to, message, System.currentTimeMillis()); } @@ -1112,17 +1059,6 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta } } - public void setAddressAndGoToDialer(String number) { - Bundle extras = new Bundle(); - extras.putString("SipUri", number); - changeCurrentFragment(FragmentsAvailable.DIALER, extras); - } - - @Override - public void goToDialer() { - changeCurrentFragment(FragmentsAvailable.DIALER, null); - } - public void startVideoActivity(LinphoneCall currentCall) { Intent intent = new Intent(this, CallActivity.class); intent.putExtra("VideoEnabled", true); @@ -1204,12 +1140,14 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta private void initInCallMenuLayout(boolean callTransfer) { selectMenu(FragmentsAvailable.DIALER); + DialerFragment dialerFragment = DialerFragment.instance(); if (dialerFragment != null) { ((DialerFragment) dialerFragment).resetLayout(callTransfer); } } public void resetClassicMenuLayoutAndGoBackToCallIfStillRunning() { + DialerFragment dialerFragment = DialerFragment.instance(); if (dialerFragment != null) { ((DialerFragment) dialerFragment).resetLayout(false); } @@ -1255,13 +1193,23 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta Bundle extras = new Bundle(); extras.putSerializable("Contact", contact); extras.putSerializable("NewSipAdress", sipAddress); - changeCurrentFragment(FragmentsAvailable.CONTACT_EDITOR, extras); + changeCurrentFragment(FragmentsAvailable.CONTACT_EDITOR, extras); } public void quit() { finish(); stopService(new Intent(Intent.ACTION_MAIN).setClass(this, LinphoneService.class)); } + + @Override + protected void onPostResume() { + super.onPostResume(); + if (pendingFragmentTransaction != FragmentsAvailable.UNKNOW) { + changeCurrentFragment(pendingFragmentTransaction, null, true); + selectMenu(pendingFragmentTransaction); + pendingFragmentTransaction = FragmentsAvailable.UNKNOW; + } + } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { @@ -1272,16 +1220,14 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta if (data.getExtras().getBoolean("Exit", false)) { quit(); } else { - FragmentsAvailable newFragment = (FragmentsAvailable) data.getExtras().getSerializable("FragmentToDisplay"); - changeCurrentFragment(newFragment, null, true); - selectMenu(newFragment); + pendingFragmentTransaction = (FragmentsAvailable) data.getExtras().getSerializable("FragmentToDisplay"); } } else if (resultCode == Activity.RESULT_FIRST_USER && requestCode == CALL_ACTIVITY) { getIntent().putExtra("PreviousActivity", CALL_ACTIVITY); boolean callTransfer = data == null ? false : data.getBooleanExtra("Transfer", false); boolean chat = data == null ? false : data.getBooleanExtra("chat", false); if(chat){ - displayChatList(); + pendingFragmentTransaction = FragmentsAvailable.CHAT_LIST; } if (LinphoneManager.getLc().getCallsNb() > 0) { initInCallMenuLayout(callTransfer); @@ -1298,9 +1244,14 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta LinphoneManager.getInstance().enableProxyPublish(!isApplicationBroughtToBackground(this)); //LinphoneManager.getInstance().subscribeFriendList(false); getIntent().putExtra("PreviousActivity", 0); - super.onPause(); } + + public void checkAndRequestExternalStoragePermission() { + if (getPackageManager().checkPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, getPackageName()) != PackageManager.PERMISSION_GRANTED) { + checkAndRequestPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, PERMISSIONS_REQUEST_EXTERNAL_FILE_STORAGE); + } + } public void checkAndRequestPermission(String permission, int result) { if (getPackageManager().checkPermission(permission, getPackageName()) != PackageManager.PERMISSION_GRANTED) { @@ -1355,6 +1306,7 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta @Override protected void onResume() { super.onResume(); + if (!LinphoneService.isReady()) { startService(new Intent(Intent.ACTION_MAIN).setClass(this, LinphoneService.class)); } @@ -1400,17 +1352,8 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta } } } - } - - @Override - protected void onStop() { - - super.onStop(); - } - - @Override protected void onDestroy() { if (mOrientationHelper != null) { @@ -1461,6 +1404,7 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta } } } else { + DialerFragment dialerFragment = DialerFragment.instance(); if (dialerFragment != null) { if (extras != null && extras.containsKey("SipUriOrNumber")) { if (getResources().getBoolean(R.bool.automatically_start_intercepted_outgoing_gsm_call)) { @@ -1595,7 +1539,7 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta return R.drawable.led_disconnected; } } catch (Exception e) { - e.printStackTrace(); + Log.e(e); } return R.drawable.led_disconnected; @@ -1607,6 +1551,7 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta TextView address = (TextView) defaultAccount.findViewById(R.id.main_account_address); TextView displayName = (TextView) defaultAccount.findViewById(R.id.main_account_display_name); + LinphoneProxyConfig proxy = LinphoneManager.getLc().getDefaultProxyConfig(); if(proxy == null && LinphoneManager.getLc().getProxyConfigList().length == 0) { displayName.setText(getString(R.string.no_account)); @@ -1735,5 +1680,4 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta interface ContactPicked { void setAddresGoToDialerAndCall(String number, String name, Uri photo); - void goToDialer(); } diff --git a/src/org/linphone/LinphoneContact.java b/src/org/linphone/LinphoneContact.java index 14b36cd44..ff2a6b88a 100644 --- a/src/org/linphone/LinphoneContact.java +++ b/src/org/linphone/LinphoneContact.java @@ -426,7 +426,15 @@ public class LinphoneContact implements Serializable, Comparable