diff --git a/README b/README
index 1693d40d6..e2269f90d 100644
--- a/README
+++ b/README
@@ -7,8 +7,8 @@ COMPILATION INSTRUCTIONS
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 (version r11) from google and add it to your path (no symlink !!!).
+0) download the Android sdk (API 23 at least) with platform-tools and tools updated to latest revision, then add both 'tools' and 'platform-tools' folders in your path.
+1) download the Android ndk (version r11c or 12b) from google and add it to your path (no symlink !!!).
2) install yasm, nasm, ant, python, cmake and vim-common
On 64 bits linux systems you'll need the ia32-libs package
With the latest Debian (multiarch), you need this:
@@ -27,11 +27,12 @@ To build liblinphone for Android, you must:
$ make mediastreamer2-sdk
8) (Optional) To generate a signed apk to publish on the Google Play, run
$ make release
-Make sure you filled the ant.properties values for version.name, key.store and key.alias in order to correctly sign the generated apk.
-You also may want to create a file name ant_password.properties with the following:
-key.store.password=[your_password]
-key.alias.password=[your_password]
-If you don't, the passwords will be asked at the signing phase.
+ Make sure you filled the ant.properties values for version.name, key.store and key.alias in order to correctly sign the generated apk.
+ You also may want to create a file name ant_password.properties with the following:
+ key.store.password=[your_password]
+ key.alias.password=[your_password]
+ If you don't, the passwords will be asked at the signing phase.
+9) (Optional) Once you compiled the libraries succesfully with 'make', you can reduce the compilation time using 'make quick': it will only generate a new APK from java files.
To run the tutorials:
--------------------
diff --git a/liblinphone_tester/custom_rules.xml b/liblinphone_tester/custom_rules.xml
index da0216dc5..8a36b3884 100644
--- a/liblinphone_tester/custom_rules.xml
+++ b/liblinphone_tester/custom_rules.xml
@@ -48,7 +48,7 @@
-
+
diff --git a/res/layout/chat.xml b/res/layout/chat.xml
index 7d8274577..11b7953ef 100644
--- a/res/layout/chat.xml
+++ b/res/layout/chat.xml
@@ -128,8 +128,9 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout/chat_bubble_incoming.xml b/res/layout/chat_bubble_incoming.xml
deleted file mode 100644
index d3912a238..000000000
--- a/res/layout/chat_bubble_incoming.xml
+++ /dev/null
@@ -1,114 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/res/layout/chat_bubble_outgoing.xml b/res/layout/chat_bubble_outgoing.xml
deleted file mode 100644
index a96d18751..000000000
--- a/res/layout/chat_bubble_outgoing.xml
+++ /dev/null
@@ -1,112 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/res/layout/contact_edit.xml b/res/layout/contact_edit.xml
index da442c190..933c88ab2 100644
--- a/res/layout/contact_edit.xml
+++ b/res/layout/contact_edit.xml
@@ -136,6 +136,7 @@
android:inputType="textPersonName|textCapWords"/>
false
false
+ true
+
false
true
diff --git a/res/values/non_localizable_strings.xml b/res/values/non_localizable_strings.xml
index 7b0463d28..c114a813e 100644
--- a/res/values/non_localizable_strings.xml
+++ b/res/values/non_localizable_strings.xml
@@ -107,6 +107,7 @@
pref_background_mode_key
pref_codec_bitrate_limit_key
pref_adaptive_rate_control_key
+ pref_echo_tester_key
push_reg_id_key
push_sender_id_key
@@ -204,4 +205,5 @@
pref_use_lime_encryption_key
pref_device_ringtone_key
pref_auto_answer_key
+ pref_android_app_settings_key
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 3d423c483..62bd17bb9 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -273,6 +273,7 @@
Echo cancellation
Removes the echo heard by other end
Echo canceler calibration
+ Test echo
Calibrating…
Calibrated in %s ms
No echo
@@ -340,6 +341,7 @@
Start at boot time
Incoming call hangup (in seconds)
Remote provisioning
+ Android app settings
Primary account
Display name
Username
diff --git a/res/xml/contacts.xml b/res/xml/contacts.xml
index 6b5d8e180..db84bc8c9 100644
--- a/res/xml/contacts.xml
+++ b/res/xml/contacts.xml
@@ -3,7 +3,7 @@
-
+
+
+
+
+
diff --git a/src/org/linphone/AboutFragment.java b/src/org/linphone/AboutFragment.java
index 933e9914f..e5cabadc5 100644
--- a/src/org/linphone/AboutFragment.java
+++ b/src/org/linphone/AboutFragment.java
@@ -69,11 +69,11 @@ public class AboutFragment extends Fragment implements OnClickListener {
sendLogButton = view.findViewById(R.id.send_log);
sendLogButton.setOnClickListener(this);
- sendLogButton.setVisibility(org.linphone.LinphonePreferences.instance().isDebugEnabled() ? View.VISIBLE : View.GONE);
+ sendLogButton.setVisibility(LinphonePreferences.instance().isDebugEnabled() ? View.VISIBLE : View.GONE);
resetLogButton = view.findViewById(R.id.reset_log);
resetLogButton.setOnClickListener(this);
- resetLogButton.setVisibility(org.linphone.LinphonePreferences.instance().isDebugEnabled() ? View.VISIBLE : View.GONE);
+ resetLogButton.setVisibility(LinphonePreferences.instance().isDebugEnabled() ? View.VISIBLE : View.GONE);
mListener = new LinphoneCoreListenerBase() {
@Override
@@ -145,7 +145,7 @@ public class AboutFragment extends Fragment implements OnClickListener {
lc.addListener(mListener);
}
- if (org.linphone.LinphoneActivity.isInstanciated()) {
+ if (LinphoneActivity.isInstanciated()) {
LinphoneActivity.instance().selectMenu(FragmentsAvailable.ABOUT);
}
@@ -154,8 +154,8 @@ public class AboutFragment extends Fragment implements OnClickListener {
@Override
public void onClick(View v) {
- if (org.linphone.LinphoneActivity.isInstanciated()) {
- LinphoneCore lc = org.linphone.LinphoneManager.getLcIfManagerNotDestroyedOrNull();
+ if (LinphoneActivity.isInstanciated()) {
+ LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
if (v == sendLogButton) {
if (lc != null) {
lc.uploadLogCollection();
@@ -174,6 +174,4 @@ public class AboutFragment extends Fragment implements OnClickListener {
public void onDestroy() {
super.onDestroy();
}
-
-
}
diff --git a/src/org/linphone/AccountPreferencesFragment.java b/src/org/linphone/AccountPreferencesFragment.java
index 0ba776a1f..9e6c98417 100644
--- a/src/org/linphone/AccountPreferencesFragment.java
+++ b/src/org/linphone/AccountPreferencesFragment.java
@@ -53,8 +53,7 @@ public class AccountPreferencesFragment extends PreferencesListFragment {
mPrefs = LinphonePreferences.instance();
}
- public void onCreate(Bundle savedInstanceState)
- {
+ public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
PreferenceScreen screen = getPreferenceScreen();
@@ -69,7 +68,7 @@ public class AccountPreferencesFragment extends PreferencesListFragment {
getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
}
- public static boolean isEditTextEmpty(String s){
+ public static boolean isEditTextEmpty(String s) {
return s.equals(""); // really empty.
}
diff --git a/src/org/linphone/BluetoothManager.java b/src/org/linphone/BluetoothManager.java
index 34982c4e0..c3d0523ec 100644
--- a/src/org/linphone/BluetoothManager.java
+++ b/src/org/linphone/BluetoothManager.java
@@ -19,7 +19,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import java.util.List;
-import org.linphone.compatibility.Compatibility;
import org.linphone.mediastream.Log;
import android.annotation.TargetApi;
@@ -68,31 +67,31 @@ public class BluetoothManager extends BroadcastReceiver {
public BluetoothManager() {
isBluetoothConnected = false;
if (!ensureInit()) {
- Log.w("BluetoothManager tried to init but LinphoneService not ready yet...");
+ Log.w("[Bluetooth] Manager tried to init but LinphoneService not ready yet...");
}
instance = this;
}
public void initBluetooth() {
if (!ensureInit()) {
- Log.w("BluetoothManager tried to init bluetooth but LinphoneService not ready yet...");
+ Log.w("[Bluetooth] Manager tried to init bluetooth but LinphoneService not ready yet...");
return;
}
IntentFilter filter = new IntentFilter();
filter.addCategory(BluetoothHeadset.VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORY + "." + BluetoothAssignedNumbers.PLANTRONICS);
- filter.addAction(Compatibility.getAudioManagerEventForBluetoothConnectionStateChangedEvent());
+ filter.addAction(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED);
filter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
filter.addAction(BluetoothHeadset.ACTION_VENDOR_SPECIFIC_HEADSET_EVENT);
mContext.registerReceiver(this, filter);
- Log.d("Bluetooth receiver started");
+ Log.d("[Bluetooth] Receiver started");
startBluetooth();
}
private void startBluetooth() {
if (isBluetoothConnected) {
- Log.e("Bluetooth already started");
+ Log.e("[Bluetooth] Already started, skipping...");
return;
}
@@ -100,14 +99,14 @@ public class BluetoothManager extends BroadcastReceiver {
if (mBluetoothAdapter != null && mBluetoothAdapter.isEnabled()) {
if (mProfileListener != null) {
- Log.w("Bluetooth headset profile was already opened, let's close it");
+ Log.w("[Bluetooth] Headset profile was already opened, let's close it");
mBluetoothAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset);
}
mProfileListener = new BluetoothProfile.ServiceListener() {
public void onServiceConnected(int profile, BluetoothProfile proxy) {
if (profile == BluetoothProfile.HEADSET) {
- Log.d("Bluetooth headset connected");
+ Log.d("[Bluetooth] Headset connected");
mBluetoothHeadset = (BluetoothHeadset) proxy;
isBluetoothConnected = true;
}
@@ -116,17 +115,17 @@ public class BluetoothManager extends BroadcastReceiver {
if (profile == BluetoothProfile.HEADSET) {
mBluetoothHeadset = null;
isBluetoothConnected = false;
- Log.d("Bluetooth headset disconnected");
+ Log.d("[Bluetooth] Headset disconnected");
LinphoneManager.getInstance().routeAudioToReceiver();
}
}
};
boolean success = mBluetoothAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.HEADSET);
if (!success) {
- Log.e("Bluetooth getProfileProxy failed !");
+ Log.e("[Bluetooth] getProfileProxy failed !");
}
} else {
- Log.w("Bluetooth interface disabled on device");
+ Log.w("[Bluetooth] Interface disabled on device");
}
}
@@ -153,7 +152,7 @@ public class BluetoothManager extends BroadcastReceiver {
if (mBluetoothAdapter != null && mBluetoothAdapter.isEnabled() && mAudioManager != null && mAudioManager.isBluetoothScoAvailableOffCall()) {
if (isBluetoothHeadsetAvailable()) {
if (mAudioManager != null && !mAudioManager.isBluetoothScoOn()) {
- Log.d("Bluetooth sco off, let's start it");
+ Log.d("[Bluetooth] SCO off, let's start it");
mAudioManager.setBluetoothScoOn(true);
mAudioManager.startBluetoothSco();
}
@@ -180,12 +179,12 @@ public class BluetoothManager extends BroadcastReceiver {
}
if (ok) {
if (retries > 0) {
- Log.d("Bluetooth route ok after " + retries + " retries");
+ Log.d("[Bluetooth] Audio route ok after " + retries + " retries");
} else {
- Log.d("Bluetooth route ok");
+ Log.d("[Bluetooth] Audio route ok");
}
} else {
- Log.d("Bluetooth still not ok...");
+ Log.d("[Bluetooth] Audio route still not ok...");
}
return ok;
@@ -212,7 +211,7 @@ public class BluetoothManager extends BroadcastReceiver {
break;
}
}
- Log.d(isHeadsetConnected ? "Headset found, bluetooth audio route available" : "No headset found, bluetooth audio route unavailable");
+ Log.d(isHeadsetConnected ? "[Bluetooth] Headset found, bluetooth audio route available" : "[Bluetooth] No headset found, bluetooth audio route unavailable");
}
return isHeadsetConnected;
}
@@ -237,12 +236,12 @@ public class BluetoothManager extends BroadcastReceiver {
mAudioManager.stopBluetoothSco();
mAudioManager.setBluetoothScoOn(false);
}
- Log.w("Bluetooth sco disconnected!");
+ Log.w("[Bluetooth] SCO disconnected!");
}
}
public void stopBluetooth() {
- Log.w("Stopping bluetooth...");
+ Log.w("[Bluetooth] Stopping...");
isBluetoothConnected = false;
disableBluetoothSCO();
@@ -253,7 +252,7 @@ public class BluetoothManager extends BroadcastReceiver {
}
mBluetoothDevice = null;
- Log.w("Bluetooth stopped!");
+ Log.w("[Bluetooth] Stopped!");
if (LinphoneManager.isInstanciated()) {
LinphoneManager.getInstance().routeAudioToReceiver();
@@ -266,7 +265,7 @@ public class BluetoothManager extends BroadcastReceiver {
try {
mContext.unregisterReceiver(this);
- Log.d("Bluetooth receiver stopped");
+ Log.d("[Bluetooth] Receiver stopped");
} catch (Exception e) {}
} catch (Exception e) {
Log.e(e);
@@ -278,30 +277,30 @@ public class BluetoothManager extends BroadcastReceiver {
return;
String action = intent.getAction();
- if (Compatibility.getAudioManagerEventForBluetoothConnectionStateChangedEvent().equals(action)) {
+ if (AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED.equals(action)) {
int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, 0);
if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED) {
- Log.d("Bluetooth sco state => connected");
+ Log.d("[Bluetooth] SCO state: connected");
// LinphoneManager.getInstance().audioStateChanged(AudioState.BLUETOOTH);
isScoConnected = true;
} else if (state == AudioManager.SCO_AUDIO_STATE_DISCONNECTED) {
- Log.d("Bluetooth sco state => disconnected");
+ Log.d("[Bluetooth] SCO state: disconnected");
// LinphoneManager.getInstance().audioStateChanged(AudioState.SPEAKER);
isScoConnected = false;
} else {
- Log.d("Bluetooth sco state => " + state);
+ Log.d("[Bluetooth] SCO state: " + state);
}
}
else if (BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED.equals(action)) {
int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE, BluetoothAdapter.STATE_DISCONNECTED);
if (state == 0) {
- Log.d("Bluetooth state => disconnected");
+ Log.d("[Bluetooth] State: disconnected");
stopBluetooth();
} else if (state == 2) {
- Log.d("Bluetooth state => connected");
+ Log.d("[Bluetooth] State: connected");
startBluetooth();
} else {
- Log.d("Bluetooth state => " + state);
+ Log.d("[Bluetooth] State: " + state);
}
}
else if (intent.getAction().equals(BluetoothHeadset.ACTION_VENDOR_SPECIFIC_HEADSET_EVENT)) {
@@ -314,7 +313,7 @@ public class BluetoothManager extends BroadcastReceiver {
if (eventName.equals("BUTTON") && args.length >= 3) {
Integer buttonID = (Integer) args[1];
Integer mode = (Integer) args[2];
- Log.d("Bluetooth event: " + command + " : " + eventName + ", id = " + buttonID + " (" + mode + ")");
+ Log.d("[Bluetooth] Event: " + command + " : " + eventName + ", id = " + buttonID + " (" + mode + ")");
}
}
}
diff --git a/src/org/linphone/CallActivity.java b/src/org/linphone/CallActivity.java
index b9274d53d..da94060e8 100644
--- a/src/org/linphone/CallActivity.java
+++ b/src/org/linphone/CallActivity.java
@@ -119,6 +119,7 @@ public class CallActivity extends Activity implements OnClickListener, SensorEve
private boolean isConferenceRunning = false;
private LinphoneCoreListenerBase mListener;
private DrawerLayout sideMenu;
+ private boolean mProximitySensingEnabled;
public static CallActivity instance() {
return instance;
@@ -800,8 +801,22 @@ public class CallActivity extends Activity implements OnClickListener, SensorEve
}
}
+ private void enableProximitySensing(boolean enable){
+ if (enable){
+ if (!mProximitySensingEnabled){
+ mSensorManager.registerListener(this, mProximity, SensorManager.SENSOR_DELAY_NORMAL);
+ mProximitySensingEnabled = true;
+ }
+ }else{
+ if (mProximitySensingEnabled){
+ mSensorManager.unregisterListener(this);
+ mProximitySensingEnabled = false;
+ }
+ }
+ }
+
private void showAudioView() {
- mSensorManager.registerListener(this, mProximity, SensorManager.SENSOR_DELAY_NORMAL);
+ enableProximitySensing(true);
replaceFragmentVideoByAudio();
displayAudioCall();
showStatusBar();
@@ -816,7 +831,7 @@ public class CallActivity extends Activity implements OnClickListener, SensorEve
}
refreshInCallActions();
- mSensorManager.unregisterListener(this);
+ enableProximitySensing(false);
replaceFragmentAudioByVideo();
hideStatusBar();
}
@@ -1173,7 +1188,7 @@ public class CallActivity extends Activity implements OnClickListener, SensorEve
handleViewIntent();
if (!isVideoEnabled(LinphoneManager.getLc().getCurrentCall())) {
- mSensorManager.registerListener(this, mProximity, SensorManager.SENSOR_DELAY_NORMAL);
+ enableProximitySensing(true);
removeCallbacks();
}
}
@@ -1223,10 +1238,7 @@ public class CallActivity extends Activity implements OnClickListener, SensorEve
mControlsHandler.removeCallbacks(mControls);
}
mControls = null;
-
- if (!isVideoEnabled(LinphoneManager.getLc().getCurrentCall())) {
- mSensorManager.unregisterListener(this);
- }
+ enableProximitySensing(false);
}
@Override
@@ -1239,7 +1251,7 @@ public class CallActivity extends Activity implements OnClickListener, SensorEve
mControls = null;
mControlsHandler = null;
- mSensorManager.unregisterListener(this);
+ enableProximitySensing(false);
unbindDrawables(findViewById(R.id.topLayout));
instance = null;
@@ -1510,7 +1522,7 @@ public class CallActivity extends Activity implements OnClickListener, SensorEve
private void displayConference(boolean isInConf){
if(isInConf) {
mControlsLayout.setVisibility(View.VISIBLE);
- mSensorManager.registerListener(this, mProximity, SensorManager.SENSOR_DELAY_NORMAL);
+ enableProximitySensing(true);
mActiveCallHeader.setVisibility(View.GONE);
mNoCurrentCall.setVisibility(View.GONE);
conferenceList.removeAllViews();
diff --git a/src/org/linphone/ChatFragment.java b/src/org/linphone/ChatFragment.java
index 4f8c4323e..5dfdadc77 100644
--- a/src/org/linphone/ChatFragment.java
+++ b/src/org/linphone/ChatFragment.java
@@ -21,8 +21,13 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.lang.ref.WeakReference;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Calendar;
import java.util.List;
import java.util.Locale;
@@ -37,22 +42,29 @@ import org.linphone.core.LinphoneCore;
import org.linphone.core.LinphoneCoreFactory;
import org.linphone.core.LinphoneCoreListenerBase;
import org.linphone.mediastream.Log;
-import org.linphone.ui.BubbleChat;
+import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Dialog;
import android.app.Fragment;
import android.app.ProgressDialog;
+import android.content.ClipData;
+import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager;
import android.content.res.Configuration;
+import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.Rect;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
import android.media.ExifInterface;
+import android.media.ThumbnailUtils;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
@@ -61,9 +73,10 @@ import android.os.Parcelable;
import android.provider.MediaStore;
import android.support.v4.content.CursorLoader;
import android.text.Editable;
+import android.text.Spanned;
import android.text.TextWatcher;
+import android.text.method.LinkMovementMethod;
import android.view.ContextMenu;
-import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
@@ -72,7 +85,6 @@ import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
-import android.widget.AbsListView;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.CheckBox;
@@ -81,6 +93,7 @@ import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
+import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
@@ -111,6 +124,7 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
private SearchContactsListAdapter searchAdapter;
private ListView messagesList, resultContactsSearch;
private LayoutInflater inflater;
+ private Bitmap defaultBitmap;
private boolean isEditMode = false;
private LinphoneContact contact;
@@ -143,9 +157,10 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
}
//Initialize UI
+ defaultBitmap = BitmapFactory.decodeResource(getActivity().getResources(), R.drawable.chat_picture_over);
+
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);
@@ -214,7 +229,6 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
LinphoneService.instance().removeMessageNotification();
cr.markAsRead();
adapter.addMessage(cr.getHistory(1)[0]);
- messagesList.setSelection(adapter.getCount()-1);
String externalBodyUrl = message.getExternalBodyUrl();
LinphoneContent fileTransferContent = message.getFileTransferInformation();
@@ -320,135 +334,11 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
}
}
- class ChatMessageAdapter extends BaseAdapter {
- ArrayList history;
- Context context;
-
- public ChatMessageAdapter(Context c) {
- context = c;
- history = new ArrayList();
- refreshHistory();
- }
-
- public void destroy() {
- if (history != null) {
- history.clear();
- }
- }
-
- public void refreshHistory() {
- history.clear();
- LinphoneChatMessage[] messages = chatRoom.getHistory();
- history.addAll(Arrays.asList(messages));
- notifyDataSetChanged();
- }
-
- public void addMessage(LinphoneChatMessage message) {
- history.add(message);
- notifyDataSetChanged();
- }
-
- @Override
- public int getCount() {
- return history.size();
- }
-
- @Override
- public LinphoneChatMessage getItem(int position) {
- return history.get(position);
- }
-
- @Override
- public long getItemId(int position) {
- return history.get(position).getStorageId();
- }
-
- @Override
- public View getView(final int position, View convertView, ViewGroup parent) {
- 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);
-
- CheckBox deleteChatBubble = (CheckBox) v.findViewById(R.id.delete_message);
-
- if(isEditMode) {
- deleteChatBubble.setVisibility(View.VISIBLE);
- if(message.isOutgoing()){
- RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
- layoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
- layoutParams.setMargins(100, 10, 10, 10);
- v.setLayoutParams(layoutParams);
- } else {
- LinearLayout message_layout = (LinearLayout) v.findViewById(R.id.message_content);
- message_layout.setGravity(Gravity.RIGHT);
- }
-
- deleteChatBubble.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
- @Override
- public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
- messagesList.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(messagesList.isItemChecked(position)) {
- deleteChatBubble.setChecked(true);
- } else {
- deleteChatBubble.setChecked(false);
- }
-
- rlayout.addView(v);
- } else {
- if(message.isOutgoing()){
- RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
- layoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
- layoutParams.setMargins(100, 10, 10, 10);
- v.setLayoutParams(layoutParams);
- } else {
- RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
- layoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
- layoutParams.setMargins(10, 10, 100, 10);
- v.setLayoutParams(layoutParams);
- }
- rlayout.addView(v);
- }
- return rlayout;
- }
- }
-
public void initChatRoom(String sipUri) {
LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
LinphoneAddress lAddress = null;
- if(sipUri == null){
+ if (sipUri == null) {
initNewChatConversation();
} else {
try {
@@ -477,7 +367,7 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
}
private void displayMessageList() {
- if(chatRoom != null) {
+ if (chatRoom != null) {
if (adapter != null) {
adapter.refreshHistory();
} else {
@@ -488,7 +378,7 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
}
private void displayChatHeader(LinphoneAddress address) {
- if(contact != null) {
+ if (contact != null) {
contactName.setText(contact.getFullName());
} else if(address != null){
contactName.setText(LinphoneUtils.getAddressDisplayName(address));
@@ -580,6 +470,10 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
if (adapter != null) {
adapter.destroy();
}
+ if (defaultBitmap != null) {
+ defaultBitmap.recycle();
+ defaultBitmap = null;
+ }
super.onDestroy();
}
@@ -618,7 +512,7 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
String draft = getArguments().getString("messageDraft");
message.setText(draft);
- if(!newChatConversation) {
+ if (!newChatConversation) {
initChatRoom(sipUri);
searchContactField.setVisibility(View.GONE);
resultContactsSearch.setVisibility(View.GONE);
@@ -626,10 +520,10 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
}
}
- private void selectAllList(boolean isSelectAll){
+ private void selectAllList(boolean isSelectAll) {
int size = messagesList.getAdapter().getCount();
- for(int i=0; i history;
+ Context context;
+
+ public ChatMessageAdapter(Context c) {
+ context = c;
+ history = new ArrayList();
+ refreshHistory();
+ }
+
+ public void destroy() {
+ if (history != null) {
+ history.clear();
+ }
+ }
+
+ public void refreshHistory() {
+ history.clear();
+ LinphoneChatMessage[] messages = chatRoom.getHistory();
+ history.addAll(Arrays.asList(messages));
+ notifyDataSetChanged();
+ }
+
+ public void addMessage(LinphoneChatMessage message) {
+ history.add(message);
+ notifyDataSetChanged();
+ messagesList.setSelection(getCount() - 1);
+ }
+
+ @Override
+ public int getCount() {
+ return history.size();
+ }
+
+ @Override
+ public LinphoneChatMessage getItem(int position) {
+ return history.get(position);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return history.get(position).getStorageId();
+ }
+
+ @Override
+ public View getView(final int position, View convertView, ViewGroup parent) {
+ final LinphoneChatMessage message = history.get(position);
+ View view = null;
+ final ViewHolder holder;
+ boolean sameMessage = false;
+
+ if (convertView != null) {
+ view = convertView;
+ holder = (ViewHolder) view.getTag();
+ LinphoneManager.removeListener(holder);
+ } else {
+ view = LayoutInflater.from(context).inflate(R.layout.chat_bubble, null);
+ holder = new ViewHolder(view);
+ view.setTag(holder);
+ }
+
+ if (holder.id == message.getStorageId()) {
+ sameMessage = true;
+ } else {
+ holder.id = message.getStorageId();
+ }
+ view.setId(holder.id);
+ registerForContextMenu(view);
+
+ LinphoneChatMessage.State status = message.getStatus();
+ String externalBodyUrl = message.getExternalBodyUrl();
+ LinphoneContent fileTransferContent = message.getFileTransferInformation();
+
+ holder.delete.setVisibility(View.GONE);
+ holder.messageText.setVisibility(View.GONE);
+ holder.messageImage.setVisibility(View.GONE);
+ holder.fileTransferLayout.setVisibility(View.GONE);
+ holder.fileTransferProgressBar.setProgress(0);
+ holder.fileTransferAction.setEnabled(true);
+ holder.messageStatus.setVisibility(View.INVISIBLE);
+ holder.messageSendingInProgress.setVisibility(View.GONE);
+
+ String displayName = message.getFrom().getDisplayName();
+ if (displayName == null) {
+ displayName = message.getFrom().getUserName();
+ }
+ if (!message.isOutgoing()) {
+ if (contact != null) {
+ if (contact != null && contact.getFullName() != null) {
+ displayName = contact.getFullName();
+ }
+ if (contact.hasPhoto()) {
+ Bitmap photo = contact.getPhoto();
+ if (photo != null) {
+ holder.contactPicture.setImageBitmap(photo);
+ } else {
+ LinphoneUtils.setImagePictureFromUri(getActivity(), holder.contactPicture, contact.getPhotoUri(), contact.getThumbnailUri());
+ }
+ } else {
+ holder.contactPicture.setImageResource(R.drawable.avatar);
+ }
+ } else {
+ holder.contactPicture.setImageResource(R.drawable.avatar);
+ }
+ } else {
+ holder.contactPicture.setImageResource(R.drawable.avatar);
+ }
+ holder.contactName.setText(timestampToHumanDate(context, message.getTime()) + " - " + displayName);
+
+ if (status == LinphoneChatMessage.State.NotDelivered) {
+ holder.messageStatus.setVisibility(View.VISIBLE);
+ holder.messageStatus.setImageResource(R.drawable.chat_message_not_delivered);
+ } else if (status == LinphoneChatMessage.State.InProgress) {
+ holder.messageSendingInProgress.setVisibility(View.VISIBLE);
+ }
+
+ if (externalBodyUrl != null || fileTransferContent != null) {
+ String appData = message.getAppData();
+
+ if (message.isOutgoing() && appData != null) {
+ holder.messageImage.setVisibility(View.VISIBLE);
+ if (!sameMessage) loadBitmap(appData, holder.messageImage);
+
+ if (LinphoneManager.getInstance().getMessageUploadPending() != null && LinphoneManager.getInstance().getMessageUploadPending().getStorageId() == message.getStorageId()) {
+ holder.messageSendingInProgress.setVisibility(View.GONE);
+ holder.fileTransferLayout.setVisibility(View.VISIBLE);
+ LinphoneManager.addListener(holder);
+ }
+ } else {
+ if (appData != null && !LinphoneManager.getInstance().isMessagePending(message) && appData.contains(context.getString(R.string.temp_photo_name_with_date).split("%s")[0])) {
+ appData = null;
+ }
+
+ if (appData == null) {
+ LinphoneManager.addListener(holder);
+ holder.fileTransferLayout.setVisibility(View.VISIBLE);
+ } else {
+ if (LinphoneManager.getInstance().isMessagePending(message)) {
+ LinphoneManager.addListener(holder);
+ holder.fileTransferAction.setEnabled(false);
+ holder.fileTransferLayout.setVisibility(View.VISIBLE);
+ } else {
+ LinphoneManager.removeListener(holder);
+ holder.fileTransferLayout.setVisibility(View.GONE);
+ holder.messageImage.setVisibility(View.VISIBLE);
+ if (!sameMessage) loadBitmap(appData, holder.messageImage);
+ }
+ }
+ }
+ } else {
+ Spanned text = null;
+ String msg = message.getText();
+ if (msg != null) {
+ text = getTextWithHttpLinks(msg);
+ holder.messageText.setText(text);
+ holder.messageText.setMovementMethod(LinkMovementMethod.getInstance());
+ holder.messageText.setVisibility(View.VISIBLE);
+ }
+ }
+
+ if (message.isOutgoing()) {
+ holder.fileTransferAction.setText(getString(R.string.cancel));
+ holder.fileTransferAction.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (LinphoneManager.getInstance().getMessageUploadPending() != null) {
+ holder.fileTransferProgressBar.setVisibility(View.GONE);
+ holder.fileTransferProgressBar.setProgress(0);
+ message.cancelFileTransfer();
+ LinphoneManager.getInstance().setUploadPendingFileMessage(null);
+ }
+ }
+ });
+ } else {
+ holder.fileTransferAction.setText(getString(R.string.accept));
+ holder.fileTransferAction.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (context.getPackageManager().checkPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, context.getPackageName()) == PackageManager.PERMISSION_GRANTED) {
+ v.setEnabled(false);
+ String extension = message.getFileTransferInformation().getSubtype();
+ String filename = context.getString(R.string.temp_photo_name_with_date).replace("%s", String.valueOf(System.currentTimeMillis())) + "." + extension;
+ File file = new File(Environment.getExternalStorageDirectory(), filename);
+ message.setAppData(filename);
+ LinphoneManager.getInstance().addDownloadMessagePending(message);
+ message.setListener(LinphoneManager.getInstance());
+ message.setFileTransferFilepath(file.getPath());
+ message.downloadFile();
+ } else {
+ Log.w("WRITE_EXTERNAL_STORAGE permission not granted, won't be able to store the downloaded file");
+ LinphoneActivity.instance().checkAndRequestExternalStoragePermission();
+ }
+ }
+ });
+ }
+
+ RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
+ if (message.isOutgoing()) {
+ layoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
+ layoutParams.setMargins(100, 10, 10, 10);
+ holder.background.setBackgroundResource(R.drawable.resizable_chat_bubble_outgoing);
+ holder.contactName.setTextAppearance(R.style.font3);
+ holder.fileTransferAction.setTextAppearance(R.style.font15);
+ holder.fileTransferAction.setBackgroundResource(R.drawable.resizable_confirm_delete_button);
+ } else {
+ if (isEditMode) {
+ layoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
+ layoutParams.setMargins(100, 10, 10, 10);
+ } else {
+ layoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
+ layoutParams.setMargins(10, 10, 100, 10);
+ }
+ holder.background.setBackgroundResource(R.drawable.resizable_chat_bubble_incoming);
+ holder.contactName.setTextAppearance(R.style.font9);
+ holder.fileTransferAction.setTextAppearance(R.style.font8);
+ holder.fileTransferAction.setBackgroundResource(R.drawable.resizable_assistant_button);
+ }
+ holder.bubbleLayout.setLayoutParams(layoutParams);
+
+ if (isEditMode) {
+ holder.delete.setVisibility(View.VISIBLE);
+ holder.delete.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
+ messagesList.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 (messagesList.isItemChecked(position)) {
+ holder.delete.setChecked(true);
+ } else {
+ holder.delete.setChecked(false);
+ }
+ }
+
+ return view;
+ }
+
+ private String timestampToHumanDate(Context context, long timestamp) {
+ try {
+ Calendar cal = Calendar.getInstance();
+ cal.setTimeInMillis(timestamp);
+
+ SimpleDateFormat dateFormat;
+ if (isToday(cal)) {
+ dateFormat = new SimpleDateFormat(context.getResources().getString(R.string.today_date_format));
+ } else {
+ dateFormat = new SimpleDateFormat(context.getResources().getString(R.string.messages_date_format));
+ }
+
+ return dateFormat.format(cal.getTime());
+ } catch (NumberFormatException nfe) {
+ return String.valueOf(timestamp);
+ }
+ }
+
+ private boolean isToday(Calendar cal) {
+ return isSameDay(cal, Calendar.getInstance());
+ }
+
+ private boolean isSameDay(Calendar cal1, Calendar cal2) {
+ if (cal1 == null || cal2 == null) {
+ return false;
+ }
+
+ return (cal1.get(Calendar.ERA) == cal2.get(Calendar.ERA) &&
+ cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) &&
+ cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR));
+ }
+
+ private Spanned getTextWithHttpLinks(String text) {
+ if (text.contains("<")) {
+ text = text.replace("<", "<");
+ }
+ if (text.contains(">")) {
+ text = text.replace(">", ">");
+ }
+ if (text.contains("http://")) {
+ int indexHttp = text.indexOf("http://");
+ int indexFinHttp = text.indexOf(" ", indexHttp) == -1 ? text.length() : text.indexOf(" ", indexHttp);
+ String link = text.substring(indexHttp, indexFinHttp);
+ String linkWithoutScheme = link.replace("http://", "");
+ text = text.replaceFirst(link, "" + linkWithoutScheme + "");
+ }
+ if (text.contains("https://")) {
+ int indexHttp = text.indexOf("https://");
+ int indexFinHttp = text.indexOf(" ", indexHttp) == -1 ? text.length() : text.indexOf(" ", indexHttp);
+ String link = text.substring(indexHttp, indexFinHttp);
+ String linkWithoutScheme = link.replace("https://", "");
+ text = text.replaceFirst(link, "" + linkWithoutScheme + "");
+ }
+
+ return Compatibility.fromHtml(text);
+ }
+
+ public void loadBitmap(String path, ImageView imageView) {
+ if (cancelPotentialWork(path, imageView)) {
+ BitmapWorkerTask task = new BitmapWorkerTask(imageView);
+ final AsyncBitmap asyncBitmap = new AsyncBitmap(context.getResources(), defaultBitmap, task);
+ imageView.setImageDrawable(asyncBitmap);
+ task.execute(path);
+ }
+ }
+
+ private class BitmapWorkerTask extends AsyncTask {
+ private final WeakReference imageViewReference;
+ public String path;
+
+ public BitmapWorkerTask(ImageView imageView) {
+ path = null;
+ // Use a WeakReference to ensure the ImageView can be garbage collected
+ imageViewReference = new WeakReference(imageView);
+ }
+
+ // Decode image in background.
+ @Override
+ protected Bitmap doInBackground(String... params) {
+ path = params[0];
+ Bitmap bm = null;
+
+ if (path.startsWith("content")) {
+ try {
+ bm = MediaStore.Images.Media.getBitmap(context.getContentResolver(), Uri.parse(path));
+ } catch (FileNotFoundException e) {
+ Log.e(e);
+ } catch (IOException e) {
+ Log.e(e);
+ }
+ } else {
+ bm = BitmapFactory.decodeFile(path);
+ path = "file://" + path;
+ }
+
+ if (bm != null) {
+ bm = ThumbnailUtils.extractThumbnail(bm, SIZE_MAX, SIZE_MAX);
+ }
+ return bm;
+ }
+
+ // Once complete, see if ImageView is still around and set bitmap.
+ @Override
+ protected void onPostExecute(Bitmap bitmap) {
+ if (isCancelled()) {
+ bitmap = null;
+ }
+
+ if (imageViewReference != null && bitmap != null) {
+ final ImageView imageView = imageViewReference.get();
+ final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
+ if (this == bitmapWorkerTask && imageView != null) {
+ imageView.setImageBitmap(bitmap);
+ imageView.setTag(path);
+ imageView.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setDataAndType(Uri.parse((String)v.getTag()), "image/*");
+ context.startActivity(intent);
+ }
+ });
+ }
+ }
+ }
+ }
+
+ class AsyncBitmap extends BitmapDrawable {
+ private final WeakReference bitmapWorkerTaskReference;
+
+ public AsyncBitmap(Resources res, Bitmap bitmap, BitmapWorkerTask bitmapWorkerTask) {
+ super(res, bitmap);
+ bitmapWorkerTaskReference = new WeakReference(bitmapWorkerTask);
+ }
+
+ public BitmapWorkerTask getBitmapWorkerTask() {
+ return bitmapWorkerTaskReference.get();
+ }
+ }
+
+ private boolean cancelPotentialWork(String path, ImageView imageView) {
+ final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
+
+ if (bitmapWorkerTask != null) {
+ final String bitmapData = bitmapWorkerTask.path;
+ // If bitmapData is not yet set or it differs from the new data
+ if (bitmapData == null || bitmapData != path) {
+ // Cancel previous task
+ bitmapWorkerTask.cancel(true);
+ } else {
+ // The same work is already in progress
+ return false;
+ }
+ }
+ // No task associated with the ImageView, or an existing task was cancelled
+ return true;
+ }
+
+ private BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) {
+ if (imageView != null) {
+ final Drawable drawable = imageView.getDrawable();
+ if (drawable instanceof AsyncBitmap) {
+ final AsyncBitmap asyncDrawable = (AsyncBitmap) drawable;
+ return asyncDrawable.getBitmapWorkerTask();
+ }
+ }
+ return null;
+ }
+ }
+
class SearchContactsListAdapter extends BaseAdapter {
+ private class ViewHolder {
+ public TextView name;
+ public TextView address;
+
+ public ViewHolder(View view) {
+ name = (TextView) view.findViewById(R.id.contact_name);
+ address = (TextView) view.findViewById(R.id.contact_address);
+ }
+ }
+
private List contacts;
private LayoutInflater mInflater;
@@ -1089,24 +1470,26 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
public View getView(int position, View convertView, ViewGroup parent) {
View view = null;
ContactAddress contact;
+ ViewHolder holder = null;
+
do {
contact = getItem(position);
} while (contact == null);
if (convertView != null) {
view = convertView;
+ holder = (ViewHolder) view.getTag();
} else {
view = mInflater.inflate(R.layout.search_contact_cell, parent, false);
+ holder = new ViewHolder(view);
+ view.setTag(holder);
}
final String a = contact.address;
LinphoneContact c = contact.contact;
- TextView name = (TextView) view.findViewById(R.id.contact_name);
- name.setText(c.getFullName());
-
- TextView address = (TextView) view.findViewById(R.id.contact_address);
- address.setText(a);
+ holder.name.setText(c.getFullName());
+ holder.address.setText(a);
view.setOnClickListener(new OnClickListener() {
@Override
diff --git a/src/org/linphone/ChatListFragment.java b/src/org/linphone/ChatListFragment.java
index d978f2ad8..d18c84fdb 100644
--- a/src/org/linphone/ChatListFragment.java
+++ b/src/org/linphone/ChatListFragment.java
@@ -30,6 +30,7 @@ import org.linphone.mediastream.Log;
import android.app.Dialog;
import android.app.Fragment;
+import android.graphics.Bitmap;
import android.graphics.Typeface;
import android.os.Bundle;
import android.view.ContextMenu;
@@ -117,15 +118,16 @@ public class ChatListFragment extends Fragment implements OnClickListener, OnIte
}
}
- private void removeChatsConversation(){
+ private void removeChatsConversation() {
int size = chatList.getAdapter().getCount();
- for(int i=0; i adapter, View view, int position, long id) {
- String sipUri = (String) view.getTag();
+ String sipUri = chatList.getAdapter().getItem(position).toString();
if (LinphoneActivity.isInstanciated() && !isEditMode) {
LinphoneActivity.instance().displayChat(sipUri);
@@ -339,7 +341,24 @@ public class ChatListFragment extends Fragment implements OnClickListener, OnIte
}
class ChatListAdapter extends BaseAdapter {
-
+ private class ViewHolder {
+ public TextView lastMessageView;
+ public TextView date;
+ public TextView displayName;
+ public TextView unreadMessages;
+ public CheckBox select;
+ public ImageView contactPicture;
+
+ public ViewHolder(View view) {
+ lastMessageView = (TextView) view.findViewById(R.id.lastMessage);
+ date = (TextView) view.findViewById(R.id.date);
+ displayName = (TextView) view.findViewById(R.id.sipUri);
+ unreadMessages = (TextView) view.findViewById(R.id.unreadMessages);
+ select = (CheckBox) view.findViewById(R.id.delete_chatroom);
+ contactPicture = (ImageView) view.findViewById(R.id.contact_picture);
+ }
+ }
+
ChatListAdapter() {}
public int getCount() {
@@ -347,7 +366,7 @@ public class ChatListFragment extends Fragment implements OnClickListener, OnIte
}
public Object getItem(int position) {
- return position;
+ return mConversations.get(position);
}
public long getItemId(int position) {
@@ -356,21 +375,23 @@ public class ChatListFragment extends Fragment implements OnClickListener, OnIte
public View getView(final int position, View convertView, ViewGroup parent) {
View view = null;
+ ViewHolder holder = null;
+ String sipUri = mConversations.get(position);
if (convertView != null) {
view = convertView;
+ holder = (ViewHolder) view.getTag();
} else {
view = mInflater.inflate(R.layout.chatlist_cell, parent, false);
+ holder = new ViewHolder(view);
+ view.setTag(holder);
}
-
- String sipUri = mConversations.get(position);
- view.setTag(sipUri);
LinphoneAddress address;
try {
address = LinphoneCoreFactory.instance().createLinphoneAddress(sipUri);
} catch (LinphoneCoreException e) {
- Log.e("Chat view cannot parse address",e);
+ Log.e("Chat view cannot parse address", e);
return view;
}
@@ -378,57 +399,55 @@ public class ChatListFragment extends Fragment implements OnClickListener, OnIte
String message = "";
Long time;
- TextView lastMessageView = (TextView) view.findViewById(R.id.lastMessage);
- TextView date = (TextView) view.findViewById(R.id.date);
- TextView displayName = (TextView) view.findViewById(R.id.sipUri);
- TextView unreadMessages = (TextView) view.findViewById(R.id.unreadMessages);
- CheckBox select = (CheckBox) view.findViewById(R.id.delete_chatroom);
- ImageView contactPicture = (ImageView) view.findViewById(R.id.contact_picture);
-
LinphoneChatRoom chatRoom = LinphoneManager.getLc().getChatRoom(address);
int unreadMessagesCount = chatRoom.getUnreadMessagesCount();
LinphoneChatMessage[] history = chatRoom.getHistory(1);
LinphoneChatMessage msg = history[0];
if(msg.getFileTransferInformation() != null || msg.getExternalBodyUrl() != null || msg.getAppData() != null ){
- lastMessageView.setBackgroundResource(R.drawable.chat_file_message);
+ holder.lastMessageView.setBackgroundResource(R.drawable.chat_file_message);
time = msg.getTime();
- date.setText(LinphoneUtils.timestampToHumanDate(getActivity(),time,getString(R.string.messages_list_date_format)));
- lastMessageView.setText("");
+ holder.date.setText(LinphoneUtils.timestampToHumanDate(getActivity(),time,getString(R.string.messages_list_date_format)));
+ holder.lastMessageView.setText("");
} else if (msg.getText() != null && msg.getText().length() > 0 ){
message = msg.getText();
- lastMessageView.setBackgroundResource(0);
+ holder.lastMessageView.setBackgroundResource(0);
time = msg.getTime();
- date.setText(LinphoneUtils.timestampToHumanDate(getActivity(),time,getString(R.string.messages_list_date_format)));
- lastMessageView.setText(message);
+ holder.date.setText(LinphoneUtils.timestampToHumanDate(getActivity(),time,getString(R.string.messages_list_date_format)));
+ holder.lastMessageView.setText(message);
}
- displayName.setSelected(true); // For animation
- displayName.setText(contact == null ? LinphoneUtils.getAddressDisplayName(address) : contact.getFullName());
+ holder.displayName.setSelected(true); // For animation
+ holder.displayName.setText(contact == null ? LinphoneUtils.getAddressDisplayName(address) : contact.getFullName());
if (contact != null) {
- LinphoneUtils.setImagePictureFromUri(view.getContext(), contactPicture, contact.getPhotoUri(), contact.getThumbnailUri());
+ Bitmap photo = contact.getPhoto();
+ if (photo != null) {
+ holder.contactPicture.setImageBitmap(photo);
+ } else {
+ LinphoneUtils.setImagePictureFromUri(getActivity(), holder.contactPicture, contact.getPhotoUri(), contact.getThumbnailUri());
+ }
} else {
- contactPicture.setImageResource(R.drawable.avatar);
+ holder.contactPicture.setImageResource(R.drawable.avatar);
}
if (unreadMessagesCount > 0) {
- unreadMessages.setVisibility(View.VISIBLE);
- unreadMessages.setText(String.valueOf(unreadMessagesCount));
- if(unreadMessagesCount > 99){
- unreadMessages.setTextSize(12);
+ holder.unreadMessages.setVisibility(View.VISIBLE);
+ holder.unreadMessages.setText(String.valueOf(unreadMessagesCount));
+ if (unreadMessagesCount > 99) {
+ holder.unreadMessages.setTextSize(12);
}
- displayName.setTypeface(null, Typeface.BOLD);
+ holder.displayName.setTypeface(null, Typeface.BOLD);
} else {
- unreadMessages.setVisibility(View.GONE);
- displayName.setTypeface(null, Typeface.NORMAL);
+ holder.unreadMessages.setVisibility(View.GONE);
+ holder.displayName.setTypeface(null, Typeface.NORMAL);
}
if (isEditMode) {
- unreadMessages.setVisibility(View.GONE);
- select.setVisibility(View.VISIBLE);
- select.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ holder.unreadMessages.setVisibility(View.GONE);
+ holder.select.setVisibility(View.VISIBLE);
+ holder.select.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
chatList.setItemChecked(position, b);
@@ -450,13 +469,13 @@ public class ChatListFragment extends Fragment implements OnClickListener, OnIte
}
});
if(chatList.isItemChecked(position)) {
- select.setChecked(true);
+ holder.select.setChecked(true);
} else {
- select.setChecked(false);
+ holder.select.setChecked(false);
}
} else {
if (unreadMessagesCount > 0) {
- unreadMessages.setVisibility(View.VISIBLE);
+ holder.unreadMessages.setVisibility(View.VISIBLE);
}
}
return view;
diff --git a/src/org/linphone/ChatMessage.java b/src/org/linphone/ChatMessage.java
deleted file mode 100644
index 496966499..000000000
--- a/src/org/linphone/ChatMessage.java
+++ /dev/null
@@ -1,117 +0,0 @@
-package org.linphone;
-
-import org.linphone.core.LinphoneChatMessage;
-
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-/*
-ChatMessage.java
-Copyright (C) 2012 Belledonne Communications, Grenoble, France
-
-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 2
-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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-*/
-
-/**
- * @author Sylvain Berfini
- * @deprecated
- */
-public class ChatMessage {
- private String message;
- private String timestamp;
- private String url;
- private boolean incoming;
- private int status;
- private int id;
- private Bitmap image;
- private boolean isRead;
-
- public ChatMessage(int id, String message, byte[] rawImage, String timestamp, boolean incoming, int status, boolean read) {
- super();
- this.id = id;
- this.message = message;
- this.timestamp = timestamp;
- this.incoming = incoming;
- this.status = status;
- this.image = rawImage != null ? BitmapFactory.decodeByteArray(rawImage, 0, rawImage.length) : null;
- this.isRead = read;
- }
-
- public ChatMessage(int id, String message, Bitmap image, String timestamp, boolean incoming, int status, boolean read) {
- super();
- this.id = id;
- this.message = message;
- this.timestamp = timestamp;
- this.incoming = incoming;
- this.status = status;
- this.image = image;
- this.isRead = read;
- }
-
- public int getId() {
- return id;
- }
-
- public String getMessage() {
- return message;
- }
-
- public void setMessage(String message) {
- this.message = message;
- }
-
- public String getTimestamp() {
- return timestamp;
- }
-
- public void setTimestamp(String timestamp) {
- this.timestamp = timestamp;
- }
-
- public boolean isIncoming() {
- return incoming;
- }
-
- public void setIncoming(boolean incoming) {
- this.incoming = incoming;
- }
-
- public void setStatus(int status) {
- this.status = status;
- }
-
- public LinphoneChatMessage.State getStatus() {
- return LinphoneChatMessage.State.fromInt(status);
- }
-
- public Bitmap getImage() {
- return image;
- }
-
- public boolean isRead() {
- return isRead;
- }
-
- public String getUrl() {
- return url;
- }
-
- public void setUrl(String url) {
- this.url = url;
- }
-
- public String toString() {
- return this.id + " : " + this.message + " (" + this.url + ") @ " + this.timestamp + ", read= " + this.isRead + ", incoming= " + this.incoming + ", status = " + this.status;
- }
-}
diff --git a/src/org/linphone/Contact.java b/src/org/linphone/Contact.java
deleted file mode 100644
index 1a2dd7138..000000000
--- a/src/org/linphone/Contact.java
+++ /dev/null
@@ -1,139 +0,0 @@
-package org.linphone;
-/*
-Contact.java
-Copyright (C) 2012 Belledonne Communications, Grenoble, France
-
-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 2
-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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-*/
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.linphone.compatibility.Compatibility;
-import org.linphone.core.LinphoneAddress;
-import org.linphone.core.LinphoneCore;
-import org.linphone.core.LinphoneFriend;
-
-import android.content.ContentResolver;
-import android.graphics.Bitmap;
-import android.net.Uri;
-
-/**
- * @author Sylvain Berfini
- * @deprecated
- */
-public class Contact implements Serializable {
- private static final long serialVersionUID = 3790717505065723499L;
-
- private String id;
- private String name;
- private transient Uri photoUri;
- private transient Uri thumbnailUri;
- private transient Bitmap photo;
- private List numbersOrAddresses;
- private boolean hasFriends;
- private LinphoneAddress address;
-
- public Contact(String id, String name) {
- super();
- this.id = id;
- this.name = name;
- this.photoUri = null;
- this.thumbnailUri = null;
- this.hasFriends = false;
- this.address = null;
- }
-
- public Contact(String id, LinphoneAddress address) {
- super();
- this.id = id;
- this.name = LinphoneUtils.getAddressDisplayName(address);
- this.photoUri = null;
- this.thumbnailUri = null;
- this.address = address;
-
- }
-
- public Contact(String id, String name, Uri photo, Uri thumbnail) {
- super();
- this.id = id;
- this.name = name;
- this.photoUri = photo;
- this.thumbnailUri = thumbnail;
- this.photo = null;
- this.hasFriends = false;
- this.address = null;
- }
-
- public Contact(String id, String name, Uri photo, Uri thumbnail, Bitmap picture) {
- super();
- this.id = id;
- this.name = name;
- this.photoUri = photo;
- this.thumbnailUri = thumbnail;
- this.photo = picture;
- this.hasFriends = false;
- this.address = null;
- }
-
-
- public boolean hasFriends() {
- return hasFriends;
- }
-
- public String getID() {
- return id;
- }
-
- public String getName() {
- return name;
- }
-
- public LinphoneAddress getLinphoneAddress() {
- return address;
- }
-
- public Uri getPhotoUri() {
- return photoUri;
- }
-
- public Uri getThumbnailUri() {
- return thumbnailUri;
- }
-
- public Bitmap getPhoto() {
- return photo;
- }
-
- public List getNumbersOrAddresses() {
- if (numbersOrAddresses == null)
- numbersOrAddresses = new ArrayList();
- return numbersOrAddresses;
- }
-
- public void refresh(ContentResolver cr) {
- this.numbersOrAddresses = Compatibility.extractContactNumbersAndAddresses(id, cr);
- LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
- if(lc != null && lc.getFriendList() != null) {
- for (LinphoneFriend friend :lc.getFriendList()){
- if (id.equals(friend.getRefKey())) {
- hasFriends = true;
- this.numbersOrAddresses.add(friend.getAddress().asStringUriOnly());
- }
- }
- }
- this.name = Compatibility.refreshContactName(cr, id);
- }
-}
diff --git a/src/org/linphone/ContactDetailsFragment.java b/src/org/linphone/ContactDetailsFragment.java
index e24a0ccdd..1b43f9254 100644
--- a/src/org/linphone/ContactDetailsFragment.java
+++ b/src/org/linphone/ContactDetailsFragment.java
@@ -78,8 +78,9 @@ public class ContactDetailsFragment extends Fragment implements OnClickListener
deleteContact.setOnClickListener(this);
organization = (TextView) view.findViewById(R.id.contactOrganization);
+ boolean isOrgVisible = getResources().getBoolean(R.bool.display_contact_organization);
String org = contact.getOrganization();
- if (org != null && !org.isEmpty()) {
+ if (org != null && !org.isEmpty() && isOrgVisible) {
organization.setText(org);
} else {
organization.setVisibility(View.GONE);
diff --git a/src/org/linphone/ContactEditorFragment.java b/src/org/linphone/ContactEditorFragment.java
index 1d555988a..56d77f816 100644
--- a/src/org/linphone/ContactEditorFragment.java
+++ b/src/org/linphone/ContactEditorFragment.java
@@ -204,9 +204,16 @@ public class ContactEditorFragment extends Fragment {
}
});
+
organization = (EditText) view.findViewById(R.id.contactOrganization);
- if (!isNewContact) {
- organization.setText(contact.getOrganization());
+ boolean isOrgVisible = getResources().getBoolean(R.bool.display_contact_organization);
+ if (!isOrgVisible) {
+ organization.setVisibility(View.GONE);
+ view.findViewById(R.id.contactOrganizationTitle).setVisibility(View.GONE);
+ } else {
+ if (!isNewContact) {
+ organization.setText(contact.getOrganization());
+ }
}
if (!isNewContact) {
diff --git a/src/org/linphone/ContactsListFragment.java b/src/org/linphone/ContactsListFragment.java
index fbc3d8673..4e75ce1d6 100644
--- a/src/org/linphone/ContactsListFragment.java
+++ b/src/org/linphone/ContactsListFragment.java
@@ -30,6 +30,7 @@ import org.linphone.core.PresenceActivityType;
import android.app.Dialog;
import android.app.Fragment;
+import android.graphics.Bitmap;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
@@ -416,6 +417,28 @@ public class ContactsListFragment extends Fragment implements OnClickListener, O
}
class ContactsListAdapter extends BaseAdapter implements SectionIndexer {
+ private class ViewHolder {
+ public CheckBox delete;
+ public ImageView linphoneFriend;
+ public TextView name;
+ public LinearLayout separator;
+ public TextView separatorText;
+ public ImageView contactPicture;
+ public TextView organization;
+ public ImageView friendStatus;
+
+ public ViewHolder(View view) {
+ delete = (CheckBox) view.findViewById(R.id.delete);
+ linphoneFriend = (ImageView) view.findViewById(R.id.friendLinphone);
+ name = (TextView) view.findViewById(R.id.name);
+ separator = (LinearLayout) view.findViewById(R.id.separator);
+ separatorText = (TextView) view.findViewById(R.id.separator_text);
+ contactPicture = (ImageView) view.findViewById(R.id.contact_picture);
+ organization = (TextView) view.findViewById(R.id.contactOrganization);
+ friendStatus = (ImageView) view.findViewById(R.id.friendStatus);
+ }
+ }
+
private List contacts;
String[] sections;
ArrayList sectionsList;
@@ -461,57 +484,57 @@ public class ContactsListFragment extends Fragment implements OnClickListener, O
LinphoneContact contact = (LinphoneContact) getItem(position);
if (contact == null) return null;
+ ViewHolder holder = null;
if (convertView != null) {
view = convertView;
+ holder = (ViewHolder) view.getTag();
} else {
view = mInflater.inflate(R.layout.contact_cell, parent, false);
+ holder = new ViewHolder(view);
+ view.setTag(holder);
}
-
- CheckBox delete = (CheckBox) view.findViewById(R.id.delete);
- ImageView linphoneFriend = (ImageView) view.findViewById(R.id.friendLinphone);
- TextView name = (TextView) view.findViewById(R.id.name);
- name.setText(contact.getFullName());
-
- LinearLayout separator = (LinearLayout) view.findViewById(R.id.separator);
- TextView separatorText = (TextView) view.findViewById(R.id.separator_text);
+ holder.name.setText(contact.getFullName());
+
if (getPositionForSection(getSectionForPosition(position)) != position) {
- separator.setVisibility(View.GONE);
+ holder.separator.setVisibility(View.GONE);
} else {
- separator.setVisibility(View.VISIBLE);
+ holder.separator.setVisibility(View.VISIBLE);
String fullName = contact.getFullName();
if (fullName != null && !fullName.isEmpty()) {
- separatorText.setText(String.valueOf(fullName.charAt(0)));
+ holder.separatorText.setText(String.valueOf(fullName.charAt(0)));
}
}
if (contact.isInLinphoneFriendList()) {
- linphoneFriend.setVisibility(View.VISIBLE);
+ holder.linphoneFriend.setVisibility(View.VISIBLE);
} else {
- linphoneFriend.setVisibility(View.GONE);
+ holder.linphoneFriend.setVisibility(View.GONE);
}
- 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());
+ Bitmap photo = contact.getPhoto();
+ if (photo != null) {
+ holder.contactPicture.setImageBitmap(photo);
+ } else {
+ LinphoneUtils.setImagePictureFromUri(getActivity(), holder.contactPicture, contact.getPhotoUri(), contact.getThumbnailUri());
+ }
} else {
- icon.setImageResource(R.drawable.avatar);
+ holder.contactPicture.setImageResource(R.drawable.avatar);
}
- TextView organization = (TextView) view.findViewById(R.id.contactOrganization);
+ boolean isOrgVisible = getResources().getBoolean(R.bool.display_contact_organization);
String org = contact.getOrganization();
- if (org != null && !org.isEmpty()) {
- organization.setText(org);
- organization.setVisibility(View.VISIBLE);
+ if (org != null && !org.isEmpty() && isOrgVisible) {
+ holder.organization.setText(org);
+ holder.organization.setVisibility(View.VISIBLE);
} else {
- organization.setVisibility(View.GONE);
+ holder.organization.setVisibility(View.GONE);
}
if (isEditMode) {
- delete.setVisibility(View.VISIBLE);
- delete.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ holder.delete.setVisibility(View.VISIBLE);
+ holder.delete.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
contactsList.setItemChecked(position, b);
@@ -533,29 +556,28 @@ public class ContactsListFragment extends Fragment implements OnClickListener, O
}
});
if (contactsList.isItemChecked(position)) {
- delete.setChecked(true);
+ holder.delete.setChecked(true);
} else {
- delete.setChecked(false);
+ holder.delete.setChecked(false);
}
} else {
- delete.setVisibility(View.GONE);
+ holder.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);
+ holder.friendStatus.setVisibility(View.VISIBLE);
PresenceActivityType presenceActivity = friends[0].getPresenceModel().getActivity().getType();
if (presenceActivity == PresenceActivityType.Online) {
- friendStatus.setImageResource(R.drawable.led_connected);
+ holder.friendStatus.setImageResource(R.drawable.led_connected);
} else if (presenceActivity == PresenceActivityType.Busy) {
- friendStatus.setImageResource(R.drawable.led_error);
+ holder.friendStatus.setImageResource(R.drawable.led_error);
} else if (presenceActivity == PresenceActivityType.Away) {
- friendStatus.setImageResource(R.drawable.led_inprogress);
+ holder.friendStatus.setImageResource(R.drawable.led_inprogress);
} else if (presenceActivity == PresenceActivityType.Offline) {
- friendStatus.setImageResource(R.drawable.led_disconnected);
+ holder.friendStatus.setImageResource(R.drawable.led_disconnected);
} else {
- friendStatus.setImageResource(R.drawable.call_quality_indicator_0);
+ holder.friendStatus.setImageResource(R.drawable.call_quality_indicator_0);
}
}
diff --git a/src/org/linphone/ContactsManager.java b/src/org/linphone/ContactsManager.java
index 4cbcdd7eb..b67f1453d 100644
--- a/src/org/linphone/ContactsManager.java
+++ b/src/org/linphone/ContactsManager.java
@@ -21,10 +21,11 @@ package org.linphone;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
import java.util.Locale;
+import java.util.Set;
-import org.linphone.compatibility.Compatibility;
import org.linphone.core.LinphoneAddress;
import org.linphone.core.LinphoneCore;
import org.linphone.core.LinphoneFriend;
@@ -38,11 +39,13 @@ import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
import android.database.Cursor;
+import android.database.MatrixCursor;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import android.provider.ContactsContract;
+import android.provider.ContactsContract.CommonDataKinds;
import android.provider.ContactsContract.Data;
interface ContactsUpdatedListener {
@@ -228,14 +231,13 @@ public class ContactsManager extends ContentObserver {
contactsFetchTask.execute();
}
-
private class ContactsFetchTask extends AsyncTask, List> {
@SuppressWarnings("unchecked")
protected List doInBackground(Void... params) {
List contacts = new ArrayList();
if (hasContactsAccess()) {
- Cursor c = Compatibility.getContactsCursor(contentResolver, null);
+ Cursor c = getContactsCursor(contentResolver);
if (c != null) {
while (c.moveToNext()) {
String id = c.getString(c.getColumnIndex(Data.CONTACT_ID));
@@ -367,4 +369,38 @@ public class ContactsManager extends ContentObserver {
public String getString(int resourceID) {
return context.getString(resourceID);
}
+
+ private Cursor getContactsCursor(ContentResolver cr) {
+ String req = "(" + Data.MIMETYPE + " = '" + CommonDataKinds.Phone.CONTENT_ITEM_TYPE
+ + "' AND " + CommonDataKinds.Phone.NUMBER + " IS NOT NULL "
+ + " OR (" + Data.MIMETYPE + " = '" + CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE
+ + "' AND " + ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS + " IS NOT NULL))";
+ String[] projection = new String[] { Data.CONTACT_ID, Data.DISPLAY_NAME };
+ String query = Data.DISPLAY_NAME + " IS NOT NULL AND (" + req + ")";
+
+ Cursor cursor = cr.query(Data.CONTENT_URI, projection, query, null, " lower(" + Data.DISPLAY_NAME + ") COLLATE UNICODE ASC");
+ if (cursor == null) {
+ return cursor;
+ }
+
+ MatrixCursor result = new MatrixCursor(cursor.getColumnNames());
+ Set groupBy = new HashSet();
+ while (cursor.moveToNext()) {
+ String name = cursor.getString(cursor.getColumnIndex(Data.DISPLAY_NAME));
+ if (!groupBy.contains(name)) {
+ groupBy.add(name);
+ Object[] newRow = new Object[cursor.getColumnCount()];
+
+ int contactID = cursor.getColumnIndex(Data.CONTACT_ID);
+ int displayName = cursor.getColumnIndex(Data.DISPLAY_NAME);
+
+ newRow[contactID] = cursor.getString(contactID);
+ newRow[displayName] = cursor.getString(displayName);
+
+ result.addRow(newRow);
+ }
+ }
+ cursor.close();
+ return result;
+ }
}
diff --git a/src/org/linphone/HistoryListFragment.java b/src/org/linphone/HistoryListFragment.java
index bb148278c..83840f0da 100644
--- a/src/org/linphone/HistoryListFragment.java
+++ b/src/org/linphone/HistoryListFragment.java
@@ -31,6 +31,7 @@ import org.linphone.core.LinphoneCallLog.CallStatus;
import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.Context;
+import android.graphics.Bitmap;
import android.os.Bundle;
import android.app.Fragment;
import android.view.LayoutInflater;
@@ -349,6 +350,22 @@ public class HistoryListFragment extends Fragment implements OnClickListener, On
}
class CallHistoryAdapter extends BaseAdapter {
+ private class ViewHolder {
+ public TextView contact;
+ public ImageView detail;
+ public CheckBox select;
+ public ImageView callDirection;
+ public ImageView contactPicture;
+
+ public ViewHolder(View view) {
+ contact = (TextView) view.findViewById(R.id.sip_uri);
+ detail = (ImageView) view.findViewById(R.id.detail);
+ select = (CheckBox) view.findViewById(R.id.delete);
+ callDirection = (ImageView) view.findViewById(R.id.icon);
+ contactPicture = (ImageView) view.findViewById(R.id.contact_picture);
+ }
+ }
+
CallHistoryAdapter(Context aContext) {
}
@@ -401,23 +418,20 @@ public class HistoryListFragment extends Fragment implements OnClickListener, On
public View getView(final int position, View convertView, ViewGroup parent) {
View view = null;
- ViewHolder holder;
+ ViewHolder holder = null;
+
if (convertView != null) {
view = convertView;
holder = (ViewHolder) view.getTag();
} else {
view = mInflater.inflate(R.layout.history_cell, parent,false);
- holder = new ViewHolder();
- holder.contact = (TextView) view.findViewById(R.id.sip_uri);
- holder.detail = (ImageView) view.findViewById(R.id.detail);
- holder.select = (CheckBox) view.findViewById(R.id.delete);
- holder.callDirection = (ImageView) view.findViewById(R.id.icon);
- holder.contactPicture = (ImageView) view.findViewById(R.id.contact_picture);
+ holder = new ViewHolder(view);
+ view.setTag(holder);
}
final LinphoneCallLog log = mLogs.get(position);
long timestamp = log.getTimestamp();
- final LinphoneAddress address;
+ LinphoneAddress address;
holder.contact.setSelected(true); // For automated horizontal scrolling of long texts
@@ -457,9 +471,18 @@ public class HistoryListFragment extends Fragment implements OnClickListener, On
LinphoneContact c = ContactsManager.getInstance().findContactFromAddress(address);
String displayName = null;
final String sipUri = address.asString();
- if(c != null){
+ if (c != null) {
displayName = c.getFullName();
- LinphoneUtils.setImagePictureFromUri(view.getContext(),holder.contactPicture,c.getPhotoUri(),c.getThumbnailUri());
+ if (c.hasPhoto()) {
+ Bitmap photo = c.getPhoto();
+ if (photo != null) {
+ holder.contactPicture.setImageBitmap(photo);
+ } else {
+ LinphoneUtils.setImagePictureFromUri(getActivity(), holder.contactPicture, c.getPhotoUri(), c.getThumbnailUri());
+ }
+ } else {
+ LinphoneUtils.setImagePictureFromUri(getActivity(), holder.contactPicture, c.getPhotoUri(), c.getThumbnailUri());
+ }
} else {
holder.contactPicture.setImageResource(R.drawable.avatar);
}
@@ -469,7 +492,6 @@ public class HistoryListFragment extends Fragment implements OnClickListener, On
} else {
holder.contact.setText(displayName);
}
- //view.setTag(sipUri);
if (isEditMode) {
holder.select.setVisibility(View.VISIBLE);
@@ -512,16 +534,7 @@ public class HistoryListFragment extends Fragment implements OnClickListener, On
}
});
}
- view.setTag(holder);
return view;
}
}
-
- static class ViewHolder {
- TextView contact;
- ImageView detail;
- CheckBox select;
- ImageView callDirection;
- ImageView contactPicture;
- }
}
\ No newline at end of file
diff --git a/src/org/linphone/LinphoneActivity.java b/src/org/linphone/LinphoneActivity.java
index 2514c6350..21386ed85 100644
--- a/src/org/linphone/LinphoneActivity.java
+++ b/src/org/linphone/LinphoneActivity.java
@@ -110,6 +110,7 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta
private static final int PERMISSIONS_REQUEST_CONTACTS = 208;
private static final int PERMISSIONS_RECORD_AUDIO_ECHO_CANCELLER = 209;
private static final int PERMISSIONS_READ_EXTERNAL_STORAGE_DEVICE_RINGTONE = 210;
+ private static final int PERMISSIONS_RECORD_AUDIO_ECHO_TESTER = 211;
private static LinphoneActivity instance;
@@ -1178,7 +1179,7 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta
public void checkAndRequestReadContactsPermission() {
checkAndRequestPermission(Manifest.permission.READ_CONTACTS, PERMISSIONS_REQUEST_CONTACTS);
}
-
+
private boolean willContactsPermissionBeAsked() {
return LinphonePreferences.instance().firstTimeAskingForPermission(Manifest.permission.READ_CONTACTS) || ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_CONTACTS);
}
@@ -1191,6 +1192,10 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta
checkAndRequestPermission(Manifest.permission.RECORD_AUDIO, PERMISSIONS_RECORD_AUDIO_ECHO_CANCELLER);
}
+ public void checkAndRequestRecordAudioPermissionsForEchoTester() {
+ checkAndRequestPermission(Manifest.permission.RECORD_AUDIO, PERMISSIONS_RECORD_AUDIO_ECHO_TESTER);
+ }
+
public void checkAndRequestReadExternalStoragePermissionForDeviceRingtone() {
checkAndRequestPermission(Manifest.permission.READ_EXTERNAL_STORAGE, PERMISSIONS_READ_EXTERNAL_STORAGE_DEVICE_RINGTONE);
}
@@ -1269,6 +1274,10 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta
case PERMISSIONS_READ_EXTERNAL_STORAGE_DEVICE_RINGTONE:
((SettingsFragment) fragment).enableDeviceRingtone(grantResults[0] == PackageManager.PERMISSION_GRANTED);
break;
+ case PERMISSIONS_RECORD_AUDIO_ECHO_TESTER:
+ if (grantResults[0] == PackageManager.PERMISSION_GRANTED)
+ ((SettingsFragment) fragment).startEchoTester();
+ break;
}
}
diff --git a/src/org/linphone/LinphoneContact.java b/src/org/linphone/LinphoneContact.java
index a50ec6fb3..c53310b1f 100644
--- a/src/org/linphone/LinphoneContact.java
+++ b/src/org/linphone/LinphoneContact.java
@@ -18,6 +18,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.linphone;
+import java.io.FileNotFoundException;
+import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
@@ -38,8 +40,10 @@ import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.Cursor;
+import android.graphics.Bitmap;
import android.net.Uri;
import android.provider.ContactsContract;
+import android.provider.MediaStore;
import android.provider.ContactsContract.CommonDataKinds;
public class LinphoneContact implements Serializable, Comparable {
@@ -55,6 +59,7 @@ public class LinphoneContact implements Serializable, Comparable changesToCommit;
private transient ArrayList changesToCommit2;
private boolean hasSipAddress;
+ private Bitmap photoBitmap, thumbnailBitmap;
public LinphoneContact() {
addresses = new ArrayList();
@@ -66,6 +71,19 @@ public class LinphoneContact implements Serializable, Comparable box && ohcodec.getUserData(box) != null)
- ((CheckBoxPreference)ohcodec.getUserData(box)).setSummary(mCodecDownloader.getLicenseMessage());
+ if (ohcodec.getUserDataSize() > box && ohcodec.getUserData(box) != null) {
+ ((CheckBoxPreference) ohcodec.getUserData(box)).setSummary(mCodecDownloader.getLicenseMessage());
+ ((CheckBoxPreference) ohcodec.getUserData(box)).setTitle("OpenH264");
+ }
}
}
});
@@ -688,6 +680,32 @@ public class LinphoneManager implements LinphoneCoreListener, LinphoneChatMessag
Log.e(e, "Cannot start linphone");
}
}
+
+ private void initPushNotificationsService() {
+ try {
+ Class> GCMRegistrar = Class.forName("com.google.android.gcm.GCMRegistrar");
+ GCMRegistrar.getMethod("checkDevice", Context.class).invoke(null, mServiceContext);
+ try {
+ GCMRegistrar.getMethod("checkManifest", Context.class).invoke(null, mServiceContext);
+ } catch (IllegalStateException e) {
+ Log.e("[Push Notification] No receiver found", e);
+ }
+ final String regId = (String)GCMRegistrar.getMethod("getRegistrationId", Context.class).invoke(null, mServiceContext);
+ String newPushSenderID = mServiceContext.getString(R.string.push_sender_id);
+ String currentPushSenderID = LinphonePreferences.instance().getPushNotificationRegistrationID();
+ if (regId.equals("") || currentPushSenderID == null || !currentPushSenderID.equals(newPushSenderID)) {
+ GCMRegistrar.getMethod("register", Context.class, String[].class).invoke(null, mServiceContext, new String[]{newPushSenderID});
+ Log.i("[Push Notification] Storing current sender id = " + newPushSenderID);
+ } else {
+ Log.i("[Push Notification] Already registered with id = " + regId);
+ LinphonePreferences.instance().setPushNotificationRegistrationID(regId);
+ }
+ } catch (java.lang.UnsupportedOperationException e) {
+ Log.i("[Push Notification] Not activated");
+ } catch (Exception e1) {
+ Log.i("[Push Notification] Assuming GCM jar is not provided.");
+ }
+ }
private synchronized void initLiblinphone(LinphoneCore lc) throws LinphoneCoreException {
mLc = lc;
@@ -742,7 +760,7 @@ public class LinphoneManager implements LinphoneCoreListener, LinphoneChatMessag
mLc.migrateCallLogs();
if (mServiceContext.getResources().getBoolean(R.bool.enable_push_id)) {
- Compatibility.initPushNotificationService(mServiceContext);
+ initPushNotificationsService();
}
/*
@@ -1020,7 +1038,16 @@ public class LinphoneManager implements LinphoneCoreListener, LinphoneChatMessag
}
return null;
}
-
+
+ public void setAudioManagerInCallMode() {
+ if (mAudioManager.getMode() == AudioManager.MODE_IN_COMMUNICATION) {
+ Log.w("[AudioManager] already in MODE_IN_COMMUNICATION, skipping...");
+ return;
+ }
+ Log.d("[AudioManager] Mode: MODE_IN_COMMUNICATION");
+ mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
+ }
+
@SuppressLint("Wakelock")
public void callState(final LinphoneCore lc,final LinphoneCall call, final State state, final String message) {
Log.i("New call state [",state,"]");
@@ -1056,7 +1083,7 @@ public class LinphoneManager implements LinphoneCoreListener, LinphoneChatMessag
if (state == State.Connected) {
if (mLc.getCallsNb() == 1) {
requestAudioFocus();
- Compatibility.setAudioManagerInCallMode(mAudioManager);
+ setAudioManagerInCallMode();
}
if (Hacks.needSoftvolume()) {
@@ -1066,7 +1093,7 @@ public class LinphoneManager implements LinphoneCoreListener, LinphoneChatMessag
}
if (state == State.OutgoingEarlyMedia) {
- Compatibility.setAudioManagerInCallMode(mAudioManager);
+ setAudioManagerInCallMode();
}
if (state == State.CallReleased || state == State.Error) {
@@ -1146,7 +1173,7 @@ public class LinphoneManager implements LinphoneCoreListener, LinphoneChatMessag
public void startEcCalibration(LinphoneCoreListener l) throws LinphoneCoreException {
routeAudioToSpeaker();
- Compatibility.setAudioManagerInCallMode((AudioManager)getContext().getSystemService(Context.AUDIO_SERVICE));
+ setAudioManagerInCallMode();
Log.i("Set audio mode on 'Voice Communication'");
int oldVolume = mAudioManager.getStreamVolume(STREAM_VOICE_CALL);
int maxVolume = mAudioManager.getStreamMaxVolume(STREAM_VOICE_CALL);
@@ -1155,6 +1182,42 @@ public class LinphoneManager implements LinphoneCoreListener, LinphoneChatMessag
mAudioManager.setStreamVolume(STREAM_VOICE_CALL, oldVolume, 0);
}
+ public int startEchoTester() throws LinphoneCoreException {
+ routeAudioToSpeaker();
+ setAudioManagerInCallMode();
+ Log.i("Set audio mode on 'Voice Communication'");
+ int oldVolume = mAudioManager.getStreamVolume(STREAM_VOICE_CALL);
+ int maxVolume = mAudioManager.getStreamMaxVolume(STREAM_VOICE_CALL);
+ int sampleRate = 0;
+ mAudioManager.setStreamVolume(STREAM_VOICE_CALL, maxVolume, 0);
+ String sampleRateProperty = mAudioManager.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE);
+ sampleRate = Integer.parseInt(sampleRateProperty);
+ int status = mLc.startEchoTester(sampleRate);
+ if (status > 0)
+ echoTesterIsRunning = true;
+ else {
+ echoTesterIsRunning = false;
+ routeAudioToReceiver();
+ mAudioManager.setStreamVolume(STREAM_VOICE_CALL, oldVolume, 0);
+ ((AudioManager)getContext().getSystemService(Context.AUDIO_SERVICE)).setMode(AudioManager.MODE_NORMAL);
+ Log.i("Set audio mode on 'Normal'");
+ }
+ return status;
+ }
+
+ public int stopEchoTester() throws LinphoneCoreException {
+ echoTesterIsRunning = false;
+ int status = mLc.stopEchoTester();
+ routeAudioToReceiver();
+ ((AudioManager)getContext().getSystemService(Context.AUDIO_SERVICE)).setMode(AudioManager.MODE_NORMAL);
+ Log.i("Set audio mode on 'Normal'");
+ return status;
+ }
+
+ public boolean getEchoTesterStatus() {
+ return echoTesterIsRunning;
+ }
+
private boolean isRinging;
private void requestAudioFocus(){
@@ -1328,88 +1391,6 @@ public class LinphoneManager implements LinphoneCoreListener, LinphoneChatMessag
mAudioManager.adjustStreamVolume(LINPHONE_VOLUME_STREAM, i < 0 ? AudioManager.ADJUST_LOWER : AudioManager.ADJUST_RAISE, AudioManager.FLAG_SHOW_UI);
}
- public static Boolean isProximitySensorNearby(final SensorEvent event) {
- float threshold = 4.001f; // <= 4 cm is near
-
- final float distanceInCm = event.values[0];
- final float maxDistance = event.sensor.getMaximumRange();
- Log.d("Proximity sensor report [",distanceInCm,"] , for max range [",maxDistance,"]");
-
- if (maxDistance <= threshold) {
- // Case binary 0/1 and short sensors
- threshold = maxDistance;
- }
-
- return distanceInCm < threshold;
- }
-
- private static boolean sLastProximitySensorValueNearby;
- private static Set sProximityDependentActivities = new HashSet();
- private static SensorEventListener sProximitySensorListener = new SensorEventListener() {
- @Override
- public void onSensorChanged(SensorEvent event) {
- if (event.timestamp == 0) return; //just ignoring for nexus 1
- sLastProximitySensorValueNearby = isProximitySensorNearby(event);
- proximityNearbyChanged();
- }
- @Override
- public void onAccuracyChanged(Sensor sensor, int accuracy) {}
- };
-
-
- private static void simulateProximitySensorNearby(Activity activity, boolean nearby) {
- final Window window = activity.getWindow();
- WindowManager.LayoutParams params = window.getAttributes();
- View view = ((ViewGroup) window.getDecorView().findViewById(android.R.id.content)).getChildAt(0);
- if (nearby) {
- params.screenBrightness = 0.1f;
- view.setVisibility(View.INVISIBLE);
- Compatibility.hideNavigationBar(activity);
- } else {
- params.screenBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE;
- view.setVisibility(View.VISIBLE);
- Compatibility.showNavigationBar(activity);
- }
- window.setAttributes(params);
- }
-
- private static void proximityNearbyChanged() {
- boolean nearby = sLastProximitySensorValueNearby;
- for (Activity activity : sProximityDependentActivities) {
- simulateProximitySensorNearby(activity, nearby);
- }
- }
-
- public static synchronized void startProximitySensorForActivity(Activity activity) {
- if (sProximityDependentActivities.contains(activity)) {
- Log.i("proximity sensor already active for " + activity.getLocalClassName());
- return;
- }
- if (sProximityDependentActivities.isEmpty()) {
- SensorManager sm = (SensorManager) activity.getSystemService(Context.SENSOR_SERVICE);
- Sensor s = sm.getDefaultSensor(Sensor.TYPE_PROXIMITY);
- if (s != null) {
- sm.registerListener(sProximitySensorListener,s,SensorManager.SENSOR_DELAY_UI);
- Log.i("Proximity sensor detected, registering");
- }
- } else if (sLastProximitySensorValueNearby){
- simulateProximitySensorNearby(activity, true);
- }
-
- sProximityDependentActivities.add(activity);
- }
-
- public static synchronized void stopProximitySensorForActivity(Activity activity) {
- sProximityDependentActivities.remove(activity);
- simulateProximitySensorNearby(activity, false);
- if (sProximityDependentActivities.isEmpty()) {
- SensorManager sm = (SensorManager) activity.getSystemService(Context.SENSOR_SERVICE);
- sm.unregisterListener(sProximitySensorListener);
- sLastProximitySensorValueNearby = false;
- }
- }
-
-
public static synchronized LinphoneCore getLcIfManagerNotDestroyedOrNull() {
if (sExited || instance == null) {
// Can occur if the UI thread play a posted event but in the meantime the LinphoneManager was destroyed
diff --git a/src/org/linphone/LinphoneUtils.java b/src/org/linphone/LinphoneUtils.java
index 510f7fdfa..76b8afcce 100644
--- a/src/org/linphone/LinphoneUtils.java
+++ b/src/org/linphone/LinphoneUtils.java
@@ -431,7 +431,7 @@ public final class LinphoneUtils {
StringBuilder sb = new StringBuilder();
try {
- p = Runtime.getRuntime().exec(new String[] { "logcat", "-d", "|", "grep", "`adb shell ps | grep org.linphone | cut -c10-15`" });
+ p = Runtime.getRuntime().exec(new String[] { "logcat", "-d", "|", "grep", "`adb shell ps | grep " + context.getPackageName() + " | cut -c10-15`" });
br = new BufferedReader(new InputStreamReader(p.getInputStream()), 2048);
String line;
diff --git a/src/org/linphone/OpenGLESDisplay.java b/src/org/linphone/OpenGLESDisplay.java
deleted file mode 100644
index 358667874..000000000
--- a/src/org/linphone/OpenGLESDisplay.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package org.linphone;
-
-public class OpenGLESDisplay {
- public static native void init(int ptr, int width, int height);
- public static native void render(int ptr);
-}
diff --git a/src/org/linphone/SettingsFragment.java b/src/org/linphone/SettingsFragment.java
index d7a9914dc..3b5d90324 100644
--- a/src/org/linphone/SettingsFragment.java
+++ b/src/org/linphone/SettingsFragment.java
@@ -48,6 +48,7 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.media.AudioManager;
+import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.preference.CheckBoxPreference;
@@ -58,6 +59,7 @@ import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceCategory;
import android.preference.PreferenceScreen;
+import android.provider.Settings;
/**
* @author Sylvain Berfini
@@ -611,10 +613,52 @@ public class SettingsFragment extends PreferencesListFragment {
return true;
}
});
+
+ findPreference(getString(R.string.pref_echo_tester_key)).setOnPreferenceClickListener(new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ synchronized (SettingsFragment.this) {
+ int recordAudio = getActivity().getPackageManager().checkPermission(Manifest.permission.RECORD_AUDIO, getActivity().getPackageName());
+ if (recordAudio == PackageManager.PERMISSION_GRANTED) {
+ if (LinphoneManager.getInstance().getEchoTesterStatus())
+ stopEchoTester();
+ else
+ startEchoTester();
+ } else {
+ LinphoneActivity.instance().checkAndRequestRecordAudioPermissionsForEchoTester();
+ }
+ }
+ return true;
+ }
+ });
+ }
+
+ public void startEchoTester() {
+ Preference preference = findPreference(getString(R.string.pref_echo_tester_key));
+ try {
+ if (LinphoneManager.getInstance().startEchoTester() > 0) {
+ preference.setSummary("Is running");
+ }
+ } catch (LinphoneCoreException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void stopEchoTester() {
+ Preference preference = findPreference(getString(R.string.pref_echo_tester_key));
+ try {
+ if (LinphoneManager.getInstance().stopEchoTester() > 0) {
+ preference.setSummary("Is stopped");
+ }
+ } catch (LinphoneCoreException e) {
+ e.printStackTrace();
+ }
}
public void startEchoCancellerCalibration() {
try {
+ if (LinphoneManager.getInstance().getEchoTesterStatus())
+ stopEchoTester();
LinphoneManager.getInstance().startEcCalibration(mListener);
} catch (LinphoneCoreException e) {
Log.e(e);
@@ -642,7 +686,9 @@ public class SettingsFragment extends PreferencesListFragment {
codecs.removeAll();
LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
+
final OpenH264DownloadHelper mCodecDownloader = LinphoneManager.getInstance().getOpenH264DownloadHelper();
+
for (final PayloadType pt : lc.getVideoCodecs()) {
final CheckBoxPreference codec = new CheckBoxPreference(getActivity());
codec.setTitle(pt.getMime());
@@ -659,8 +705,10 @@ public class SettingsFragment extends PreferencesListFragment {
}
}
}
- if (pt.getMime().equals("H264") && mCodecDownloader.isCodecFound())
+ if (pt.getMime().equals("H264") && mCodecDownloader.isCodecFound()) {
codec.setSummary(mCodecDownloader.getLicenseMessage());
+ codec.setTitle("OpenH264");
+ }
codec.setChecked(lc.isPayloadTypeEnabled(pt));
codec.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@@ -670,9 +718,9 @@ public class SettingsFragment extends PreferencesListFragment {
try {
if (enable && Version.getCpuAbis().contains("armeabi-v7a") && !Version.getCpuAbis().contains("x86")
&& pt.getMime().equals("H264") && !mCodecDownloader.isCodecFound()) {
- LinphoneManager.getInstance().getOpenH264DownloadHelper().setOpenH264HelperListener(LinphoneManager.getInstance().getOpenH264HelperListener());
- LinphoneManager.getInstance().getOpenH264DownloadHelper().setUserData(0,LinphoneManager.getInstance().getContext());
- LinphoneManager.getInstance().getOpenH264DownloadHelper().setUserData(1,codec);
+ mCodecDownloader.setOpenH264HelperListener(LinphoneManager.getInstance().getOpenH264HelperListener());
+ mCodecDownloader.setUserData(0,LinphoneManager.getInstance().getContext());
+ mCodecDownloader.setUserData(1,codec);
AlertDialog.Builder builder = new AlertDialog.Builder(LinphoneManager.getInstance().getContext());
builder.setCancelable(false);
@@ -702,7 +750,6 @@ public class SettingsFragment extends PreferencesListFragment {
codecs.addPreference(codec);
}
-
((CheckBoxPreference) findPreference(getString(R.string.pref_video_enable_key))).setChecked(mPrefs.isVideoEnabled());
((CheckBoxPreference) findPreference(getString(R.string.pref_video_use_front_camera_key))).setChecked(mPrefs.useFrontCam());
((CheckBoxPreference) findPreference(getString(R.string.pref_video_initiate_call_with_video_key))).setChecked(mPrefs.shouldInitiateVideoCall());
@@ -1146,6 +1193,24 @@ public class SettingsFragment extends PreferencesListFragment {
return true;
}
});
+
+ findPreference(getString(R.string.pref_android_app_settings_key)).setOnPreferenceClickListener(new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ synchronized (SettingsFragment.this) {
+ Context context = SettingsFragment.this.getActivity();
+ Intent i = new Intent();
+ i.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
+ i.addCategory(Intent.CATEGORY_DEFAULT);
+ i.setData(Uri.parse("package:" + context.getPackageName()));
+ i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ i.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
+ i.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ context.startActivity(i);
+ }
+ return true;
+ }
+ });
findPreference(getString(R.string.pref_display_name_key)).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@Override
@@ -1182,9 +1247,11 @@ public class SettingsFragment extends PreferencesListFragment {
}
}
-
+
@Override
public void onPause() {
+ if (LinphoneManager.getInstance().getEchoTesterStatus())
+ stopEchoTester();
LinphoneActivity.instance().hideTopBar();
super.onPause();
}
diff --git a/src/org/linphone/StatusFragment.java b/src/org/linphone/StatusFragment.java
index 64a842dc5..cfc8ffa0a 100644
--- a/src/org/linphone/StatusFragment.java
+++ b/src/org/linphone/StatusFragment.java
@@ -478,7 +478,10 @@ public class StatusFragment extends Fragment {
PayloadType payloadAudio = params.getUsedAudioCodec();
PayloadType payloadVideo = params.getUsedVideoCodec();
if (payloadVideo != null && payloadAudio != null) {
- codec.setText(payloadVideo.getMime() + " / " + payloadAudio.getMime() + (payloadAudio.getRate() / 1000));
+ String videoMime = payloadVideo.getMime();
+ if (payloadVideo.getMime().equals("H264") && LinphoneManager.getInstance().getOpenH264DownloadHelper().isCodecFound())
+ videoMime = "OpenH264";
+ codec.setText(videoMime + " / " + payloadAudio.getMime() + (payloadAudio.getRate() / 1000));
}
dl.setText(String.valueOf((int) videoStats.getDownloadBandwidth()) + " / " + (int) audioStats.getDownloadBandwidth() + " kbits/s");
ul.setText(String.valueOf((int) videoStats.getUploadBandwidth()) + " / " + (int) audioStats.getUploadBandwidth() + " kbits/s");
diff --git a/src/org/linphone/assistant/CodecDownloaderFragment.java b/src/org/linphone/assistant/CodecDownloaderFragment.java
index 496dc3892..deb58390a 100644
--- a/src/org/linphone/assistant/CodecDownloaderFragment.java
+++ b/src/org/linphone/assistant/CodecDownloaderFragment.java
@@ -19,6 +19,13 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+import org.linphone.LinphoneManager;
+import org.linphone.R;
+import org.linphone.core.LinphoneCoreException;
+import org.linphone.core.OpenH264DownloadHelperListener;
+import org.linphone.core.PayloadType;
+import org.linphone.tools.OpenH264DownloadHelper;
+
import android.app.Fragment;
import android.os.Bundle;
import android.os.Handler;
@@ -29,15 +36,6 @@ import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
-import org.linphone.LinphoneActivity;
-import org.linphone.LinphoneManager;
-import org.linphone.R;
-import org.linphone.core.LinphoneCoreFactory;
-import org.linphone.core.OpenH264DownloadHelperListener;
-import org.linphone.core.LinphoneCoreException;
-import org.linphone.core.PayloadType;
-import org.linphone.tools.OpenH264DownloadHelper;
-
/**
* @author Erwan CROZE
*/
diff --git a/src/org/linphone/assistant/LinphoneLoginFragment.java b/src/org/linphone/assistant/LinphoneLoginFragment.java
index e606e00c5..e889336b1 100644
--- a/src/org/linphone/assistant/LinphoneLoginFragment.java
+++ b/src/org/linphone/assistant/LinphoneLoginFragment.java
@@ -18,11 +18,11 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import org.linphone.R;
+import org.linphone.compatibility.Compatibility;
import android.app.Fragment;
import android.os.Bundle;
import android.text.Editable;
-import android.text.Html;
import android.text.TextWatcher;
import android.text.method.LinkMovementMethod;
import android.view.LayoutInflater;
@@ -53,7 +53,7 @@ public class LinphoneLoginFragment extends Fragment implements OnClickListener,
password = (EditText) view.findViewById(R.id.assistant_password);
password.addTextChangedListener(this);
forgotPassword = (TextView) view.findViewById(R.id.forgot_password);
- forgotPassword.setText(Html.fromHtml(""+ getString(R.string.forgot_password) + ""));
+ forgotPassword.setText(Compatibility.fromHtml(""+ getString(R.string.forgot_password) + ""));
forgotPassword.setMovementMethod(LinkMovementMethod.getInstance());
displayName = (EditText) view.findViewById(R.id.assistant_display_name);
apply = (Button) view.findViewById(R.id.assistant_apply);
diff --git a/src/org/linphone/compatibility/ApiEightPlus.java b/src/org/linphone/compatibility/ApiEightPlus.java
deleted file mode 100644
index 30f5a78fb..000000000
--- a/src/org/linphone/compatibility/ApiEightPlus.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package org.linphone.compatibility;
-
-import org.linphone.LinphonePreferences;
-import org.linphone.R;
-import org.linphone.mediastream.Log;
-
-import android.annotation.TargetApi;
-import android.content.Context;
-import android.media.AudioManager;
-
-/*
-ApiEightPlus.java
-Copyright (C) 2012 Belledonne Communications, Grenoble, France
-
-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 2
-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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-/**
- * @author Sylvain Berfini
- */
-
-@TargetApi(8)
-public class ApiEightPlus {
-
- public static void initPushNotificationService(Context context) {
- try {
- Class> GCMRegistrar = Class.forName("com.google.android.gcm.GCMRegistrar");
- // Starting the push notification service
- GCMRegistrar.getMethod("checkDevice", Context.class).invoke(null, context);
- try {
- GCMRegistrar.getMethod("checkManifest", Context.class).invoke(null, context);
- } catch (IllegalStateException e){
- Log.e("Push notification: No receiver found",e);
- }
- final String regId = (String)GCMRegistrar.getMethod("getRegistrationId", Context.class).invoke(null, context);
- String newPushSenderID = context.getString(R.string.push_sender_id);
- String currentPushSenderID = LinphonePreferences.instance().getPushNotificationRegistrationID();
- if (regId.equals("") || currentPushSenderID == null || !currentPushSenderID.equals(newPushSenderID)) {
- GCMRegistrar.getMethod("register", Context.class, String[].class).invoke(null, context, new String[]{newPushSenderID});
- Log.d("Push Notification: storing current sender id = " + newPushSenderID);
- } else {
- Log.d("Push Notification: already registered with id = " + regId);
- LinphonePreferences.instance().setPushNotificationRegistrationID(regId);
- }
- } catch (java.lang.UnsupportedOperationException e) {
- Log.i("Push Notification: not activated");
- } catch (Exception e1) {
- //assume the jar is not provided
- Log.i("Push Notification: assuming GCM jar is not provided.");
- }
- }
-
- @SuppressWarnings("deprecation")
- public static String getAudioManagerEventForBluetoothConnectionStateChangedEvent() {
- return AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED;
- }
-}
\ No newline at end of file
diff --git a/src/org/linphone/compatibility/ApiElevenPlus.java b/src/org/linphone/compatibility/ApiElevenPlus.java
index d763c5221..7b30e5581 100644
--- a/src/org/linphone/compatibility/ApiElevenPlus.java
+++ b/src/org/linphone/compatibility/ApiElevenPlus.java
@@ -3,19 +3,15 @@ package org.linphone.compatibility;
import java.util.ArrayList;
import org.linphone.R;
-import org.linphone.mediastream.Log;
import android.annotation.TargetApi;
import android.app.Notification;
import android.app.PendingIntent;
-import android.content.ClipData;
-import android.content.ClipboardManager;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
-import android.media.AudioManager;
import android.net.Uri;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.SipAddress;
@@ -119,21 +115,6 @@ public class ApiElevenPlus {
return notif;
}
-
- public static void copyTextToClipboard(Context context, String msg) {
- ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
- ClipData clip = android.content.ClipData.newPlainText("Message", msg);
- clipboard.setPrimaryClip(clip);
- }
-
- public static void setAudioManagerInCallMode(AudioManager manager) {
- if (manager.getMode() == AudioManager.MODE_IN_COMMUNICATION) {
- Log.w("---AudioManager: already in MODE_IN_COMMUNICATION, skipping...");
- return;
- }
- Log.d("---AudioManager: set mode to MODE_IN_COMMUNICATION");
- manager.setMode(AudioManager.MODE_IN_COMMUNICATION);
- }
public static Intent prepareAddContactIntent(String displayName, String sipUri) {
Intent intent = new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI);
diff --git a/src/org/linphone/compatibility/ApiFivePlus.java b/src/org/linphone/compatibility/ApiFivePlus.java
deleted file mode 100644
index 7adc28c1e..000000000
--- a/src/org/linphone/compatibility/ApiFivePlus.java
+++ /dev/null
@@ -1,406 +0,0 @@
-package org.linphone.compatibility;
-
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import org.linphone.LinphoneContact;
-import org.linphone.R;
-import org.linphone.core.LinphoneAddress;
-
-import android.annotation.TargetApi;
-import android.app.Activity;
-import android.app.Notification;
-import android.app.PendingIntent;
-import android.content.ContentProviderOperation;
-import android.content.ContentResolver;
-import android.content.ContentUris;
-import android.content.Context;
-import android.content.Intent;
-import android.database.Cursor;
-import android.database.MatrixCursor;
-import android.media.AudioManager;
-import android.net.Uri;
-import android.preference.CheckBoxPreference;
-import android.preference.Preference;
-import android.provider.ContactsContract;
-import android.provider.ContactsContract.CommonDataKinds;
-import android.provider.ContactsContract.CommonDataKinds.Phone;
-import android.provider.ContactsContract.Contacts;
-import android.provider.ContactsContract.Data;
-import android.support.v4.app.NotificationCompat;
-import android.text.ClipboardManager;
-import android.text.TextUtils;
-import android.view.ViewTreeObserver;
-import android.view.ViewTreeObserver.OnGlobalLayoutListener;
-
-/*
-ApiFivePlus.java
-Copyright (C) 2012 Belledonne Communications, Grenoble, France
-
-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 2
-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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-*/
-/**
- * @author Sylvain Berfini
- */
-@SuppressWarnings("deprecation")
-@TargetApi(5)
-public class ApiFivePlus {
- public static void overridePendingTransition(Activity activity, int idAnimIn, int idAnimOut) {
- activity.overridePendingTransition(idAnimIn, idAnimOut);
- }
-
- public static Intent prepareAddContactIntent(String displayName, String sipUri) {
- Intent intent = new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI);
- intent.putExtra(ContactsContract.Intents.Insert.NAME, displayName);
-
- // VoIP field not available, we store the address in the IM field
- intent.putExtra(ContactsContract.Intents.Insert.IM_HANDLE, sipUri);
- intent.putExtra(ContactsContract.Intents.Insert.IM_PROTOCOL, "sip");
-
- return intent;
- }
-
- public static Intent prepareEditContactIntent(int id) {
- Intent intent = new Intent(Intent.ACTION_EDIT, Contacts.CONTENT_URI);
- Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, id);
- intent.setData(contactUri);
-
- return intent;
- }
-
- public static Intent prepareEditContactIntentWithSipAddress(int id, String sipUri) {
- Intent intent = new Intent(Intent.ACTION_EDIT, Contacts.CONTENT_URI);
- Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, id);
- intent.setData(contactUri);
-
- // VoIP field not available, we store the address in the IM field
- intent.putExtra(ContactsContract.Intents.Insert.IM_HANDLE, sipUri);
- intent.putExtra(ContactsContract.Intents.Insert.IM_PROTOCOL, "sip");
-
- return intent;
- }
-
- public static List extractContactNumbersAndAddresses(String id, ContentResolver cr) {
- List list = new ArrayList();
-
- Uri uri = Data.CONTENT_URI;
- String[] projection = {ContactsContract.CommonDataKinds.Im.DATA};
-
- // IM addresses
- String selection = new StringBuilder()
- .append(Data.CONTACT_ID).append(" = ? AND ")
- .append(Data.MIMETYPE).append(" = '")
- .append(ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE)
- .append("' AND lower(")
- .append(ContactsContract.CommonDataKinds.Im.CUSTOM_PROTOCOL)
- .append(") = 'sip'")
- .toString();
- Cursor c = cr.query(uri, projection, selection, new String[]{id}, null);
- if (c != null) {
- int nbId = c.getColumnIndex(ContactsContract.CommonDataKinds.Im.DATA);
- while (c.moveToNext()) {
- list.add("sip:" + c.getString(nbId));
- }
- c.close();
- }
-
- // Phone Numbers
- c = cr.query(Phone.CONTENT_URI, new String[]{Phone.NUMBER}, Phone.CONTACT_ID + " = " + id, null, null);
- if (c != null) {
- while (c.moveToNext()) {
- String number = c.getString(c.getColumnIndex(Phone.NUMBER));
- list.add(number);
- }
- c.close();
- }
-
- return list;
- }
-
- public static Cursor getContactsCursor(ContentResolver cr, List ids) {
- String req = Data.MIMETYPE + " = '" + CommonDataKinds.Phone.CONTENT_ITEM_TYPE
- + "' AND " + CommonDataKinds.Phone.NUMBER + " IS NOT NULL";
-
- req += " OR (" + Contacts.Data.MIMETYPE + " = '" + CommonDataKinds.Im.CONTENT_ITEM_TYPE
- + "' AND lower(" + CommonDataKinds.Im.CUSTOM_PROTOCOL + ") = 'sip')";
-
- if(ids != null){
- String s = TextUtils.join(",", ids);
- req += " OR (" + Data.CONTACT_ID + " IN (" + s + "))";
- }
-
- return getGeneralContactCursor(cr, req, true);
- }
-
- public static Cursor getSIPContactsCursor(ContentResolver cr, List ids) {
- String req = null;
- req = Contacts.Data.MIMETYPE + " = '" + CommonDataKinds.Im.CONTENT_ITEM_TYPE
- + "' AND lower(" + CommonDataKinds.Im.CUSTOM_PROTOCOL + ") = 'sip'";
-
- if(ids != null){
- String s = TextUtils.join(",", ids);
- req += " OR (" + Data.CONTACT_ID + " IN (" + s + "))";
- }
-
- return getGeneralContactCursor(cr, req, true);
- }
-
- private static Cursor getSIPContactCursor(ContentResolver cr, String id) {
- String req = null;
- req = Contacts.Data.MIMETYPE + " = '" + CommonDataKinds.Im.CONTENT_ITEM_TYPE
- + " AND lower(" + CommonDataKinds.Im.CUSTOM_PROTOCOL + ") = 'sip' AND "
- + android.provider.ContactsContract.CommonDataKinds.Im.DATA + " LIKE '" + id + "'";
-
- return getGeneralContactCursor(cr, req, false);
- }
-
- public static Cursor getGeneralContactCursor(ContentResolver cr, String select, boolean shouldGroupBy) {
- String[] projection = new String[] { Data.CONTACT_ID, Data.DISPLAY_NAME };
- String query;
-
- query = Data.DISPLAY_NAME + " IS NOT NULL AND (" + select + ")";
-
- Cursor cursor = cr.query(Data.CONTENT_URI, projection, query, null, " lower(" + Data.DISPLAY_NAME + ") COLLATE UNICODE ASC");
-
- if (!shouldGroupBy || cursor == null) {
- return cursor;
- }
-
- MatrixCursor result = new MatrixCursor(cursor.getColumnNames());
- Set groupBy = new HashSet();
- while (cursor.moveToNext()) {
- String name = cursor.getString(getCursorDisplayNameColumnIndex(cursor));
- if (!groupBy.contains(name)) {
- groupBy.add(name);
- Object[] newRow = new Object[cursor.getColumnCount()];
-
- int contactID = cursor.getColumnIndex(Data.CONTACT_ID);
- int displayName = cursor.getColumnIndex(Data.DISPLAY_NAME);
-
- newRow[contactID] = cursor.getString(contactID);
- newRow[displayName] = cursor.getString(displayName);
-
- result.addRow(newRow);
- }
- }
- cursor.close();
- return result;
- }
-
- public static int getCursorDisplayNameColumnIndex(Cursor cursor) {
- return cursor.getColumnIndex(Data.DISPLAY_NAME);
- }
-
- public static LinphoneContact getContact(ContentResolver cr, Cursor cursor, int position) {
- try {
- if(cursor != null) {
- cursor.moveToFirst();
- boolean success = cursor.move(position);
- if (!success)
- return null;
-
- String id = cursor.getString(cursor.getColumnIndex(Data.CONTACT_ID));
- String name = getContactDisplayName(cursor);
- Uri thumbnail = getContactPictureUri(id);
- Uri photo = getContactPhotoUri(id);
- InputStream input = getContactPictureInputStream(cr, id);
-
- LinphoneContact contact = new LinphoneContact();
- contact.setAndroidId(id);
- contact.setFullName(name);
- if (input != null) {
- contact.setPhotoUri(photo);
- contact.setThumbnailUri(thumbnail);
- }
-
- return contact;
- } else {
- return null;
- }
- } catch (Exception e) {
-
- }
- return null;
- }
-
- public static InputStream getContactPictureInputStream(ContentResolver cr, String id) {
- Uri person = ContentUris.withAppendedId(Contacts.CONTENT_URI, Long.parseLong(id));
- return Contacts.openContactPhotoInputStream(cr, person);
- }
-
- private static String getContactDisplayName(Cursor cursor) {
- return cursor.getString(cursor.getColumnIndex(Data.DISPLAY_NAME));
- }
-
- private static Uri getContactPictureUri(String id) {
- Uri person = ContentUris.withAppendedId(Contacts.CONTENT_URI, Long.parseLong(id));
- return Uri.withAppendedPath(person, Contacts.Photo.CONTENT_DIRECTORY);
- }
-
- private static Uri getContactPhotoUri(String id) {
- Uri person = ContentUris.withAppendedId(Contacts.CONTENT_URI, Long.parseLong(id));
- return Uri.withAppendedPath(person, Contacts.Photo.DISPLAY_PHOTO);
- }
-
- public static Uri findUriPictureOfContactAndSetDisplayName(LinphoneAddress address, ContentResolver cr) {
- String username = address.getUserName();
- String domain = address.getDomain();
- String sipUri = username + "@" + domain;
-
- Cursor cursor = getSIPContactCursor(cr, sipUri);
- if(cursor != null) {
- LinphoneContact contact = getContact(cr, cursor, 0);
- if (contact != null && contact.getNumbersOrAddresses().contains(sipUri)) {
- address.setDisplayName(contact.getFullName());
- cursor.close();
- return contact.getPhotoUri();
- }
- cursor.close();
- }
- return null;
- }
-
- public static String refreshContactName(ContentResolver cr, String id) {
- Cursor cursor = getGeneralContactCursor(cr, Data.CONTACT_ID + " = '" + id + "'", false);
- if (cursor != null && cursor.moveToFirst()) {
- String contactDisplayName = getContactDisplayName(cursor);
- cursor.close();
- return contactDisplayName;
- }
- return null;
- }
-
- public static Notification createMessageNotification(Context context, String title, String msg, PendingIntent intent) {
- Notification notif = new Notification();
- notif.icon = R.drawable.topbar_chat_notification;
- notif.iconLevel = 0;
- notif.when = System.currentTimeMillis();
- notif.flags &= Notification.FLAG_ONGOING_EVENT;
-
- notif.defaults |= Notification.DEFAULT_VIBRATE;
- notif.defaults |= Notification.DEFAULT_SOUND;
- notif.defaults |= Notification.DEFAULT_LIGHTS;
-
- return notif;
- }
-
- public static Notification createInCallNotification(Context context, String title, String msg, int iconID, PendingIntent intent) {
- NotificationCompat.Builder notifBuilder = new NotificationCompat.Builder(context)
- .setSmallIcon(iconID)
- .setContentTitle(title)
- .setContentText(msg)
- .setContentIntent(intent);
-
- return notifBuilder.build();
- }
-
- public static void setPreferenceChecked(Preference preference, boolean checked) {
- ((CheckBoxPreference) preference).setChecked(checked);
- }
-
- public static boolean isPreferenceChecked(Preference preference) {
- return ((CheckBoxPreference) preference).isChecked();
- }
-
- public static void copyTextToClipboard(Context context, String msg) {
- ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
- clipboard.setText(msg);
- }
-
- public static void addSipAddressToContact(Context context, ArrayList ops, String sipAddress) {
- ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
- .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
- .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE)
- .withValue(ContactsContract.CommonDataKinds.Im.DATA, sipAddress)
- .withValue(ContactsContract.CommonDataKinds.Im.TYPE, ContactsContract.CommonDataKinds.Im.TYPE_CUSTOM)
- .withValue(ContactsContract.CommonDataKinds.Im.LABEL, context.getString(R.string.addressbook_label))
- .build()
- );
- }
-
- public static void addSipAddressToContact(Context context, ArrayList ops, String sipAddress, String rawContactID) {
- ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
- .withValue(ContactsContract.Data.RAW_CONTACT_ID, rawContactID)
- .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE)
- .withValue(ContactsContract.CommonDataKinds.Im.DATA, sipAddress)
- .withValue(ContactsContract.CommonDataKinds.Im.TYPE, ContactsContract.CommonDataKinds.Im.TYPE_CUSTOM)
- .withValue(ContactsContract.CommonDataKinds.Im.LABEL, context.getString(R.string.addressbook_label))
- .build()
- );
- }
-
- public static void updateSipAddressForContact(ArrayList ops, String oldSipAddress, String newSipAddress, String contactID) {
- String select = ContactsContract.Data.CONTACT_ID + "=? AND "
- + ContactsContract.Data.MIMETYPE + "='" + ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE + "' AND "
- + ContactsContract.CommonDataKinds.Im.DATA + "=?";
- String[] args = new String[] { String.valueOf(contactID), oldSipAddress };
-
- ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
- .withSelection(select, args)
- .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE)
- .withValue(ContactsContract.CommonDataKinds.Im.DATA, newSipAddress)
- .build()
- );
- }
-
- public static void deleteSipAddressFromContact(ArrayList ops, String oldSipAddress, String contactID) {
- String select = ContactsContract.Data.CONTACT_ID + "=? AND "
- + ContactsContract.Data.MIMETYPE + "='" + ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE + "' AND "
- + ContactsContract.CommonDataKinds.Im.DATA + "=?";
- String[] args = new String[] { String.valueOf(contactID), oldSipAddress };
-
- ops.add(ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI)
- .withSelection(select, args)
- .build()
- );
- }
-
- public static void removeGlobalLayoutListener(ViewTreeObserver viewTreeObserver, OnGlobalLayoutListener keyboardListener) {
- viewTreeObserver.removeGlobalOnLayoutListener(keyboardListener);
- }
-
- public static void setAudioManagerInCallMode(AudioManager manager) {
- /* Do not use MODE_IN_CALL, because it is reserved to GSM. This is causing conflicts on audio system resulting in silenced audio.*/
- //manager.setMode(AudioManager.MODE_IN_CALL);
- }
-
- public static Notification createNotification(Context context, String title, String message, int icon, int level, PendingIntent intent, boolean isOngoingEvent) {
- NotificationCompat.Builder notifBuilder = new NotificationCompat.Builder(context)
- .setSmallIcon(icon, level)
- .setContentTitle(title)
- .setContentText(message)
- .setContentIntent(intent);
-
- return notifBuilder.build();
- }
-
- public static Notification createSimpleNotification(Context context, String title, String text, PendingIntent intent) {
- NotificationCompat.Builder notifBuilder = new NotificationCompat.Builder(context)
- .setSmallIcon(R.drawable.linphone_logo)
- .setContentTitle(title)
- .setContentText(text)
- .setContentIntent(intent);
-
- Notification notif = notifBuilder.build();
- notif.defaults |= Notification.DEFAULT_VIBRATE;
- notif.defaults |= Notification.DEFAULT_SOUND;
- notif.defaults |= Notification.DEFAULT_LIGHTS;
-
- return notif;
- }
-}
diff --git a/src/org/linphone/compatibility/ApiFourteenPlus.java b/src/org/linphone/compatibility/ApiFourteenPlus.java
deleted file mode 100644
index df480ad78..000000000
--- a/src/org/linphone/compatibility/ApiFourteenPlus.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.linphone.compatibility;
-
-import android.annotation.TargetApi;
-import android.app.Activity;
-import android.media.AudioManager;
-import android.preference.Preference;
-import android.preference.TwoStatePreference;
-import android.view.View;
-
-/*
-ApiFourteenPlus.java
-Copyright (C) 2012 Belledonne Communications, Grenoble, France
-
-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 2
-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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-*/
-/**
- * @author Sylvain Berfini
- */
-@TargetApi(14)
-public class ApiFourteenPlus {
-
- public static void setPreferenceChecked(Preference preference, boolean checked) {
- ((TwoStatePreference) preference).setChecked(checked);
- }
-
- public static boolean isPreferenceChecked(Preference preference) {
- return ((TwoStatePreference) preference).isChecked();
- }
-
- public static void hideNavigationBar(Activity activity) {
- activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
- }
-
- public static void showNavigationBar(Activity activity) {
- activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
- }
-
- public static String getAudioManagerEventForBluetoothConnectionStateChangedEvent() {
- return AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED;
- }
-}
diff --git a/src/org/linphone/compatibility/ApiNinePlus.java b/src/org/linphone/compatibility/ApiNinePlus.java
deleted file mode 100644
index 313ee4d1a..000000000
--- a/src/org/linphone/compatibility/ApiNinePlus.java
+++ /dev/null
@@ -1,195 +0,0 @@
-package org.linphone.compatibility;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.linphone.LinphoneContact;
-import org.linphone.R;
-import org.linphone.core.LinphoneAddress;
-
-import android.annotation.TargetApi;
-import android.content.ContentProviderOperation;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.database.Cursor;
-import android.net.Uri;
-import android.provider.ContactsContract;
-import android.provider.ContactsContract.CommonDataKinds;
-import android.provider.ContactsContract.CommonDataKinds.Phone;
-import android.provider.ContactsContract.Contacts;
-import android.provider.ContactsContract.Data;
-import android.text.TextUtils;
-
-/*
-ApiNinePlus.java
-Copyright (C) 2012 Belledonne Communications, Grenoble, France
-
-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 2
-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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-*/
-/**
- * @author Sylvain Berfini
- */
-@TargetApi(9)
-public class ApiNinePlus {
-
- public static void addSipAddressToContact(Context context, ArrayList ops, String sipAddress) {
- ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
- .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
- .withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE)
- .withValue(ContactsContract.CommonDataKinds.SipAddress.DATA, sipAddress)
- .withValue(CommonDataKinds.SipAddress.TYPE, CommonDataKinds.SipAddress.TYPE_CUSTOM)
- .withValue(CommonDataKinds.SipAddress.LABEL, context.getString(R.string.addressbook_label))
- .build()
- );
- }
-
- public static void addSipAddressToContact(Context context, ArrayList ops, String sipAddress, String rawContactID) {
- ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
- .withValue(ContactsContract.Data.RAW_CONTACT_ID, rawContactID)
- .withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE)
- .withValue(ContactsContract.CommonDataKinds.SipAddress.DATA, sipAddress)
- .withValue(CommonDataKinds.SipAddress.TYPE, CommonDataKinds.SipAddress.TYPE_CUSTOM)
- .withValue(CommonDataKinds.SipAddress.LABEL, context.getString(R.string.addressbook_label))
- .build()
- );
- }
-
- public static void updateSipAddressForContact(ArrayList ops, String oldSipAddress, String newSipAddress, String contactID) {
- String select = ContactsContract.Data.CONTACT_ID + "=? AND "
- + ContactsContract.Data.MIMETYPE + "='" + ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE + "' AND "
- + ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS + "=?";
- String[] args = new String[] { String.valueOf(contactID), oldSipAddress };
-
- ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
- .withSelection(select, args)
- .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE)
- .withValue(ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS, newSipAddress)
- .build()
- );
- }
-
- public static void deleteSipAddressFromContact(ArrayList ops, String oldSipAddress, String contactID) {
- String select = ContactsContract.Data.CONTACT_ID + "=? AND "
- + ContactsContract.Data.MIMETYPE + "='" + ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE + "' AND "
- + ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS + "=? ";
- String[] args = new String[] { String.valueOf(contactID), oldSipAddress };
-
- ops.add(ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI)
- .withSelection(select, args)
- .build()
- );
- }
-
- public static List extractContactNumbersAndAddresses(String id, ContentResolver cr) {
- List list = new ArrayList();
-
- Uri uri = Data.CONTENT_URI;
- String[] projection;
-
- // SIP addresses
- String selection2 = new StringBuilder()
- .append(Data.CONTACT_ID)
- .append(" = ? AND ")
- .append(Data.MIMETYPE)
- .append(" = '")
- .append(ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE)
- .append("'")
- .toString();
- projection = new String[] {ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS};
- Cursor c = cr.query(uri, projection, selection2, new String[]{id}, null);
- if (c != null) {
- int nbid = c.getColumnIndex(ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS);
- while (c.moveToNext()) {
- list.add("sip:" + c.getString(nbid));
- }
- c.close();
- }
-
- // Phone Numbers
- c = cr.query(Phone.CONTENT_URI, new String[] { Phone.NUMBER }, Phone.CONTACT_ID + " = " + id, null, null);
- if (c != null) {
- while (c.moveToNext()) {
- String number = c.getString(c.getColumnIndex(Phone.NUMBER));
- list.add(number);
- }
- c.close();
- }
-
- return list;
- }
-
- public static Cursor getContactsCursor(ContentResolver cr, String search, List ids) {
- String req;
- if(ids != null && ids.size() > 0) {
- req = "(" + Data.MIMETYPE + " = '" + CommonDataKinds.Phone.CONTENT_ITEM_TYPE
- + "' AND " + CommonDataKinds.Phone.NUMBER + " IS NOT NULL "
- + " OR (" + Data.MIMETYPE + " = '" + CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE
- + "' AND " + ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS + " IS NOT NULL)"
- + " OR (" + Data.CONTACT_ID + " IN (" + TextUtils.join(" , ", ids) + ")))";
- } else {
- req = "(" + Data.MIMETYPE + " = '" + CommonDataKinds.Phone.CONTENT_ITEM_TYPE
- + "' AND " + CommonDataKinds.Phone.NUMBER + " IS NOT NULL "
- + " OR (" + Data.MIMETYPE + " = '" + CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE
- + "' AND " + ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS + " IS NOT NULL))";
- }
-
- if (search != null) {
- req += " AND " + Data.DISPLAY_NAME + " LIKE '%" + search + "%'";
- }
-
- return ApiFivePlus.getGeneralContactCursor(cr, req, true);
- }
-
- public static Cursor getSIPContactsCursor(ContentResolver cr, String search, List ids) {
-
- String req = "(" + Data.MIMETYPE + " = '" + CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE
- + "' AND " + ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS + " IS NOT NULL) ";
-
- if(ids != null && ids.size() > 0) {
- req += " OR (" + Data.CONTACT_ID + " IN (" + TextUtils.join(" , ", ids) + "))";
- }
-
- if (search != null) {
- req += " AND " + Data.DISPLAY_NAME + " LIKE '%" + search + "%'";
- }
-
- return ApiFivePlus.getGeneralContactCursor(cr, req, true);
- }
-
- private static Cursor getSIPContactCursor(ContentResolver cr, String id) {
- String req = null;
- req = Contacts.Data.MIMETYPE + " = '" + CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE
- + "' AND " + ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS + " LIKE '" + id + "'";
-
- return ApiFivePlus.getGeneralContactCursor(cr, req, false);
- }
-
- public static Uri findUriPictureOfContactAndSetDisplayName(LinphoneAddress address, ContentResolver cr) {
- String username = address.getUserName();
- String domain = address.getDomain();
- String sipUri = username + "@" + domain;
-
- Cursor cursor = getSIPContactCursor(cr, sipUri);
- LinphoneContact contact = ApiFivePlus.getContact(cr, cursor, 0);
- if (contact != null && contact.getNumbersOrAddresses().contains(sipUri)) {
- address.setDisplayName(contact.getFullName());
- cursor.close();
- return contact.getPhotoUri();
- }
-
- cursor.close();
- return null;
- }
-}
diff --git a/src/org/linphone/compatibility/ApiSixteenPlus.java b/src/org/linphone/compatibility/ApiSixteenPlus.java
index 148756063..f7fff7d2f 100644
--- a/src/org/linphone/compatibility/ApiSixteenPlus.java
+++ b/src/org/linphone/compatibility/ApiSixteenPlus.java
@@ -33,6 +33,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@TargetApi(16)
public class ApiSixteenPlus {
+ @SuppressWarnings("deprecation")
public static Notification createMessageNotification(Context context,
int msgCount, String msgSender, String msg, Bitmap contactIcon,
PendingIntent intent) {
diff --git a/src/org/linphone/compatibility/ApiTwentyOnePlus.java b/src/org/linphone/compatibility/ApiTwentyOnePlus.java
index b75b72ef2..66d0a37b6 100644
--- a/src/org/linphone/compatibility/ApiTwentyOnePlus.java
+++ b/src/org/linphone/compatibility/ApiTwentyOnePlus.java
@@ -33,6 +33,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@TargetApi(21)
public class ApiTwentyOnePlus {
+ @SuppressWarnings("deprecation")
public static Notification createMessageNotification(Context context,
int msgCount, String msgSender, String msg, Bitmap contactIcon,
PendingIntent intent) {
diff --git a/src/org/linphone/compatibility/Compatibility.java b/src/org/linphone/compatibility/Compatibility.java
index 10846675d..cad5a21a0 100644
--- a/src/org/linphone/compatibility/Compatibility.java
+++ b/src/org/linphone/compatibility/Compatibility.java
@@ -17,191 +17,54 @@ 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.linphone.LinphoneContact;
-import org.linphone.core.LinphoneAddress;
import org.linphone.mediastream.Version;
-import android.app.Activity;
import android.app.Notification;
import android.app.PendingIntent;
-import android.content.ContentProviderOperation;
-import android.content.ContentResolver;
import android.content.Context;
-import android.content.Intent;
-import android.database.Cursor;
import android.graphics.Bitmap;
-import android.media.AudioManager;
-import android.net.Uri;
import android.os.PowerManager;
-import android.preference.Preference;
import android.provider.Settings;
+import android.text.Html;
+import android.text.Spanned;
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
/**
* @author Sylvain Berfini
*/
public class Compatibility {
- public static void overridePendingTransition(Activity activity, int idAnimIn, int idAnimOut) {
- if (Version.sdkAboveOrEqual(Version.API05_ECLAIR_20)) {
- ApiFivePlus.overridePendingTransition(activity, idAnimIn, idAnimOut);
- }
- }
-
- public static Intent prepareAddContactIntent(String displayName, String sipUri) {
- if (Version.sdkAboveOrEqual(Version.API11_HONEYCOMB_30)) {
- return ApiElevenPlus.prepareAddContactIntent(displayName, sipUri);
- } else {
- return ApiFivePlus.prepareAddContactIntent(displayName, sipUri);
- }
- }
-
- public static Intent prepareEditContactIntent(int id) {
- if (Version.sdkAboveOrEqual(Version.API05_ECLAIR_20)) {
- return ApiFivePlus.prepareEditContactIntent(id);
- }
- return null;
- }
-
- public static Intent prepareEditContactIntentWithSipAddress(int id, String sipAddress) {
- if (Version.sdkAboveOrEqual(Version.API11_HONEYCOMB_30)) {
- return ApiElevenPlus.prepareEditContactIntentWithSipAddress(id, sipAddress);
- } else {
- return ApiFivePlus.prepareEditContactIntent(id);
- }
- }
-
- public static List extractContactNumbersAndAddresses(String id, ContentResolver cr) {
- if (Version.sdkAboveOrEqual(Version.API09_GINGERBREAD_23)) {
- return ApiNinePlus.extractContactNumbersAndAddresses(id, cr);
- } else {
- return ApiFivePlus.extractContactNumbersAndAddresses(id, cr);
- }
- }
-
- public static List extractContactImAddresses(String id, ContentResolver cr) {
- if (Version.sdkAboveOrEqual(Version.API09_GINGERBREAD_23)) {
- return ApiFivePlus.extractContactNumbersAndAddresses(id, cr);
- } else {
- return null;
- }
- }
-
- public static Cursor getContactsCursor(ContentResolver cr, List contactsId) {
- if (Version.sdkAboveOrEqual(Version.API09_GINGERBREAD_23)) {
- return ApiNinePlus.getContactsCursor(cr, null, contactsId);
- } else {
- return ApiFivePlus.getContactsCursor(cr, contactsId);
- }
- }
-
- public static Cursor getContactsCursor(ContentResolver cr, String search, List contactsId) {
- if (Version.sdkAboveOrEqual(Version.API09_GINGERBREAD_23)) {
- return ApiNinePlus.getContactsCursor(cr, search, contactsId);
- } else {
- return ApiFivePlus.getContactsCursor(cr, contactsId);
- }
- }
-
- public static Cursor getSIPContactsCursor(ContentResolver cr, List contactsId) {
- if (Version.sdkAboveOrEqual(Version.API09_GINGERBREAD_23)) {
- return ApiNinePlus.getSIPContactsCursor(cr, null, contactsId);
- } else {
- return ApiFivePlus.getSIPContactsCursor(cr, contactsId);
- }
- }
-
- public static Cursor getSIPContactsCursor(ContentResolver cr, String search, List contactsId) {
- if (Version.sdkAboveOrEqual(Version.API09_GINGERBREAD_23)) {
- return ApiNinePlus.getSIPContactsCursor(cr, search, contactsId);
- } else {
- return ApiFivePlus.getSIPContactsCursor(cr, contactsId);
- }
- }
-
- public static Cursor getImContactsCursor(ContentResolver cr) {
- return ApiFivePlus.getSIPContactsCursor(cr,null);
- }
-
- public static int getCursorDisplayNameColumnIndex(Cursor cursor) {
- if (Version.sdkAboveOrEqual(Version.API05_ECLAIR_20)) {
- return ApiFivePlus.getCursorDisplayNameColumnIndex(cursor);
- }
- return -1;
- }
-
- public static LinphoneContact getContact(ContentResolver cr, Cursor cursor, int position) {
- if (Version.sdkAboveOrEqual(Version.API05_ECLAIR_20)) {
- return ApiFivePlus.getContact(cr, cursor, position);
- }
- return null;
- }
-
- public static InputStream getContactPictureInputStream(ContentResolver cr, String id) {
- if (Version.sdkAboveOrEqual(Version.API05_ECLAIR_20)) {
- return ApiFivePlus.getContactPictureInputStream(cr, id);
- }
- return null;
- }
-
- public static Uri findUriPictureOfContactAndSetDisplayName(LinphoneAddress address, ContentResolver cr) {
- if (Version.sdkAboveOrEqual(Version.API09_GINGERBREAD_23)) {
- return ApiNinePlus.findUriPictureOfContactAndSetDisplayName(address, cr);
- } else {
- return ApiFivePlus.findUriPictureOfContactAndSetDisplayName(address, cr);
- }
- }
-
public static Notification createSimpleNotification(Context context, String title, String text, PendingIntent intent) {
Notification notif = null;
-
if (Version.sdkAboveOrEqual(Version.API21_LOLLIPOP_50)) {
return ApiTwentyOnePlus.createSimpleNotification(context, title, text, intent);
} else if (Version.sdkAboveOrEqual(Version.API16_JELLY_BEAN_41)) {
notif = ApiSixteenPlus.createSimpleNotification(context, title, text, intent);
- } else if (Version.sdkAboveOrEqual(Version.API11_HONEYCOMB_30)) {
- notif = ApiElevenPlus.createSimpleNotification(context, title, text, intent);
} else {
- notif = ApiFivePlus.createSimpleNotification(context, title, text, intent);
+ notif = ApiElevenPlus.createSimpleNotification(context, title, text, intent);
}
return notif;
}
public static Notification createMessageNotification(Context context, int msgCount, String msgSender, String msg, Bitmap contactIcon, PendingIntent intent) {
- Notification notif = null;
- String title;
- if (msgCount == 1) {
- title = "Unread message from %s".replace("%s", msgSender);
- } else {
- title = "%i unread messages".replace("%i", String.valueOf(msgCount));
- }
-
+ Notification notif = null;
if (Version.sdkAboveOrEqual(Version.API21_LOLLIPOP_50)) {
return ApiTwentyOnePlus.createMessageNotification(context, msgCount, msgSender, msg, contactIcon, intent);
} else if (Version.sdkAboveOrEqual(Version.API16_JELLY_BEAN_41)) {
notif = ApiSixteenPlus.createMessageNotification(context, msgCount, msgSender, msg, contactIcon, intent);
- } else if (Version.sdkAboveOrEqual(Version.API11_HONEYCOMB_30)) {
- notif = ApiElevenPlus.createMessageNotification(context, msgCount, msgSender, msg, contactIcon, intent);
} else {
- notif = ApiFivePlus.createMessageNotification(context, title, msg, intent);
+ notif = ApiElevenPlus.createMessageNotification(context, msgCount, msgSender, msg, contactIcon, intent);
}
return notif;
}
public static Notification createInCallNotification(Context context, String title, String msg, int iconID, Bitmap contactIcon, String contactName, PendingIntent intent) {
Notification notif = null;
-
if (Version.sdkAboveOrEqual(Version.API21_LOLLIPOP_50)) {
return ApiTwentyOnePlus.createInCallNotification(context, title, msg, iconID, contactIcon, contactName, intent);
} else if (Version.sdkAboveOrEqual(Version.API16_JELLY_BEAN_41)) {
notif = ApiSixteenPlus.createInCallNotification(context, title, msg, iconID, contactIcon, contactName, intent);
- } else if (Version.sdkAboveOrEqual(Version.API11_HONEYCOMB_30)) {
- notif = ApiElevenPlus.createInCallNotification(context, title, msg, iconID, contactIcon, contactName, intent);
} else {
- notif = ApiFivePlus.createInCallNotification(context, title, msg, iconID, intent);
+ notif = ApiElevenPlus.createInCallNotification(context, title, msg, iconID, contactIcon, contactName, intent);
}
return notif;
}
@@ -211,20 +74,11 @@ public class Compatibility {
return ApiTwentyOnePlus.createNotification(context, title, message, icon, iconLevel, largeIcon, intent, isOngoingEvent,priority);
} else if (Version.sdkAboveOrEqual(Version.API16_JELLY_BEAN_41)) {
return ApiSixteenPlus.createNotification(context, title, message, icon, iconLevel, largeIcon, intent, isOngoingEvent,priority);
- } else if (Version.sdkAboveOrEqual(Version.API11_HONEYCOMB_30)) {
- return ApiElevenPlus.createNotification(context, title, message, icon, iconLevel, largeIcon, intent, isOngoingEvent);
} else {
- return ApiFivePlus.createNotification(context, title, message, icon, iconLevel, intent, isOngoingEvent);
+ return ApiElevenPlus.createNotification(context, title, message, icon, iconLevel, largeIcon, intent, isOngoingEvent);
}
}
- public static String refreshContactName(ContentResolver cr, String id) {
- if (Version.sdkAboveOrEqual(Version.API05_ECLAIR_20)) {
- return ApiFivePlus.refreshContactName(cr, id);
- }
- return null;
- }
-
public static CompatibilityScaleGestureDetector getScaleGestureDetector(Context context, CompatibilityScaleGestureListener listener) {
if (Version.sdkAboveOrEqual(Version.API08_FROYO_22)) {
CompatibilityScaleGestureDetector csgd = new CompatibilityScaleGestureDetector(context);
@@ -233,109 +87,13 @@ public class Compatibility {
}
return null;
}
-
-
- public static void setPreferenceChecked(Preference preference, boolean checked) {
- if (Version.sdkAboveOrEqual(Version.API14_ICE_CREAM_SANDWICH_40)) {
- ApiFourteenPlus.setPreferenceChecked(preference, checked);
- } else {
- ApiFivePlus.setPreferenceChecked(preference, checked);
- }
- }
-
- public static boolean isPreferenceChecked(Preference preference) {
- if (Version.sdkAboveOrEqual(Version.API14_ICE_CREAM_SANDWICH_40)) {
- return ApiFourteenPlus.isPreferenceChecked(preference);
- } else {
- return ApiFivePlus.isPreferenceChecked(preference);
- }
- }
-
- public static void initPushNotificationService(Context context) {
- if (Version.sdkAboveOrEqual(Version.API08_FROYO_22)) {
- ApiEightPlus.initPushNotificationService(context);
- }
- }
-
- public static void copyTextToClipboard(Context context, String msg) {
- if(Version.sdkAboveOrEqual(Version.API11_HONEYCOMB_30)) {
- ApiElevenPlus.copyTextToClipboard(context, msg);
- } else {
- ApiFivePlus.copyTextToClipboard(context, msg);
- }
- }
-
- public static void addSipAddressToContact(Context context, ArrayList ops, String sipAddress) {
- if (Version.sdkAboveOrEqual(Version.API09_GINGERBREAD_23)) {
- ApiNinePlus.addSipAddressToContact(context, ops, sipAddress);
- } else {
- ApiFivePlus.addSipAddressToContact(context, ops, sipAddress);
- }
- }
-
- public static void addSipAddressToContact(Context context, ArrayList ops, String sipAddress, String rawContactID) {
- if (Version.sdkAboveOrEqual(Version.API09_GINGERBREAD_23)) {
- ApiNinePlus.addSipAddressToContact(context, ops, sipAddress, rawContactID);
- } else {
- ApiFivePlus.addSipAddressToContact(context, ops, sipAddress, rawContactID);
- }
- }
-
- public static void updateSipAddressForContact(ArrayList ops, String oldSipAddress, String newSipAddress, String contactID) {
- if (Version.sdkAboveOrEqual(Version.API09_GINGERBREAD_23)) {
- ApiNinePlus.updateSipAddressForContact(ops, oldSipAddress, newSipAddress, contactID);
- } else {
- ApiFivePlus.updateSipAddressForContact(ops, oldSipAddress, newSipAddress, contactID);
- }
- }
-
- public static void deleteSipAddressFromContact(ArrayList ops, String oldSipAddress, String contactID) {
- if (Version.sdkAboveOrEqual(Version.API09_GINGERBREAD_23)) {
- ApiNinePlus.deleteSipAddressFromContact(ops, oldSipAddress, contactID);
- } else {
- ApiFivePlus.deleteSipAddressFromContact(ops, oldSipAddress, contactID);
- }
- }
-
- public static void deleteImAddressFromContact(ArrayList ops, String oldSipAddress, String contactID) {
- ApiFivePlus.deleteSipAddressFromContact(ops, oldSipAddress, contactID);
- }
+ @SuppressWarnings("deprecation")
public static void removeGlobalLayoutListener(ViewTreeObserver viewTreeObserver, OnGlobalLayoutListener keyboardListener) {
if (Version.sdkAboveOrEqual(Version.API16_JELLY_BEAN_41)) {
ApiSixteenPlus.removeGlobalLayoutListener(viewTreeObserver, keyboardListener);
} else {
- ApiFivePlus.removeGlobalLayoutListener(viewTreeObserver, keyboardListener);
- }
- }
-
- public static void hideNavigationBar(Activity activity)
- {
- if (Version.sdkAboveOrEqual(Version.API14_ICE_CREAM_SANDWICH_40)) {
- ApiFourteenPlus.hideNavigationBar(activity);
- }
- }
-
- public static void showNavigationBar(Activity activity)
- {
- if (Version.sdkAboveOrEqual(Version.API14_ICE_CREAM_SANDWICH_40)) {
- ApiFourteenPlus.showNavigationBar(activity);
- }
- }
-
- public static void setAudioManagerInCallMode(AudioManager manager) {
- if (Version.sdkAboveOrEqual(Version.API11_HONEYCOMB_30)) {
- ApiElevenPlus.setAudioManagerInCallMode(manager);
- } else {
- ApiFivePlus.setAudioManagerInCallMode(manager);
- }
- }
-
- public static String getAudioManagerEventForBluetoothConnectionStateChangedEvent() {
- if (Version.sdkAboveOrEqual(Version.API14_ICE_CREAM_SANDWICH_40)) {
- return ApiFourteenPlus.getAudioManagerEventForBluetoothConnectionStateChangedEvent();
- } else {
- return ApiEightPlus.getAudioManagerEventForBluetoothConnectionStateChangedEvent();
+ viewTreeObserver.removeGlobalOnLayoutListener(keyboardListener);
}
}
@@ -354,4 +112,12 @@ public class Compatibility {
return pm.isScreenOn();
}
}
+
+ @SuppressWarnings("deprecation")
+ public static Spanned fromHtml(String text) {
+ /*if (Version.sdkAboveOrEqual(Version.API24_NOUGAT_70)) {
+ return Html.fromHtml(text, Html.FROM_HTML_MODE_LEGACY);
+ }*/
+ return Html.fromHtml(text);
+ }
}
diff --git a/src/org/linphone/gcm/GCMService.java b/src/org/linphone/gcm/GCMService.java
index ebeb8f7f6..ebfc1273f 100644
--- a/src/org/linphone/gcm/GCMService.java
+++ b/src/org/linphone/gcm/GCMService.java
@@ -53,13 +53,13 @@ public class GCMService extends GCMBaseIntentService {
@Override
protected void onError(Context context, String errorId) {
initLogger(context);
- Log.e("Error while registering push notification : " + errorId);
+ Log.e("[Push Notification] Error while registering: " + errorId);
}
@Override
protected void onMessage(Context context, Intent intent) {
initLogger(context);
- Log.d("Push notification received");
+ Log.d("[Push Notification] Received");
if (!LinphoneService.isReady()) {
startService(new Intent(ACTION_MAIN).setClass(this, LinphoneService.class));
@@ -79,7 +79,7 @@ public class GCMService extends GCMBaseIntentService {
@Override
protected void onRegistered(Context context, String regId) {
initLogger(context);
- Log.d("Registered push notification : " + regId);
+ Log.d("[Push Notification] Registered: " + regId);
LinphonePreferences.instance().setPushNotificationRegistrationID(regId);
}
@@ -87,7 +87,7 @@ public class GCMService extends GCMBaseIntentService {
@Override
protected void onUnregistered(Context context, String regId) {
initLogger(context);
- Log.w("Unregistered push notification : " + regId);
+ Log.w("[Push Notification] Unregistered: " + regId);
LinphonePreferences.instance().setPushNotificationRegistrationID(null);
}
diff --git a/src/org/linphone/tutorials/TutorialCardDavSync.java b/src/org/linphone/tutorials/TutorialCardDavSync.java
index 2ef341bdd..efcd4bd0d 100644
--- a/src/org/linphone/tutorials/TutorialCardDavSync.java
+++ b/src/org/linphone/tutorials/TutorialCardDavSync.java
@@ -162,8 +162,7 @@ public class TutorialCardDavSync extends Activity implements OnClickListener, Li
}
@Override
- public void onLinphoneFriendSyncStatusChanged(LinphoneFriendList list,
- org.linphone.core.LinphoneFriendList.State status, String message) {
+ public void onLinphoneFriendSyncStatusChanged(LinphoneFriendList list, LinphoneFriendList.State status, String message) {
// TODO Auto-generated method stub
String msg = "Sync status changed: " + status.toString() + " (" + message + ")";
myLog(msg);
diff --git a/src/org/linphone/ui/BubbleChat.java b/src/org/linphone/ui/BubbleChat.java
deleted file mode 100644
index d65709eec..000000000
--- a/src/org/linphone/ui/BubbleChat.java
+++ /dev/null
@@ -1,463 +0,0 @@
-package org.linphone.ui;
-/*
-BubbleChat.java
-Copyright (C) 2012 Belledonne Communications, Grenoble, France
-
-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 2
-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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-*/
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.lang.ref.WeakReference;
-import java.text.SimpleDateFormat;
-import java.util.Calendar;
-import java.util.HashMap;
-import java.util.Map.Entry;
-
-import org.linphone.LinphoneActivity;
-import org.linphone.LinphoneContact;
-import org.linphone.LinphoneManager;
-import org.linphone.LinphoneUtils;
-import org.linphone.R;
-import org.linphone.core.LinphoneBuffer;
-import org.linphone.core.LinphoneChatMessage;
-import org.linphone.core.LinphoneChatMessage.State;
-import org.linphone.core.LinphoneContent;
-import org.linphone.mediastream.Log;
-
-import android.Manifest;
-import android.annotation.SuppressLint;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.media.ThumbnailUtils;
-import android.net.Uri;
-import android.os.AsyncTask;
-import android.os.Environment;
-import android.provider.MediaStore;
-import android.text.Html;
-import android.text.Spannable;
-import android.text.SpannableStringBuilder;
-import android.text.Spanned;
-import android.text.method.LinkMovementMethod;
-import android.text.style.ImageSpan;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.Button;
-import android.widget.ImageView;
-import android.widget.ProgressBar;
-import android.widget.RelativeLayout;
-import android.widget.TextView;
-
-/**
- * @author Sylvain Berfini
- */
-@SuppressLint("SimpleDateFormat")
-public class BubbleChat implements LinphoneChatMessage.LinphoneChatMessageListener {
- private static final HashMap emoticons = new HashMap();
-
- private View view;
- private ImageView statusView, contactPicture;
- private LinphoneChatMessage nativeMessage;
- private Context mContext;
- private Button cancelUpload, acceptDownload;
- private static final int SIZE_MAX = 512;
- private ProgressBar progressBar, inprogress;
- private Bitmap defaultBitmap;
-
- @SuppressLint("InflateParams")
- public BubbleChat(final Context context, LinphoneChatMessage message, LinphoneContact c) {
- if (message == null) {
- return;
- }
- nativeMessage = message;
- mContext = context;
-
- if (message.isOutgoing()) {
- view = LayoutInflater.from(context).inflate(R.layout.chat_bubble_outgoing, null);
- } else {
- view = LayoutInflater.from(context).inflate(R.layout.chat_bubble_incoming, null);
- }
- view.setId(message.getStorageId());
-
- defaultBitmap = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.chat_picture_over);
- inprogress = (ProgressBar) view.findViewById(R.id.inprogress);
- progressBar = (ProgressBar) view.findViewById(R.id.progress_bar);
-
- LinphoneChatMessage.State status = message.getStatus();
- statusView = (ImageView) view.findViewById(R.id.status);
-
- if (statusView != null) {
- if (status == LinphoneChatMessage.State.Delivered) {
- statusView.setVisibility(View.INVISIBLE);
- inprogress.setVisibility(View.GONE);
- } else if (status == LinphoneChatMessage.State.NotDelivered) {
- statusView.setVisibility(View.VISIBLE);
- statusView.setImageResource(R.drawable.chat_message_not_delivered);
- } else {
- statusView.setVisibility(View.GONE);
- inprogress.setVisibility(View.VISIBLE);
- }
- }
-
- String externalBodyUrl = message.getExternalBodyUrl();
- LinphoneContent fileTransferContent = message.getFileTransferInformation();
-
- if(nativeMessage.isOutgoing()){
- cancelUpload = (Button) view.findViewById(R.id.cancel_upload);
- cancelUpload.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (LinphoneManager.getInstance().getMessageUploadPending() != null) {
- progressBar.setVisibility(View.GONE);
- progressBar.setProgress(0);
- nativeMessage.cancelFileTransfer();
- LinphoneManager.getInstance().setUploadPendingFileMessage(null);
- }
- }
- });
- }
-
- if(LinphoneManager.getInstance().getMessageUploadPending() != null){
- progressBar.setVisibility(View.VISIBLE);
- LinphoneManager.addListener(this);
- }
-
- if (externalBodyUrl != null || fileTransferContent != null) {
- String appData = message.getAppData();
- ImageView imageView = (ImageView) view.findViewById(R.id.image);
-
- if(nativeMessage.isOutgoing() && appData != null){
- imageView.setVisibility(View.VISIBLE);
- loadBitmap(appData, imageView);
-
- RelativeLayout imageLayout = (RelativeLayout) view.findViewById(R.id.file_transfer_layout);
- if(LinphoneManager.getInstance().getMessageUploadPending() != null && LinphoneManager.getInstance().getMessageUploadPending().getStorageId() == nativeMessage.getStorageId()){
- inprogress.setVisibility(View.INVISIBLE);
- imageLayout.setVisibility(View.VISIBLE);
- nativeMessage.setListener(LinphoneManager.getInstance());
- }
- } else {
- if (appData != null && !LinphoneManager.getInstance().isMessagePending(nativeMessage) &&
- appData.contains(context.getString(R.string.temp_photo_name_with_date).split("%s")[0])) {
- appData = null;
- }
-
- RelativeLayout imageLayout = (RelativeLayout) view.findViewById(R.id.file_transfer_layout);
- acceptDownload = (Button) view.findViewById(R.id.accept_download);
-
- if (appData == null) {
- LinphoneManager.addListener(this);
- imageLayout.setVisibility(View.VISIBLE);
- acceptDownload.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- if (mContext.getPackageManager().checkPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, mContext.getPackageName()) == PackageManager.PERMISSION_GRANTED) {
- v.setEnabled(false);
- String extension = nativeMessage.getFileTransferInformation().getSubtype();
- String filename = context.getString(R.string.temp_photo_name_with_date).replace("%s", String.valueOf(System.currentTimeMillis())) + "." + extension;
- File file = new File(Environment.getExternalStorageDirectory(), filename);
- nativeMessage.setAppData(filename);
- LinphoneManager.getInstance().addDownloadMessagePending(nativeMessage);
- nativeMessage.setListener(LinphoneManager.getInstance());
- nativeMessage.setFileTransferFilepath(file.getPath());
- nativeMessage.downloadFile();
- } else {
- Log.w("WRITE_EXTERNAL_STORAGE permission not granted, won't be able to store the downloaded file");
- LinphoneActivity.instance().checkAndRequestExternalStoragePermission();
- }
- }
- });
- } else {
- if (LinphoneManager.getInstance().isMessagePending(nativeMessage)) {
- LinphoneManager.addListener(this);
- acceptDownload.setEnabled(false);
- imageLayout.setVisibility(View.VISIBLE);
- } else {
- LinphoneManager.removeListener(this);
- imageLayout.setVisibility(View.GONE);
- imageView.setVisibility(View.VISIBLE);
- loadBitmap(appData, imageView);
- }
- }
- }
- } else {
- TextView msgView = (TextView) view.findViewById(R.id.message);
- if (msgView != null) {
- Spanned text = null;
- String msg = message.getText();
- if (msg != null) {
- text = getSmiledText(context, getTextWithHttpLinks(msg));
- msgView.setText(text);
- msgView.setMovementMethod(LinkMovementMethod.getInstance());
- msgView.setVisibility(View.VISIBLE);
- }
- }
- }
-
- TextView contact = (TextView) view.findViewById(R.id.contact_header);
-
-
-
- contactPicture = (ImageView) view.findViewById(R.id.contact_picture);
-
- String displayName = nativeMessage.getFrom().getUserName();
- if(!nativeMessage.isOutgoing()) {
- if (c != null) {
- displayName = c.getFullName();
- LinphoneUtils.setImagePictureFromUri(view.getContext(), contactPicture, c.getPhotoUri(), c.getThumbnailUri());
- } else {
- contactPicture.setImageResource(R.drawable.avatar);
- }
- }
-
- contact.setText(timestampToHumanDate(context, message.getTime()) + " - " + displayName);
-
- }
-
- public View getView() {
- return view;
- }
-
- public void destroy() {
- defaultBitmap.recycle();
- }
-
- private String timestampToHumanDate(Context context, long timestamp) {
- try {
- Calendar cal = Calendar.getInstance();
- cal.setTimeInMillis(timestamp);
-
- SimpleDateFormat dateFormat;
- if (isToday(cal)) {
- dateFormat = new SimpleDateFormat(context.getResources().getString(R.string.today_date_format));
- } else {
- dateFormat = new SimpleDateFormat(context.getResources().getString(R.string.messages_date_format));
- }
-
- return dateFormat.format(cal.getTime());
- } catch (NumberFormatException nfe) {
- return String.valueOf(timestamp);
- }
- }
-
- private boolean isToday(Calendar cal) {
- return isSameDay(cal, Calendar.getInstance());
- }
-
- private boolean isSameDay(Calendar cal1, Calendar cal2) {
- if (cal1 == null || cal2 == null) {
- return false;
- }
-
- return (cal1.get(Calendar.ERA) == cal2.get(Calendar.ERA) &&
- cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) &&
- cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR));
- }
-
- public static Spannable getSmiledText(Context context, Spanned spanned) {
- SpannableStringBuilder builder = new SpannableStringBuilder(spanned);
- String text = spanned.toString();
-
- for (Entry entry : emoticons.entrySet()) {
- String key = entry.getKey();
- int indexOf = text.indexOf(key);
- while (indexOf >= 0) {
- int end = indexOf + key.length();
- builder.setSpan(new ImageSpan(context, entry.getValue()), indexOf, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- indexOf = text.indexOf(key, end);
- }
- }
-
- return builder;
- }
-
- public static Spanned getTextWithHttpLinks(String text) {
- if (text.contains("<")) {
- text = text.replace("<", "<");
- }
- if (text.contains(">")) {
- text = text.replace(">", ">");
- }
- if (text.contains("http://")) {
- int indexHttp = text.indexOf("http://");
- int indexFinHttp = text.indexOf(" ", indexHttp) == -1 ? text.length() : text.indexOf(" ", indexHttp);
- String link = text.substring(indexHttp, indexFinHttp);
- String linkWithoutScheme = link.replace("http://", "");
- text = text.replaceFirst(link, "" + linkWithoutScheme + "");
- }
- if (text.contains("https://")) {
- int indexHttp = text.indexOf("https://");
- int indexFinHttp = text.indexOf(" ", indexHttp) == -1 ? text.length() : text.indexOf(" ", indexHttp);
- String link = text.substring(indexHttp, indexFinHttp);
- String linkWithoutScheme = link.replace("https://", "");
- text = text.replaceFirst(link, "" + linkWithoutScheme + "");
- }
-
- return Html.fromHtml(text);
- }
-
- public String getTextMessage() {
- return nativeMessage.getText();
- }
-
- public State getStatus() {
- return nativeMessage.getStatus();
- }
-
- public LinphoneChatMessage getNativeMessageObject() {
- return nativeMessage;
- }
-
- public int getId() {
- return nativeMessage.getStorageId();
- }
-
- public void loadBitmap(String path, ImageView imageView) {
- if (cancelPotentialWork(path, imageView)) {
- BitmapWorkerTask task = new BitmapWorkerTask(imageView);
- final AsyncBitmap asyncBitmap = new AsyncBitmap(mContext.getResources(), defaultBitmap, task);
- imageView.setImageDrawable(asyncBitmap);
- task.execute(path);
- }
- }
-
- private class BitmapWorkerTask extends AsyncTask {
- private final WeakReference imageViewReference;
- public String path;
-
- public BitmapWorkerTask(ImageView imageView) {
- path = null;
- // Use a WeakReference to ensure the ImageView can be garbage collected
- imageViewReference = new WeakReference(imageView);
- }
-
- // Decode image in background.
- @Override
- protected Bitmap doInBackground(String... params) {
- path = params[0];
- Bitmap bm = null;
-
- if (path.startsWith("content")) {
- try {
- bm = MediaStore.Images.Media.getBitmap(mContext.getContentResolver(), Uri.parse(path));
- } catch (FileNotFoundException e) {
- Log.e(e);
- } catch (IOException e) {
- Log.e(e);
- }
- } else {
- bm = BitmapFactory.decodeFile(path);
- path = "file://" + path;
- }
-
- if (bm != null) {
- bm = ThumbnailUtils.extractThumbnail(bm, SIZE_MAX, SIZE_MAX);
- }
- return bm;
- }
-
- // Once complete, see if ImageView is still around and set bitmap.
- @Override
- protected void onPostExecute(Bitmap bitmap) {
- if (isCancelled()) {
- bitmap = null;
- }
-
- if (imageViewReference != null && bitmap != null) {
- final ImageView imageView = imageViewReference.get();
- final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
- if (this == bitmapWorkerTask && imageView != null) {
- imageView.setImageBitmap(bitmap);
- imageView.setTag(path);
- imageView.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.setDataAndType(Uri.parse((String)v.getTag()), "image/*");
- mContext.startActivity(intent);
- }
- });
- }
- }
- }
- }
-
- static class AsyncBitmap extends BitmapDrawable {
- private final WeakReference bitmapWorkerTaskReference;
-
- public AsyncBitmap(Resources res, Bitmap bitmap, BitmapWorkerTask bitmapWorkerTask) {
- super(res, bitmap);
- bitmapWorkerTaskReference = new WeakReference(bitmapWorkerTask);
- }
-
- public BitmapWorkerTask getBitmapWorkerTask() {
- return bitmapWorkerTaskReference.get();
- }
- }
-
- public static boolean cancelPotentialWork(String path, ImageView imageView) {
- final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
-
- if (bitmapWorkerTask != null) {
- final String bitmapData = bitmapWorkerTask.path;
- // If bitmapData is not yet set or it differs from the new data
- if (bitmapData == null || bitmapData != path) {
- // Cancel previous task
- bitmapWorkerTask.cancel(true);
- } else {
- // The same work is already in progress
- return false;
- }
- }
- // No task associated with the ImageView, or an existing task was cancelled
- return true;
- }
-
- private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) {
- if (imageView != null) {
- final Drawable drawable = imageView.getDrawable();
- if (drawable instanceof AsyncBitmap) {
- final AsyncBitmap asyncDrawable = (AsyncBitmap) drawable;
- return asyncDrawable.getBitmapWorkerTask();
- }
- }
- return null;
- }
-
- @Override
- public void onLinphoneChatMessageStateChanged(LinphoneChatMessage msg, State state) {
- }
-
- @Override
- public void onLinphoneChatMessageFileTransferReceived(LinphoneChatMessage msg, LinphoneContent content, LinphoneBuffer buffer) {
- }
-
- @Override
- public void onLinphoneChatMessageFileTransferSent(LinphoneChatMessage msg, LinphoneContent content, int offset, int size, LinphoneBuffer bufferToFill) {
- }
-
- @Override
- public void onLinphoneChatMessageFileTransferProgressChanged(LinphoneChatMessage msg, LinphoneContent content, int offset, int total) {
- if(nativeMessage.getStorageId() == msg.getStorageId())
- progressBar.setProgress(offset * 100 / total);
- }
-}
diff --git a/submodules/bctoolbox b/submodules/bctoolbox
index fbac73d67..921a21332 160000
--- a/submodules/bctoolbox
+++ b/submodules/bctoolbox
@@ -1 +1 @@
-Subproject commit fbac73d6704f9f5697770188747639e519a28819
+Subproject commit 921a21332c327ae99900267950be0bfd2d7c6126
diff --git a/submodules/belle-sip b/submodules/belle-sip
index 086bb16bd..b553f58c3 160000
--- a/submodules/belle-sip
+++ b/submodules/belle-sip
@@ -1 +1 @@
-Subproject commit 086bb16bd79180265136ed9d4a89661049c95016
+Subproject commit b553f58c3f23633b9c183af5784b2170b6b4aa91
diff --git a/submodules/cmake-builder b/submodules/cmake-builder
index 29911ee5b..f4eac4803 160000
--- a/submodules/cmake-builder
+++ b/submodules/cmake-builder
@@ -1 +1 @@
-Subproject commit 29911ee5ba6053dd041ee02c6dc13b0134e890d2
+Subproject commit f4eac4803eee43de3efa96ecca9450ba4f2bc7dc
diff --git a/submodules/linphone b/submodules/linphone
index 61a3b8a98..958366ce1 160000
--- a/submodules/linphone
+++ b/submodules/linphone
@@ -1 +1 @@
-Subproject commit 61a3b8a98e6d35bff351b64e2c6717491792afb3
+Subproject commit 958366ce1928bd0aabaf983082faa8c49e501c4a
diff --git a/tests/custom_rules.xml b/tests/custom_rules.xml
index 87abcd905..5e7d620df 100644
--- a/tests/custom_rules.xml
+++ b/tests/custom_rules.xml
@@ -40,7 +40,7 @@
-
+