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) { | ||||
|  | ||||
							
								
								
									
										11
									
								
								src/eu/siacs/conversations/services/Defaults.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/eu/siacs/conversations/services/Defaults.java
									
									
									
									
									
										Normal file
									
								
							| @ -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
	
	Block a user
	 iNPUTmice
						iNPUTmice