display geo uris as location. show 'send loction' in share menu if request location intent can be resolved

This commit is contained in:
iNPUTmice 2015-03-07 14:15:38 +01:00
parent cbca92d209
commit 87a048fe6f
7 changed files with 230 additions and 53 deletions

View file

@ -8,6 +8,7 @@ import java.net.URL;
import java.util.Arrays;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.utils.GeoHelper;
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
import eu.siacs.conversations.xmpp.jid.Jid;
@ -49,6 +50,7 @@ public class Message extends AbstractEntity {
public static final String RELATIVE_FILE_PATH = "relativeFilePath";
public static final String ME_COMMAND = "/me ";
public boolean markable = false;
protected String conversationUuid;
protected Jid counterpart;
@ -368,6 +370,8 @@ public class Message extends AbstractEntity {
this.getCounterpart() != null &&
this.getCounterpart().equals(message.getCounterpart()) &&
(message.getTimeSent() - this.getTimeSent()) <= (Config.MESSAGE_MERGE_WINDOW * 1000) &&
!GeoHelper.isGeoUri(message.getBody()) &&
!GeoHelper.isGeoUri(this.body) &&
!message.bodyContainsDownloadable() &&
!this.bodyContainsDownloadable() &&
!message.getBody().startsWith(ME_COMMAND) &&

View file

@ -306,6 +306,24 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
return this.mAvatarService;
}
public void attachLocationToConversation(final Conversation conversation,
final Uri uri,
final UiCallback<Message> callback) {
int encryption = conversation.getNextEncryption(forceEncryption());
if (encryption == Message.ENCRYPTION_PGP) {
encryption = Message.ENCRYPTION_DECRYPTED;
}
Message message = new Message(conversation,uri.toString(),encryption);
if (conversation.getNextCounterpart() != null) {
message.setCounterpart(conversation.getNextCounterpart());
}
if (encryption == Message.ENCRYPTION_DECRYPTED) {
getPgpEngine().encrypt(message,callback);
} else {
callback.success(message);
}
}
public void attachFileToConversation(final Conversation conversation,
final Uri uri,
final UiCallback<Message> callback) {

View file

@ -33,7 +33,6 @@ import java.util.ArrayList;
import java.util.List;
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Blockable;
import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.entities.Conversation;
@ -63,6 +62,7 @@ public class ConversationActivity extends XmppActivity
private static final int ATTACHMENT_CHOICE_TAKE_PHOTO = 0x0302;
private static final int ATTACHMENT_CHOICE_CHOOSE_FILE = 0x0303;
private static final int ATTACHMENT_CHOICE_RECORD_VOICE = 0x0304;
private static final int ATTACHMENT_CHOICE_LOCATION = 0x0305;
private static final String STATE_OPEN_CONVERSATION = "state_open_conversation";
private static final String STATE_PANEL_OPEN = "state_panel_open";
private static final String STATE_PENDING_URI = "state_pending_uri";
@ -71,6 +71,7 @@ public class ConversationActivity extends XmppActivity
private boolean mPanelOpen = true;
private Uri mPendingImageUri = null;
private Uri mPendingFileUri = null;
private Uri mPendingGeoUri = null;
private View mContentView;
@ -313,7 +314,6 @@ public class ConversationActivity extends XmppActivity
menuInviteContact.setVisible(getSelectedConversation().getMucOptions().canInvite());
} else {
menuMucDetails.setVisible(false);
final Account account = this.getSelectedConversation().getAccount();
}
if (this.getSelectedConversation().isMuted()) {
menuMute.setVisible(false);
@ -325,50 +325,60 @@ public class ConversationActivity extends XmppActivity
return true;
}
private void selectPresenceToAttachFile(final int attachmentChoice) {
selectPresence(getSelectedConversation(), new OnPresenceSelected() {
private void selectPresenceToAttachFile(final int attachmentChoice, final int encryption) {
if (attachmentChoice == ATTACHMENT_CHOICE_LOCATION && encryption != Message.ENCRYPTION_OTR) {
getSelectedConversation().setNextCounterpart(null);
Intent intent = new Intent("eu.siacs.conversations.location.request");
startActivityForResult(intent,attachmentChoice);
} else {
selectPresence(getSelectedConversation(), new OnPresenceSelected() {
@Override
public void onPresenceSelected() {
Intent intent = new Intent();
boolean chooser = false;
switch (attachmentChoice) {
case ATTACHMENT_CHOICE_CHOOSE_IMAGE:
intent.setAction(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
chooser = true;
break;
case ATTACHMENT_CHOICE_TAKE_PHOTO:
mPendingImageUri = xmppConnectionService.getFileBackend().getTakePhotoUri();
intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT,mPendingImageUri);
break;
case ATTACHMENT_CHOICE_CHOOSE_FILE:
chooser = true;
intent.setType("*/*");
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setAction(Intent.ACTION_GET_CONTENT);
break;
case ATTACHMENT_CHOICE_RECORD_VOICE:
intent.setAction(MediaStore.Audio.Media.RECORD_SOUND_ACTION);
break;
}
if (intent.resolveActivity(getPackageManager()) != null) {
if (chooser) {
startActivityForResult(
Intent.createChooser(intent,getString(R.string.perform_action_with)),
attachmentChoice);
} else {
startActivityForResult(intent, attachmentChoice);
@Override
public void onPresenceSelected() {
Intent intent = new Intent();
boolean chooser = false;
switch (attachmentChoice) {
case ATTACHMENT_CHOICE_CHOOSE_IMAGE:
intent.setAction(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
chooser = true;
break;
case ATTACHMENT_CHOICE_TAKE_PHOTO:
mPendingImageUri = xmppConnectionService.getFileBackend().getTakePhotoUri();
intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, mPendingImageUri);
break;
case ATTACHMENT_CHOICE_CHOOSE_FILE:
chooser = true;
intent.setType("*/*");
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setAction(Intent.ACTION_GET_CONTENT);
break;
case ATTACHMENT_CHOICE_RECORD_VOICE:
intent.setAction(MediaStore.Audio.Media.RECORD_SOUND_ACTION);
break;
case ATTACHMENT_CHOICE_LOCATION:
intent.setAction("eu.siacs.conversations.location.request");
break;
}
if (intent.resolveActivity(getPackageManager()) != null) {
if (chooser) {
startActivityForResult(
Intent.createChooser(intent, getString(R.string.perform_action_with)),
attachmentChoice);
} else {
startActivityForResult(intent, attachmentChoice);
}
}
}
}
});
});
}
}
private void attachFile(final int attachmentChoice) {
final Conversation conversation = getSelectedConversation();
if (conversation.getNextEncryption(forceEncryption()) == Message.ENCRYPTION_PGP) {
final int encryption = conversation.getNextEncryption(forceEncryption());
if (encryption == Message.ENCRYPTION_PGP) {
if (hasPgp()) {
if (conversation.getContact().getPgpKeyId() != 0) {
xmppConnectionService.getPgpEngine().hasKey(
@ -378,13 +388,12 @@ public class ConversationActivity extends XmppActivity
@Override
public void userInputRequried(PendingIntent pi,
Contact contact) {
ConversationActivity.this.runIntent(pi,
attachmentChoice);
ConversationActivity.this.runIntent(pi,attachmentChoice);
}
@Override
public void success(Contact contact) {
selectPresenceToAttachFile(attachmentChoice);
selectPresenceToAttachFile(attachmentChoice,encryption);
}
@Override
@ -406,7 +415,7 @@ public class ConversationActivity extends XmppActivity
.setNextEncryption(Message.ENCRYPTION_NONE);
xmppConnectionService.databaseBackend
.updateConversation(conversation);
selectPresenceToAttachFile(attachmentChoice);
selectPresenceToAttachFile(attachmentChoice,Message.ENCRYPTION_NONE);
}
});
}
@ -414,11 +423,8 @@ public class ConversationActivity extends XmppActivity
} else {
showInstallPgpDialog();
}
} else if (getSelectedConversation().getNextEncryption(
forceEncryption()) == Message.ENCRYPTION_NONE) {
selectPresenceToAttachFile(attachmentChoice);
} else {
selectPresenceToAttachFile(attachmentChoice);
selectPresenceToAttachFile(attachmentChoice,encryption);
}
}
@ -526,6 +532,9 @@ public class ConversationActivity extends XmppActivity
if (new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION).resolveActivity(getPackageManager()) == null) {
attachFilePopup.getMenu().findItem(R.id.attach_record_voice).setVisible(false);
}
if (new Intent("eu.siacs.conversations.location.request").resolveActivity(getPackageManager()) == null) {
attachFilePopup.getMenu().findItem(R.id.attach_location).setVisible(false);
}
attachFilePopup.setOnMenuItemClickListener(new OnMenuItemClickListener() {
@Override
@ -543,6 +552,9 @@ public class ConversationActivity extends XmppActivity
case R.id.attach_record_voice:
attachFile(ATTACHMENT_CHOICE_RECORD_VOICE);
break;
case R.id.attach_location:
attachFile(ATTACHMENT_CHOICE_LOCATION);
break;
}
return false;
}
@ -809,6 +821,7 @@ public class ConversationActivity extends XmppActivity
showConversationsOverview();
mPendingImageUri = null;
mPendingFileUri = null;
mPendingGeoUri = null;
setSelectedConversation(conversationList.get(0));
this.mConversationFragment.reInit(getSelectedConversation());
}
@ -819,6 +832,9 @@ public class ConversationActivity extends XmppActivity
} else if (mPendingFileUri != null) {
attachFileToConversation(getSelectedConversation(),mPendingFileUri);
mPendingFileUri = null;
} else if (mPendingGeoUri != null) {
attachLocationToConversation(getSelectedConversation(),mPendingGeoUri);
mPendingGeoUri = null;
}
ExceptionHelper.checkForCrash(this, this.xmppConnectionService);
setIntent(new Intent());
@ -897,6 +913,14 @@ public class ConversationActivity extends XmppActivity
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
intent.setData(mPendingImageUri);
sendBroadcast(intent);
} else if (requestCode == ATTACHMENT_CHOICE_LOCATION) {
double latitude = data.getDoubleExtra("latitude",0);
double longitude = data.getDoubleExtra("longitude",0);
this.mPendingGeoUri = Uri.parse("geo:"+String.valueOf(latitude)+","+String.valueOf(longitude));
if (xmppConnectionServiceBound) {
attachLocationToConversation(getSelectedConversation(), mPendingGeoUri);
this.mPendingGeoUri = null;
}
}
} else {
if (requestCode == ATTACHMENT_CHOICE_TAKE_PHOTO) {
@ -905,6 +929,26 @@ public class ConversationActivity extends XmppActivity
}
}
private void attachLocationToConversation(Conversation conversation, Uri uri) {
xmppConnectionService.attachLocationToConversation(conversation,uri, new UiCallback<Message>() {
@Override
public void success(Message message) {
xmppConnectionService.sendMessage(message);
}
@Override
public void error(int errorCode, Message object) {
}
@Override
public void userInputRequried(PendingIntent pi, Message object) {
}
});
}
private void attachFileToConversation(Conversation conversation, Uri uri) {
prepareFileToast = Toast.makeText(getApplicationContext(),
getText(R.string.preparing_file), Toast.LENGTH_LONG);

View file

@ -34,6 +34,7 @@ import eu.siacs.conversations.entities.DownloadableFile;
import eu.siacs.conversations.entities.Message;
import eu.siacs.conversations.entities.Message.ImageParams;
import eu.siacs.conversations.ui.ConversationActivity;
import eu.siacs.conversations.utils.GeoHelper;
import eu.siacs.conversations.utils.UIHelper;
public class MessageAdapter extends ArrayAdapter<Message> {
@ -299,6 +300,21 @@ public class MessageAdapter extends ArrayAdapter<Message> {
viewHolder.download_button.setOnLongClickListener(openContextMenu);
}
private void displayLocationMessage(ViewHolder viewHolder, final Message message) {
viewHolder.image.setVisibility(View.GONE);
viewHolder.messageBody.setVisibility(View.GONE);
viewHolder.download_button.setVisibility(View.VISIBLE);
viewHolder.download_button.setText(R.string.show_location);
viewHolder.download_button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
showLocation(message);
}
});
viewHolder.download_button.setOnLongClickListener(openContextMenu);
}
private void displayImageMessage(ViewHolder viewHolder,
final Message message) {
if (viewHolder.download_button != null) {
@ -509,7 +525,11 @@ public class MessageAdapter extends ArrayAdapter<Message> {
} else if (message.getEncryption() == Message.ENCRYPTION_DECRYPTION_FAILED) {
displayDecryptionFailed(viewHolder);
} else {
displayTextMessage(viewHolder, message);
if (GeoHelper.isGeoUri(message.getBody())) {
displayLocationMessage(viewHolder,message);
} else {
displayTextMessage(viewHolder, message);
}
}
displayStatus(viewHolder, message);
@ -544,6 +564,16 @@ public class MessageAdapter extends ArrayAdapter<Message> {
}
}
public void showLocation(Message message) {
for(Intent intent : GeoHelper.createGeoIntentsFromMessage(message)) {
if (intent.resolveActivity(getContext().getPackageManager()) != null) {
getContext().startActivity(intent);
return;
}
}
Toast.makeText(activity,R.string.no_application_found_to_display_location,Toast.LENGTH_SHORT).show();
}
public interface OnContactPictureClicked {
public void onContactPictureClicked(Message message);
}

View file

@ -0,0 +1,71 @@
package eu.siacs.conversations.utils;
import android.content.Intent;
import android.net.Uri;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.Message;
public class GeoHelper {
private static Pattern GEO_URI = Pattern.compile("geo:([\\-0-9.]+),([\\-0-9.]+)(?:,([\\-0-9.]+))?(?:\\?(.*))?", Pattern.CASE_INSENSITIVE);
public static boolean isGeoUri(String body) {
return body != null && GEO_URI.matcher(body).matches();
}
public static ArrayList<Intent> createGeoIntentsFromMessage(Message message) {
final ArrayList<Intent> intents = new ArrayList();
Matcher matcher = GEO_URI.matcher(message.getBody());
if (!matcher.matches()) {
return intents;
}
double latitude;
double longitude;
try {
latitude = Double.parseDouble(matcher.group(1));
if (latitude > 90.0 || latitude < -90.0) {
return intents;
}
longitude = Double.parseDouble(matcher.group(2));
if (longitude > 180.0 || longitude < -180.0) {
return intents;
}
} catch (NumberFormatException nfe) {
return intents;
}
final Conversation conversation = message.getConversation();
String label;
if (conversation.getMode() == Conversation.MODE_SINGLE && message.getStatus() == Message.STATUS_RECEIVED) {
try {
label = "(" + URLEncoder.encode(message.getConversation().getName(), "UTF-8") + ")";
} catch (UnsupportedEncodingException e) {
label = "";
}
} else {
label = "";
}
Intent locationPluginIntent = new Intent("eu.siacs.conversations.location.show");
locationPluginIntent.putExtra("latitude",latitude);
locationPluginIntent.putExtra("longitude",longitude);
if (conversation.getMode() == Conversation.MODE_SINGLE && message.getStatus() == Message.STATUS_RECEIVED) {
locationPluginIntent.putExtra("name",conversation.getName());
}
intents.add(locationPluginIntent);
Intent geoIntent = new Intent(Intent.ACTION_VIEW);
geoIntent.setData(Uri.parse("geo:" + String.valueOf(latitude) + "," + String.valueOf(longitude) + "?q=" + String.valueOf(latitude) + "," + String.valueOf(longitude) + label));
intents.add(geoIntent);
Intent httpIntent = new Intent(Intent.ACTION_VIEW);
httpIntent.setData(Uri.parse("https://maps.google.com/maps?q=loc:"+String.valueOf(latitude) + "," + String.valueOf(longitude) +label));
intents.add(httpIntent);
return intents;
}
}

View file

@ -2,14 +2,21 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/attach_choose_picture"
android:title="@string/attach_choose_picture"/>
android:id="@+id/attach_location"
android:title="@string/send_location"/>
<item
android:id="@+id/attach_record_voice"
android:title="@string/attach_record_voice"/>
<item
android:id="@+id/attach_take_picture"
android:title="@string/attach_take_picture"/>
<item
android:id="@+id/attach_record_voice"
android:title="@string/attach_record_voice"/>
<item
android:id="@+id/attach_choose_picture"
android:title="@string/attach_choose_picture"/>
<item
android:id="@+id/attach_choose_file"
android:title="@string/choose_file"/>

View file

@ -449,4 +449,7 @@
<string name="contact_has_stopped_typing">%s has stopped typing</string>
<string name="pref_chat_states">Typing notifications</string>
<string name="pref_chat_states_summary">Let your contact know when you are writing a new message</string>
<string name="send_location">Send location</string>
<string name="show_location">Show location</string>
<string name="no_application_found_to_display_location">No application found to display location</string>
</resources>