Merge remote-tracking branch 'origin/master' into bellesip
Conflicts: .gitignore
1
.gitignore
vendored
|
@ -14,3 +14,4 @@ tests/*$py.class
|
|||
tests/build.xml
|
||||
res/.DS_Store
|
||||
bc-android.keystore
|
||||
res/raw/lpconfig.xsd
|
||||
|
|
Before Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 4 KiB |
Before Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 4 KiB |
Before Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 3.5 KiB |
BIN
res/drawable-xhdpi/routes_bluetooth_off_default.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
res/drawable-xhdpi/routes_bluetooth_off_disabled.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
res/drawable-xhdpi/routes_bluetooth_off_over.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
res/drawable-xhdpi/routes_bluetooth_on_default.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
res/drawable-xhdpi/routes_bluetooth_on_disabled.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
res/drawable-xhdpi/routes_bluetooth_on_over.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
res/drawable-xhdpi/routes_phone_off_default.png
Normal file
After Width: | Height: | Size: 3 KiB |
BIN
res/drawable-xhdpi/routes_phone_off_disabled.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
res/drawable-xhdpi/routes_phone_off_over.png
Normal file
After Width: | Height: | Size: 3 KiB |
BIN
res/drawable-xhdpi/routes_phone_on_default.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
res/drawable-xhdpi/routes_phone_on_disabled.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
res/drawable-xhdpi/routes_phone_on_over.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.6 KiB |
BIN
res/drawable-xhdpi/routes_speaker_off_default.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
res/drawable-xhdpi/routes_speaker_off_disabled.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
res/drawable-xhdpi/routes_speaker_off_over.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
res/drawable-xhdpi/routes_speaker_on_default.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
res/drawable-xhdpi/routes_speaker_on_disabled.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
res/drawable-xhdpi/routes_speaker_on_over.png
Normal file
After Width: | Height: | Size: 2 KiB |
|
@ -1,9 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_pressed="true"
|
||||
android:drawable="@drawable/route_bluetooth_off_over" />
|
||||
android:drawable="@drawable/routes_bluetooth_off_over" />
|
||||
<item android:state_enabled="false"
|
||||
android:drawable="@drawable/route_bluetooth_off_disabled" />
|
||||
android:drawable="@drawable/routes_bluetooth_off_disabled" />
|
||||
<item
|
||||
android:drawable="@drawable/route_bluetooth_off_default" />
|
||||
android:drawable="@drawable/routes_bluetooth_off_default" />
|
||||
</selector>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_pressed="true"
|
||||
android:drawable="@drawable/route_bluetooth_off_over" />
|
||||
android:drawable="@drawable/routes_bluetooth_on_over" />
|
||||
<item android:state_enabled="false"
|
||||
android:drawable="@drawable/route_bluetooth_off_disabled" />
|
||||
android:drawable="@drawable/routes_bluetooth_on_disabled" />
|
||||
<item
|
||||
android:drawable="@drawable/route_bluetooth_on_default" />
|
||||
android:drawable="@drawable/routes_bluetooth_on_default" />
|
||||
</selector>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_pressed="true"
|
||||
android:drawable="@drawable/route_phone_off_over" />
|
||||
android:drawable="@drawable/routes_phone_off_over" />
|
||||
<item android:state_enabled="false"
|
||||
android:drawable="@drawable/route_phone_off_disabled" />
|
||||
android:drawable="@drawable/routes_phone_off_disabled" />
|
||||
<item
|
||||
android:drawable="@drawable/route_phone_off_default" />
|
||||
android:drawable="@drawable/routes_phone_off_default" />
|
||||
</selector>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_pressed="true"
|
||||
android:drawable="@drawable/route_phone_off_over" />
|
||||
android:drawable="@drawable/routes_phone_on_over" />
|
||||
<item android:state_enabled="false"
|
||||
android:drawable="@drawable/route_phone_off_disabled" />
|
||||
android:drawable="@drawable/routes_phone_on_disabled" />
|
||||
<item
|
||||
android:drawable="@drawable/route_phone_on_default" />
|
||||
android:drawable="@drawable/routes_phone_on_default" />
|
||||
</selector>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_pressed="true"
|
||||
android:drawable="@drawable/route_speaker_off_over" />
|
||||
android:drawable="@drawable/routes_speaker_off_over" />
|
||||
<item android:state_enabled="false"
|
||||
android:drawable="@drawable/route_speaker_off_disabled" />
|
||||
android:drawable="@drawable/routes_speaker_off_disabled" />
|
||||
<item
|
||||
android:drawable="@drawable/route_speaker_off_default" />
|
||||
android:drawable="@drawable/routes_speaker_off_default" />
|
||||
</selector>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_pressed="true"
|
||||
android:drawable="@drawable/route_speaker_off_over" />
|
||||
android:drawable="@drawable/routes_speaker_on_over" />
|
||||
<item android:state_enabled="false"
|
||||
android:drawable="@drawable/route_speaker_off_disabled" />
|
||||
android:drawable="@drawable/routes_speaker_on_disabled" />
|
||||
<item
|
||||
android:drawable="@drawable/route_speaker_on_default" />
|
||||
android:drawable="@drawable/routes_speaker_on_default" />
|
||||
</selector>
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
|
||||
</LinearLayout>
|
||||
|
||||
<ScrollView
|
||||
<org.linphone.ui.LinphoneScrollView
|
||||
android:id="@+id/chatScrollView"
|
||||
android:paddingTop="5dp"
|
||||
android:layout_weight="1"
|
||||
|
@ -47,7 +47,7 @@
|
|||
|
||||
</RelativeLayout>
|
||||
|
||||
</ScrollView>
|
||||
</org.linphone.ui.LinphoneScrollView>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/messageLayout"
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
|
||||
</LinearLayout>
|
||||
|
||||
<ScrollView
|
||||
<org.linphone.ui.LinphoneScrollView
|
||||
android:id="@+id/chatScrollView"
|
||||
android:paddingTop="5dp"
|
||||
android:layout_weight="1"
|
||||
|
@ -47,7 +47,7 @@
|
|||
|
||||
</RelativeLayout>
|
||||
|
||||
</ScrollView>
|
||||
</org.linphone.ui.LinphoneScrollView>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/messageLayout"
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
|
||||
</LinearLayout>
|
||||
|
||||
<ScrollView
|
||||
<org.linphone.ui.LinphoneScrollView
|
||||
android:id="@+id/chatScrollView"
|
||||
android:paddingTop="5dp"
|
||||
android:layout_weight="1"
|
||||
|
@ -47,7 +47,7 @@
|
|||
|
||||
</RelativeLayout>
|
||||
|
||||
</ScrollView>
|
||||
</org.linphone.ui.LinphoneScrollView>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/messageLayout"
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
|
||||
</LinearLayout>
|
||||
|
||||
<ScrollView
|
||||
<org.linphone.ui.LinphoneScrollView
|
||||
android:id="@+id/chatScrollView"
|
||||
android:paddingTop="5dp"
|
||||
android:layout_weight="1"
|
||||
|
@ -47,7 +47,7 @@
|
|||
|
||||
</RelativeLayout>
|
||||
|
||||
</ScrollView>
|
||||
</org.linphone.ui.LinphoneScrollView>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/messageLayout"
|
||||
|
|
|
@ -41,6 +41,8 @@ import org.linphone.core.LinphoneChatRoom;
|
|||
import org.linphone.core.LinphoneCore;
|
||||
import org.linphone.ui.AvatarWithShadow;
|
||||
import org.linphone.ui.BubbleChat;
|
||||
import org.linphone.ui.LinphoneScrollView;
|
||||
import org.linphone.ui.ScrollViewListener;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
|
@ -79,7 +81,6 @@ import android.widget.EditText;
|
|||
import android.widget.ImageView;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.ScrollView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
|
@ -99,6 +100,7 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
|
|||
private static final int SIZE_SMALL = 500;
|
||||
private static final int SIZE_MEDIUM = 1000;
|
||||
private static final int SIZE_LARGE = 1500;
|
||||
private static final int MESSAGES_STEP = 20;
|
||||
|
||||
private LinphoneChatRoom chatRoom;
|
||||
private View view;
|
||||
|
@ -108,11 +110,13 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
|
|||
private TextView sendImage, sendMessage, contactName;
|
||||
private AvatarWithShadow contactPicture;
|
||||
private RelativeLayout messagesLayout, uploadLayout, textLayout;
|
||||
private ScrollView messagesScrollView;
|
||||
private LinphoneScrollView messagesScrollView;
|
||||
private int previousMessageID;
|
||||
private Handler mHandler = new Handler();
|
||||
private BubbleChat lastSentMessageBubble;
|
||||
private HashMap<Integer, String> latestImageMessages;
|
||||
private int messagesFilterLimit = 0;
|
||||
private List<ChatMessage> messagesList;
|
||||
|
||||
private ProgressBar progressBar;
|
||||
private int bytesSent;
|
||||
|
@ -148,7 +152,7 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
|
|||
textLayout = (RelativeLayout) view.findViewById(R.id.messageLayout);
|
||||
|
||||
messagesLayout = (RelativeLayout) view.findViewById(R.id.messages);
|
||||
messagesScrollView = (ScrollView) view.findViewById(R.id.chatScrollView);
|
||||
messagesScrollView = (LinphoneScrollView) view.findViewById(R.id.chatScrollView);
|
||||
progressBar = (ProgressBar) view.findViewById(R.id.progressbar);
|
||||
|
||||
sendImage = (TextView) view.findViewById(R.id.sendPicture);
|
||||
|
@ -171,6 +175,9 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
|
|||
}
|
||||
});
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
messagesFilterLimit = savedInstanceState.getInt("messagesFilterLimit");
|
||||
}
|
||||
displayChat(displayName, pictureUri);
|
||||
|
||||
LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
|
||||
|
@ -223,10 +230,15 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
|
|||
return view;
|
||||
}
|
||||
|
||||
private void refreshMessages() {
|
||||
messagesList = LinphoneActivity.instance().getChatMessages(sipUri);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
outState.putString("fileToUploadPath", fileToUploadPath);
|
||||
outState.putParcelable("imageToUpload", imageToUpload);
|
||||
outState.putInt("messagesFilterLimit", messagesFilterLimit);
|
||||
super.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
|
@ -255,32 +267,73 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
|
|||
public void showKeyboardVisibleMode() {
|
||||
LinphoneActivity.instance().hideMenu(true);
|
||||
contactPicture.setVisibility(View.GONE);
|
||||
scrollToEnd();
|
||||
//scrollToEnd();
|
||||
}
|
||||
|
||||
public void hideKeyboardVisibleMode() {
|
||||
LinphoneActivity.instance().hideMenu(false);
|
||||
contactPicture.setVisibility(View.VISIBLE);
|
||||
scrollToEnd();
|
||||
//scrollToEnd();
|
||||
}
|
||||
|
||||
private void invalidate() {
|
||||
messagesLayout.removeAllViews();
|
||||
List<ChatMessage> messagesList = LinphoneActivity.instance().getChatMessages(sipUri);
|
||||
refreshMessages();
|
||||
|
||||
previousMessageID = -1;
|
||||
ChatStorage chatStorage = LinphoneActivity.instance().getChatStorage();
|
||||
for (ChatMessage msg : messagesList) {
|
||||
if (msg.getMessage() != null) {
|
||||
displayMessage(msg.getId(), msg.getMessage(), msg.getTimestamp(), msg.isIncoming(), msg.getStatus(), messagesLayout);
|
||||
} else {
|
||||
displayImageMessage(msg.getId(), msg.getImage(), msg.getTimestamp(), msg.isIncoming(), msg.getStatus(), messagesLayout);
|
||||
}
|
||||
chatStorage.markMessageAsRead(msg.getId());
|
||||
}
|
||||
LinphoneActivity.instance().updateMissedChatCount();
|
||||
|
||||
scrollToEnd();
|
||||
if (messagesFilterLimit == 0) {
|
||||
if (messagesList.size() > MESSAGES_STEP)
|
||||
messagesFilterLimit = MESSAGES_STEP;
|
||||
else
|
||||
messagesFilterLimit = messagesList.size();
|
||||
} else {
|
||||
if (messagesFilterLimit + MESSAGES_STEP <= messagesList.size())
|
||||
messagesFilterLimit += MESSAGES_STEP;
|
||||
else
|
||||
messagesFilterLimit = messagesList.size();
|
||||
}
|
||||
invalidate(messagesFilterLimit);
|
||||
}
|
||||
|
||||
private void invalidate(final int limit) {
|
||||
messagesLayout.removeAllViews();
|
||||
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
previousMessageID = -1;
|
||||
ChatStorage chatStorage = LinphoneActivity.instance().getChatStorage();
|
||||
|
||||
for (int i = messagesList.size() - limit; i < messagesList.size(); i++) {
|
||||
ChatMessage msg = messagesList.get(i);
|
||||
if (msg.getMessage() != null) {
|
||||
displayMessage(msg.getId(), msg.getMessage(), msg.getTimestamp(), msg.isIncoming(), msg.getStatus(), messagesLayout);
|
||||
} else {
|
||||
displayImageMessage(msg.getId(), msg.getImage(), msg.getTimestamp(), msg.isIncoming(), msg.getStatus(), messagesLayout);
|
||||
}
|
||||
|
||||
if (!msg.isRed())
|
||||
chatStorage.markMessageAsRead(msg.getId());
|
||||
}
|
||||
LinphoneActivity.instance().updateMissedChatCount();
|
||||
|
||||
if (limit < messagesList.size()) {
|
||||
messagesScrollView.setScrollViewListener(new ScrollViewListener() {
|
||||
@Override
|
||||
public void OnScrollToTop(final int previousHeight) {
|
||||
invalidate();mHandler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
//Scroll to latest saw message
|
||||
messagesScrollView.scrollTo(0, messagesLayout.getChildAt(MESSAGES_STEP-1).getBottom());
|
||||
}
|
||||
}, 300);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
messagesScrollView.setScrollViewListener(null);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void displayChat(String displayName, String pictureUri) {
|
||||
|
@ -288,8 +341,7 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
|
|||
contactName.setText(LinphoneUtils.getUsernameFromAddress(sipUri));
|
||||
} else if (displayName == null) {
|
||||
contactName.setText(sipUri);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
contactName.setText(displayName);
|
||||
}
|
||||
|
||||
|
@ -299,44 +351,37 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
|
|||
contactPicture.setImageResource(R.drawable.unknown_small);
|
||||
}
|
||||
|
||||
messagesScrollView.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
scrollToEnd();
|
||||
}
|
||||
});
|
||||
if (messagesFilterLimit == 0)
|
||||
invalidate();
|
||||
else {
|
||||
invalidate(messagesFilterLimit);
|
||||
}
|
||||
|
||||
invalidate();
|
||||
scrollToEnd();
|
||||
}
|
||||
|
||||
private void displayMessage(final int id, final String message, final String time, final boolean isIncoming, final LinphoneChatMessage.State status, final RelativeLayout layout) {
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
BubbleChat bubble = new BubbleChat(layout.getContext(), id, message, null, time, isIncoming, status, previousMessageID);
|
||||
if (!isIncoming) {
|
||||
lastSentMessageBubble = bubble;
|
||||
}
|
||||
previousMessageID = id;
|
||||
layout.addView(bubble.getView());
|
||||
registerForContextMenu(bubble.getView());
|
||||
}
|
||||
});
|
||||
private void displayMessage(int id, String message, String time, boolean isIncoming, LinphoneChatMessage.State status, RelativeLayout layout) {
|
||||
BubbleChat bubble = new BubbleChat(layout.getContext(), id, message, null, time, isIncoming, status, previousMessageID);
|
||||
if (!isIncoming) {
|
||||
lastSentMessageBubble = bubble;
|
||||
}
|
||||
|
||||
View v = bubble.getView();
|
||||
previousMessageID = id;
|
||||
layout.addView(v);
|
||||
registerForContextMenu(v);
|
||||
}
|
||||
|
||||
private void displayImageMessage(final int id, final Bitmap image, final String time, final boolean isIncoming, final LinphoneChatMessage.State status, final RelativeLayout layout) {
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
BubbleChat bubble = new BubbleChat(layout.getContext(), id, null, image, time, isIncoming, status, previousMessageID);
|
||||
if (!isIncoming) {
|
||||
lastSentMessageBubble = bubble;
|
||||
}
|
||||
previousMessageID = id;
|
||||
layout.addView(bubble.getView());
|
||||
registerForContextMenu(bubble.getView());
|
||||
}
|
||||
});
|
||||
private void displayImageMessage(int id, Bitmap image, String time, boolean isIncoming, LinphoneChatMessage.State status, RelativeLayout layout) {
|
||||
BubbleChat bubble = new BubbleChat(layout.getContext(), id, null, image, time, isIncoming, status, previousMessageID);
|
||||
if (!isIncoming) {
|
||||
lastSentMessageBubble = bubble;
|
||||
}
|
||||
|
||||
View v = bubble.getView();
|
||||
previousMessageID = id;
|
||||
layout.addView(v);
|
||||
registerForContextMenu(v);
|
||||
}
|
||||
|
||||
public void changeDisplayedChat(String newSipUri, String displayName, String pictureUri) {
|
||||
|
@ -351,6 +396,7 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
|
|||
LinphoneActivity.instance().getChatStorage().deleteDraft(sipUri);
|
||||
}
|
||||
|
||||
messagesFilterLimit = 0;
|
||||
sipUri = newSipUri;
|
||||
if (LinphoneActivity.isInstanciated()) {
|
||||
String draft = LinphoneActivity.instance().getChatStorage().getDraft(sipUri);
|
||||
|
@ -444,7 +490,6 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
|
|||
LinphoneActivity.instance().selectMenu(FragmentsAvailable.CHAT);
|
||||
LinphoneActivity.instance().updateChatFragment(this);
|
||||
}
|
||||
scrollToEnd();
|
||||
|
||||
if (LinphoneActivity.isInstanciated()) {
|
||||
String draft = LinphoneActivity.instance().getChatStorage().getDraft(sipUri);
|
||||
|
@ -503,7 +548,7 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
|
|||
}
|
||||
|
||||
private void scrollToEnd() {
|
||||
mHandler.postDelayed(new Runnable() {
|
||||
messagesScrollView.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
messagesScrollView.fullScroll(View.FOCUS_DOWN);
|
||||
|
@ -519,14 +564,24 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
|
|||
}
|
||||
}
|
||||
|
||||
public void onMessageReceived(int id, LinphoneAddress from, LinphoneChatMessage message) {
|
||||
public void onMessageReceived(final int id, LinphoneAddress from, final LinphoneChatMessage message) {
|
||||
if (from.asStringUriOnly().equals(sipUri)) {
|
||||
if (message.getText() != null) {
|
||||
displayMessage(id, message.getText(), String.valueOf(System.currentTimeMillis()), true, null, messagesLayout);
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
displayMessage(id, message.getText(), String.valueOf(System.currentTimeMillis()), true, null, messagesLayout);
|
||||
}
|
||||
});
|
||||
} else if (message.getExternalBodyUrl() != null) {
|
||||
byte[] rawImage = LinphoneActivity.instance().getChatStorage().getRawImageFromMessage(id);
|
||||
Bitmap bm = BitmapFactory.decodeByteArray(rawImage, 0, rawImage.length);
|
||||
displayImageMessage(id, bm, String.valueOf(System.currentTimeMillis()), true, null, messagesLayout);
|
||||
final Bitmap bm = BitmapFactory.decodeByteArray(rawImage, 0, rawImage.length);
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
displayImageMessage(id, bm, String.valueOf(System.currentTimeMillis()), true, null, messagesLayout);
|
||||
}
|
||||
});
|
||||
}
|
||||
scrollToEnd();
|
||||
}
|
||||
|
|
|
@ -33,8 +33,9 @@ public class ChatMessage {
|
|||
private int status;
|
||||
private int id;
|
||||
private Bitmap image;
|
||||
private boolean isRed;
|
||||
|
||||
public ChatMessage(int id, String message, byte[] rawImage, String timestamp, boolean incoming, int status) {
|
||||
public ChatMessage(int id, String message, byte[] rawImage, String timestamp, boolean incoming, int status, boolean red) {
|
||||
super();
|
||||
this.id = id;
|
||||
this.message = message;
|
||||
|
@ -42,6 +43,7 @@ public class ChatMessage {
|
|||
this.incoming = incoming;
|
||||
this.status = status;
|
||||
this.image = rawImage != null ? BitmapFactory.decodeByteArray(rawImage, 0, rawImage.length) : null;
|
||||
this.isRed = red;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
|
@ -83,4 +85,8 @@ public class ChatMessage {
|
|||
public Bitmap getImage() {
|
||||
return image;
|
||||
}
|
||||
|
||||
public boolean isRed() {
|
||||
return isRed;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,13 +55,23 @@ public class ChatStorage {
|
|||
}
|
||||
|
||||
public void updateMessageStatus(String to, String message, int status) {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put("status", status);
|
||||
|
||||
String where = "direction LIKE ? AND remoteContact LIKE ? AND message LIKE ?";
|
||||
String[] whereArgs = { String.valueOf(OUTGOING), to, message };
|
||||
Cursor c = db.query(TABLE_NAME, null, "direction LIKE ? AND remoteContact LIKE ? AND message LIKE ?", whereArgs, null, null, "id DESC");
|
||||
|
||||
String id = null;
|
||||
if (c.moveToFirst()) {
|
||||
try {
|
||||
id = c.getString(c.getColumnIndex("id"));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
c.close();
|
||||
|
||||
db.update(TABLE_NAME, values, where, whereArgs);
|
||||
if (id != null && id.length() > 0) {
|
||||
int intID = Integer.parseInt(id);
|
||||
updateMessageStatus(to, intID, status);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateMessageStatus(String to, int id, int status) {
|
||||
|
@ -183,8 +193,9 @@ public class ChatStorage {
|
|||
timestamp = c.getString(c.getColumnIndex("time"));
|
||||
int status = c.getInt(c.getColumnIndex("status"));
|
||||
byte[] rawImage = c.getBlob(c.getColumnIndex("image"));
|
||||
int read = c.getInt(c.getColumnIndex("read"));
|
||||
|
||||
ChatMessage chatMessage = new ChatMessage(id, message, rawImage, timestamp, direction == INCOMING, status);
|
||||
ChatMessage chatMessage = new ChatMessage(id, message, rawImage, timestamp, direction == INCOMING, status, read == READ);
|
||||
chatMessages.add(chatMessage);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
|
|
|
@ -407,6 +407,7 @@ public class InCallActivity extends FragmentActivity implements
|
|||
}
|
||||
else if (id == R.id.routeBluetooth) {
|
||||
LinphoneManager.getInstance().routeAudioToBluetooth();
|
||||
isSpeakerEnabled = false;
|
||||
routeBluetooth.setBackgroundResource(R.drawable.route_bluetooth_on);
|
||||
routeReceiver.setBackgroundResource(R.drawable.route_receiver_off);
|
||||
routeSpeaker.setBackgroundResource(R.drawable.route_speaker_off);
|
||||
|
@ -414,6 +415,7 @@ public class InCallActivity extends FragmentActivity implements
|
|||
}
|
||||
else if (id == R.id.routeReceiver) {
|
||||
LinphoneManager.getInstance().routeAudioToReceiver();
|
||||
isSpeakerEnabled = false;
|
||||
routeBluetooth.setBackgroundResource(R.drawable.route_bluetooth_off);
|
||||
routeReceiver.setBackgroundResource(R.drawable.route_receiver_on);
|
||||
routeSpeaker.setBackgroundResource(R.drawable.route_speaker_off);
|
||||
|
@ -421,6 +423,7 @@ public class InCallActivity extends FragmentActivity implements
|
|||
}
|
||||
else if (id == R.id.routeSpeaker) {
|
||||
LinphoneManager.getInstance().routeAudioToSpeaker();
|
||||
isSpeakerEnabled = true;
|
||||
routeBluetooth.setBackgroundResource(R.drawable.route_bluetooth_off);
|
||||
routeReceiver.setBackgroundResource(R.drawable.route_receiver_off);
|
||||
routeSpeaker.setBackgroundResource(R.drawable.route_speaker_on);
|
||||
|
@ -940,24 +943,7 @@ public class InCallActivity extends FragmentActivity implements
|
|||
}
|
||||
|
||||
private void hideOrDisplayAudioRoutes()
|
||||
{
|
||||
if (isSpeakerEnabled) {
|
||||
speaker.setBackgroundResource(R.drawable.speaker_on);
|
||||
routeSpeaker.setBackgroundResource(R.drawable.route_speaker_on);
|
||||
routeReceiver.setBackgroundResource(R.drawable.route_receiver_off);
|
||||
routeBluetooth.setBackgroundResource(R.drawable.route_bluetooth_off);
|
||||
} else {
|
||||
speaker.setBackgroundResource(R.drawable.speaker_off);
|
||||
routeSpeaker.setBackgroundResource(R.drawable.route_speaker_off);
|
||||
if (LinphoneManager.getInstance().isUsingBluetoothAudioRoute) {
|
||||
routeReceiver.setBackgroundResource(R.drawable.route_receiver_off);
|
||||
routeBluetooth.setBackgroundResource(R.drawable.route_bluetooth_on);
|
||||
} else {
|
||||
routeReceiver.setBackgroundResource(R.drawable.route_receiver_on);
|
||||
routeBluetooth.setBackgroundResource(R.drawable.route_bluetooth_off);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
if (routeSpeaker.getVisibility() == View.VISIBLE) {
|
||||
routeSpeaker.setVisibility(View.INVISIBLE);
|
||||
routeBluetooth.setVisibility(View.INVISIBLE);
|
||||
|
|
|
@ -971,7 +971,13 @@ public final class LinphoneManager implements LinphoneCoreListener {
|
|||
mLc.enablePayloadType(videoCodec, enable);
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||
private void doDestroy() {
|
||||
try {
|
||||
if (Version.sdkAboveOrEqual(Version.API11_HONEYCOMB_30))
|
||||
mBluetoothAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset);
|
||||
} catch (Exception e) {}
|
||||
|
||||
try {
|
||||
mTimer.cancel();
|
||||
mLc.destroy();
|
||||
|
|
56
src/org/linphone/ui/LinphoneScrollView.java
Normal file
|
@ -0,0 +1,56 @@
|
|||
package org.linphone.ui;
|
||||
/*
|
||||
LinphoneScrollView.java
|
||||
Copyright (C) 2013 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.
|
||||
*/
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.ScrollView;
|
||||
|
||||
/**
|
||||
* @author Sylvain Berfini
|
||||
*/
|
||||
public class LinphoneScrollView extends ScrollView {
|
||||
private ScrollViewListener scrollViewListener = null;
|
||||
|
||||
public LinphoneScrollView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public LinphoneScrollView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
public LinphoneScrollView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public void setScrollViewListener(ScrollViewListener scrollViewListener) {
|
||||
this.scrollViewListener = scrollViewListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onScrollChanged(int x, int y, int oldx, int oldy) {
|
||||
super.onScrollChanged(x, y, oldx, oldy);
|
||||
if (y >= getMeasuredHeight() && scrollViewListener != null) {
|
||||
//scrollViewListener.OnScrollToBottom();
|
||||
}
|
||||
else if (y == 0 && scrollViewListener != null) {
|
||||
scrollViewListener.OnScrollToTop(getMeasuredHeight());
|
||||
}
|
||||
}
|
||||
}
|
26
src/org/linphone/ui/ScrollViewListener.java
Normal file
|
@ -0,0 +1,26 @@
|
|||
package org.linphone.ui;
|
||||
/*
|
||||
ScrollViewListener.java
|
||||
Copyright (C) 2013 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
|
||||
*/
|
||||
public interface ScrollViewListener {
|
||||
void OnScrollToTop(int previousHeight);
|
||||
}
|