publish avatars
This commit is contained in:
parent
629ff3afcd
commit
f8b4d5f338
|
@ -76,12 +76,19 @@
|
|||
android:paddingRight="8dp" >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/explanation"
|
||||
android:id="@+id/account"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/primarytext"
|
||||
android:textSize="18sp"/>
|
||||
|
||||
<TextView
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/publish_avatar_explanation"
|
||||
android:textColor="@color/primarytext"
|
||||
android:textSize="18sp" />
|
||||
android:textSize="14sp" />
|
||||
</LinearLayout>
|
||||
|
||||
</RelativeLayout>
|
|
@ -270,5 +270,5 @@
|
|||
<string name="contact_has_read_up_to_this_point">%s has read up to this point</string>
|
||||
<string name="publish_avatar">Publish avatar</string>
|
||||
<string name="touch_to_choose_picture">Touch avatar to select picture from gallary</string>
|
||||
<string name="publish_avatar_explanation">Publish avatar for <b>%s</b>. Everyone subscribed to your presence updates will also be able to see this picture.</string>
|
||||
<string name="publish_avatar_explanation">Please note: Everyone subscribed to your presence updates will be allowed to see this picture.</string>
|
||||
</resources>
|
||||
|
|
|
@ -18,7 +18,8 @@ public abstract class AbstractGenerator {
|
|||
"http://jabber.org/protocol/muc",
|
||||
"jabber:x:conference",
|
||||
"http://jabber.org/protocol/caps",
|
||||
"http://jabber.org/protocol/disco#info"};
|
||||
"http://jabber.org/protocol/disco#info",
|
||||
"urn:xmpp:avatar:metadata+notify"};
|
||||
public final String IDENTITY_NAME = "Conversations 0.5";
|
||||
public final String IDENTITY_TYPE = "phone";
|
||||
/*public final String[] FEATURES = { "http://jabber.org/protocol/muc","http://jabber.org/protocol/disco#info", "http://jabber.org/protocol/disco#items", "http://jabber.org/protocol/caps" };
|
||||
|
|
|
@ -5,6 +5,7 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
|
||||
import eu.siacs.conversations.xml.Element;
|
||||
import eu.siacs.conversations.xmpp.pep.Avatar;
|
||||
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
||||
|
||||
public class IqGenerator extends AbstractGenerator {
|
||||
|
@ -28,4 +29,34 @@ public class IqGenerator extends AbstractGenerator {
|
|||
}
|
||||
return packet;
|
||||
}
|
||||
|
||||
protected IqPacket publish(String node, Element item) {
|
||||
IqPacket packet = new IqPacket(IqPacket.TYPE_SET);
|
||||
Element pubsub = packet.addChild("pubsub", "http://jabber.org/protocol/pubsub");
|
||||
Element publish = pubsub.addChild("publish");
|
||||
publish.setAttribute("node", node);
|
||||
publish.addChild(item);
|
||||
return packet;
|
||||
}
|
||||
|
||||
public IqPacket publishAvatar(Avatar avatar) {
|
||||
Element item = new Element("item");
|
||||
item.setAttribute("id", avatar.sha1sum);
|
||||
Element data = item.addChild("data","urn:xmpp:avatar:data");
|
||||
data.setContent(avatar.image);
|
||||
return publish("urn:xmpp:avatar:data", item);
|
||||
}
|
||||
|
||||
public IqPacket publishAvatarMetadata(Avatar avatar) {
|
||||
Element item = new Element("item");
|
||||
item.setAttribute("id", avatar.sha1sum);
|
||||
Element metadata = item.addChild("metadata","urn:xmpp:avatar:metadata");
|
||||
Element info = metadata.addChild("info");
|
||||
info.setAttribute("bytes",avatar.size);
|
||||
info.setAttribute("id",avatar.sha1sum);
|
||||
info.setAttribute("height",avatar.height);
|
||||
info.setAttribute("width",avatar.height);
|
||||
info.setAttribute("type", avatar.type);
|
||||
return publish("urn:xmpp:avatar:metadata",item);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package eu.siacs.conversations.parser;
|
||||
|
||||
import android.os.SystemClock;
|
||||
import android.util.Log;
|
||||
import net.java.otr4j.session.Session;
|
||||
import net.java.otr4j.session.SessionStatus;
|
||||
import eu.siacs.conversations.entities.Account;
|
||||
|
@ -213,6 +214,10 @@ public class MessageParser extends AbstractParser implements
|
|||
}
|
||||
|
||||
private void parseNormal(Element packet, Account account) {
|
||||
if (packet.hasChild("event","http://jabber.org/protocol/pubsub#event")) {
|
||||
Element event = packet.findChild("event","http://jabber.org/protocol/pubsub#event");
|
||||
parseEvent(event,packet.getAttribute("from"),account);
|
||||
}
|
||||
if (packet.hasChild("displayed", "urn:xmpp:chat-markers:0")) {
|
||||
String id = packet
|
||||
.findChild("displayed", "urn:xmpp:chat-markers:0")
|
||||
|
@ -254,6 +259,16 @@ public class MessageParser extends AbstractParser implements
|
|||
}
|
||||
}
|
||||
|
||||
private void parseEvent(Element event, String from, Account account) {
|
||||
Element items = event.findChild("items");
|
||||
String node = items.getAttribute("node");
|
||||
if (node!=null) {
|
||||
Log.d("xmppService",account.getJid()+": "+node+" from "+from);
|
||||
} else {
|
||||
Log.d("xmppService",event.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private String getPgpBody(Element message) {
|
||||
Element child = message.findChild("x", "jabber:x:encrypted");
|
||||
if (child == null) {
|
||||
|
@ -324,6 +339,9 @@ public class MessageParser extends AbstractParser implements
|
|||
} else if (packet.getType() == MessagePacket.TYPE_NORMAL) {
|
||||
this.parseNormal(packet, account);
|
||||
return;
|
||||
} else if (packet.getType() == MessagePacket.TYPE_HEADLINE) {
|
||||
this.parseHeadline(packet, account);
|
||||
return;
|
||||
}
|
||||
if ((message == null) || (message.getBody() == null)) {
|
||||
return;
|
||||
|
@ -346,4 +364,11 @@ public class MessageParser extends AbstractParser implements
|
|||
}
|
||||
mXmppConnectionService.notifyUi(conversation, notify);
|
||||
}
|
||||
|
||||
private void parseHeadline(MessagePacket packet, Account account) {
|
||||
if (packet.hasChild("event","http://jabber.org/protocol/pubsub#event")) {
|
||||
Element event = packet.findChild("event","http://jabber.org/protocol/pubsub#event");
|
||||
parseEvent(event,packet.getFrom(),account);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -261,7 +261,7 @@ public class FileBackend {
|
|||
mDigestOutputStream.write(avatar.getImageAsBytes());
|
||||
mDigestOutputStream.flush();
|
||||
mDigestOutputStream.close();
|
||||
Log.d("xmppService","sha1sum after write: "+CryptoHelper.bytesToHex(digest.digest()));
|
||||
avatar.size = file.length();
|
||||
} catch (FileNotFoundException e) {
|
||||
|
||||
} catch (IOException e) {
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
package eu.siacs.conversations.services;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
|
||||
public final class Defaults {
|
||||
public static final int AVATAR_SIZE = 192;
|
||||
public static final Bitmap.CompressFormat AVATAR_FORMAT = Bitmap.CompressFormat.WEBP;
|
||||
private Defaults() {
|
||||
|
||||
}
|
||||
}
|
|
@ -20,6 +20,7 @@ import de.duenndns.ssl.MemorizingTrustManager;
|
|||
import net.java.otr4j.OtrException;
|
||||
import net.java.otr4j.session.Session;
|
||||
import net.java.otr4j.session.SessionStatus;
|
||||
import eu.siacs.conversations.R;
|
||||
import eu.siacs.conversations.crypto.PgpEngine;
|
||||
import eu.siacs.conversations.entities.Account;
|
||||
import eu.siacs.conversations.entities.Bookmark;
|
||||
|
@ -1186,13 +1187,46 @@ public class XmppConnectionService extends Service {
|
|||
}
|
||||
|
||||
|
||||
public void pushAvatar(Account account, Uri image) {
|
||||
Avatar avatar = getFileBackend().getPepAvatar(image, 192, Bitmap.CompressFormat.WEBP);
|
||||
public void publishAvatar(Account account, Uri image, final UiCallback<Avatar> callback) {
|
||||
final Bitmap.CompressFormat format = Defaults.AVATAR_FORMAT;
|
||||
final int size = Defaults.AVATAR_SIZE;
|
||||
final Avatar avatar = getFileBackend().getPepAvatar(image, size, format);
|
||||
if (avatar!=null) {
|
||||
Log.d(LOGTAG,avatar.sha1sum);
|
||||
Log.d(LOGTAG,avatar.image);
|
||||
avatar.type = "image/webp";
|
||||
avatar.height = size;
|
||||
avatar.width = size;
|
||||
if (format.equals(Bitmap.CompressFormat.WEBP)) {
|
||||
avatar.type = "image/webp";
|
||||
} else if (format.equals(Bitmap.CompressFormat.JPEG)) {
|
||||
avatar.type = "image/jpeg";
|
||||
} else if (format.equals(Bitmap.CompressFormat.PNG)) {
|
||||
avatar.type = "image/png";
|
||||
}
|
||||
getFileBackend().save(avatar);
|
||||
IqPacket packet = this.mIqGenerator.publishAvatar(avatar);
|
||||
this.sendIqPacket(account, packet, new OnIqPacketReceived() {
|
||||
|
||||
@Override
|
||||
public void onIqPacketReceived(Account account, IqPacket result) {
|
||||
if (result.getType() == IqPacket.TYPE_RESULT) {
|
||||
IqPacket packet = XmppConnectionService.this.mIqGenerator.publishAvatarMetadata(avatar);
|
||||
sendIqPacket(account, packet, new OnIqPacketReceived() {
|
||||
|
||||
@Override
|
||||
public void onIqPacketReceived(Account account, IqPacket result) {
|
||||
if (result.getType() == IqPacket.TYPE_RESULT) {
|
||||
callback.success(avatar);
|
||||
} else {
|
||||
callback.error(R.string.error, avatar);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
callback.error(R.string.error, avatar);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
callback.error(R.string.error, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
package eu.siacs.conversations.ui;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.Button;
|
||||
|
@ -13,13 +14,14 @@ import android.widget.TextView;
|
|||
import eu.siacs.conversations.R;
|
||||
import eu.siacs.conversations.entities.Account;
|
||||
import eu.siacs.conversations.utils.PhoneHelper;
|
||||
import eu.siacs.conversations.xmpp.pep.Avatar;
|
||||
|
||||
public class PublishProfilePictureActivity extends XmppActivity {
|
||||
|
||||
private static final int REQUEST_CHOOSE_FILE = 0xac23;
|
||||
|
||||
private ImageView avatar;
|
||||
private TextView explanation;
|
||||
private TextView accountTextView;
|
||||
private Button cancelButton;
|
||||
private Button publishButton;
|
||||
|
||||
|
@ -27,21 +29,42 @@ public class PublishProfilePictureActivity extends XmppActivity {
|
|||
|
||||
private Account account;
|
||||
|
||||
private UiCallback<Avatar> avatarPublication = new UiCallback<Avatar>() {
|
||||
|
||||
@Override
|
||||
public void success(Avatar object) {
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(int errorCode, Avatar object) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void userInputRequried(PendingIntent pi, Avatar object) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_publish_profile_picture);
|
||||
this.avatar = (ImageView) findViewById(R.id.account_image);
|
||||
this.explanation = (TextView) findViewById(R.id.explanation);
|
||||
this.cancelButton = (Button) findViewById(R.id.cancel_button);
|
||||
this.publishButton = (Button) findViewById(R.id.publish_button);
|
||||
this.accountTextView = (TextView) findViewById(R.id.account);
|
||||
this.publishButton.setOnClickListener(new OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (avatarUri!=null) {
|
||||
xmppConnectionService.pushAvatar(account, avatarUri);
|
||||
finish();
|
||||
if (avatarUri != null) {
|
||||
disablePublishButton();
|
||||
xmppConnectionService.publishAvatar(account, avatarUri,
|
||||
avatarPublication);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -72,31 +95,42 @@ public class PublishProfilePictureActivity extends XmppActivity {
|
|||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if (resultCode == RESULT_OK) {
|
||||
if (requestCode == REQUEST_CHOOSE_FILE) {
|
||||
Log.d("xmppService","bla");
|
||||
this.avatarUri = data.getData();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem menuItem) {
|
||||
super.onOptionsItemSelected(menuItem);
|
||||
switch (menuItem.getItemId()) {
|
||||
case android.R.id.home:
|
||||
finish();
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBackendConnected() {
|
||||
if (getIntent()!=null) {
|
||||
if (getIntent() != null) {
|
||||
String jid = getIntent().getStringExtra("account");
|
||||
if (jid!=null) {
|
||||
if (jid != null) {
|
||||
this.account = xmppConnectionService.findAccountByJid(jid);
|
||||
if (this.avatarUri == null) {
|
||||
avatarUri = PhoneHelper.getSefliUri(getApplicationContext());
|
||||
avatarUri = PhoneHelper
|
||||
.getSefliUri(getApplicationContext());
|
||||
}
|
||||
loadImageIntoPreview(avatarUri);
|
||||
String explainText = getString(R.string.publish_avatar_explanation,account.getJid());
|
||||
this.explanation.setText(explainText);
|
||||
this.accountTextView.setText(this.account.getJid());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected void loadImageIntoPreview(Uri uri) {
|
||||
Bitmap bm = xmppConnectionService.getFileBackend().cropCenterSquare(uri, 384);
|
||||
Bitmap bm = xmppConnectionService.getFileBackend().cropCenterSquare(
|
||||
uri, 384);
|
||||
this.avatar.setImageBitmap(bm);
|
||||
enablePublishButton();
|
||||
}
|
||||
|
@ -106,4 +140,9 @@ public class PublishProfilePictureActivity extends XmppActivity {
|
|||
this.publishButton.setTextColor(getPrimaryTextColor());
|
||||
}
|
||||
|
||||
protected void disablePublishButton() {
|
||||
this.publishButton.setEnabled(false);
|
||||
this.publishButton.setTextColor(getSecondaryTextColor());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -144,4 +144,12 @@ public class Element {
|
|||
public void clearChildren() {
|
||||
this.children.clear();
|
||||
}
|
||||
|
||||
public void setAttribute(String name, long value) {
|
||||
this.setAttribute(name, ""+value);
|
||||
}
|
||||
|
||||
public void setAttribute(String name, int value) {
|
||||
this.setAttribute(name, ""+value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,9 @@ public class Avatar {
|
|||
public String type;
|
||||
public String sha1sum;
|
||||
public String image;
|
||||
public int height;
|
||||
public int width;
|
||||
public long size;
|
||||
public byte[] getImageAsBytes() {
|
||||
return Base64.decode(image, Base64.DEFAULT);
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ public class MessagePacket extends AbstractStanza {
|
|||
public static final int TYPE_NORMAL = 2;
|
||||
public static final int TYPE_GROUPCHAT = 3;
|
||||
public static final int TYPE_ERROR = 4;
|
||||
public static final int TYPE_HEADLINE = 5;
|
||||
|
||||
public MessagePacket() {
|
||||
super("message");
|
||||
|
@ -59,6 +60,8 @@ public class MessagePacket extends AbstractStanza {
|
|||
return TYPE_GROUPCHAT;
|
||||
} else if (type.equals("error")) {
|
||||
return TYPE_ERROR;
|
||||
} else if (type.equals("headline")) {
|
||||
return TYPE_HEADLINE;
|
||||
} else {
|
||||
return TYPE_UNKNOWN;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue