aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--build.gradle2
-rw-r--r--src/main/java/eu/siacs/conversations/ui/ConversationActivity.java2
-rw-r--r--src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java96
-rw-r--r--src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java175
-rw-r--r--src/main/java/eu/siacs/conversations/ui/XmppActivity.java8
-rw-r--r--src/main/res/menu/editaccount.xml8
-rw-r--r--src/main/res/menu/start_conversation.xml16
-rw-r--r--src/main/res/values/strings.xml3
8 files changed, 235 insertions, 75 deletions
diff --git a/build.gradle b/build.gradle
index a37b92c4..e5edcb9a 100644
--- a/build.gradle
+++ b/build.gradle
@@ -34,6 +34,8 @@ dependencies {
compile 'com.android.support:support-v13:19.1.0'
compile 'org.bouncycastle:bcprov-jdk15on:1.50'
compile 'net.java:otr4j:0.21'
+ compile 'com.google.zxing:core:3.1.0'
+ compile 'com.google.zxing:android-integration:3.1.0'
}
android {
diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java
index 67f227d8..b4a8e56a 100644
--- a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java
@@ -88,7 +88,7 @@ public class ConversationActivity extends XmppActivity implements
public NdefMessage createNdefMessage(NfcEvent nfcEvent) {
Conversation conversation = getSelectedConversation();
NdefMessage msg = new NdefMessage(new NdefRecord[]{
- NdefRecord.createUri("xmpp:"+conversation.getAccount().getJid().getBytes()),
+ NdefRecord.createUri("xmpp:"+conversation.getAccount().getJid()),
NdefRecord.createApplicationRecord("eu.siacs.conversations")
});
return msg;
diff --git a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java
index 58ca49cc..4942816d 100644
--- a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java
@@ -1,23 +1,44 @@
package eu.siacs.conversations.ui;
+import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.graphics.Point;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
+import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.ImageButton;
+import android.widget.ImageView;
import android.widget.LinearLayout;
-import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
+
+import com.google.zxing.BarcodeFormat;
+import com.google.zxing.EncodeHintType;
+import com.google.zxing.WriterException;
+import com.google.zxing.common.BitMatrix;
+import com.google.zxing.integration.android.IntentIntegrator;
+import com.google.zxing.integration.android.IntentResult;
+import com.google.zxing.qrcode.QRCodeWriter;
+import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
+
+import java.util.Hashtable;
+
+import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.services.XmppConnectionService.OnAccountUpdate;
@@ -173,13 +194,13 @@ public class EditAccountActivity extends XmppActivity {
@Override
public void onTextChanged(CharSequence s, int start, int before,
- int count) {
+ int count) {
updateSaveButton();
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
- int after) {
+ int after) {
}
@@ -216,9 +237,45 @@ public class EditAccountActivity extends XmppActivity {
} else {
return (!mAccount.getJid().equals(mAccountJid.getText().toString()))
|| (!mAccount.getPassword().equals(
- mPassword.getText().toString()) || mAccount
- .isOptionSet(Account.OPTION_REGISTER) != mRegisterNew
- .isChecked());
+ mPassword.getText().toString()) || mAccount
+ .isOptionSet(Account.OPTION_REGISTER) != mRegisterNew
+ .isChecked());
+ }
+ }
+
+ protected void showQrCode() {
+ Point size = new Point();
+ getWindowManager().getDefaultDisplay().getSize(size);
+ final int width = (size.x < size.y ? size.x : size.y);
+ String jid = mAccount.getJid();
+ Bitmap bitmap = createQrCodeBitmap("xmpp:" + jid, width);
+ ImageView view = new ImageView(this);
+ view.setImageBitmap(bitmap);
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setView(view);
+ builder.create().show();
+ }
+
+ protected Bitmap createQrCodeBitmap(String input, int size) {
+ try {
+ final QRCodeWriter QR_CODE_WRITER = new QRCodeWriter();
+ final Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
+ hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
+ final BitMatrix result = QR_CODE_WRITER.encode(input, BarcodeFormat.QR_CODE, size, size, hints);
+ final int width = result.getWidth();
+ final int height = result.getHeight();
+ final int[] pixels = new int[width * height];
+ for (int y = 0; y < height; y++) {
+ final int offset = y * width;
+ for (int x = 0; x < width; x++) {
+ pixels[offset + x] = result.get(x, y) ? Color.BLACK : Color.TRANSPARENT;
+ }
+ }
+ final Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+ bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
+ return bitmap;
+ } catch (final WriterException e) {
+ return null;
}
}
@@ -257,7 +314,7 @@ public class EditAccountActivity extends XmppActivity {
return (!this.mAccount.getJid().equals(
this.mAccountJid.getText().toString()))
|| (!this.mAccount.getPassword().equals(
- this.mPassword.getText().toString()));
+ this.mPassword.getText().toString()));
}
@Override
@@ -287,7 +344,7 @@ public class EditAccountActivity extends XmppActivity {
@Override
public void onCheckedChanged(CompoundButton buttonView,
- boolean isChecked) {
+ boolean isChecked) {
if (isChecked) {
mPasswordConfirm.setVisibility(View.VISIBLE);
} else {
@@ -299,6 +356,27 @@ public class EditAccountActivity extends XmppActivity {
}
@Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+ getMenuInflater().inflate(R.menu.editaccount, menu);
+ MenuItem showQrCode = menu.findItem(R.id.action_show_qr_code);
+ if (mAccount == null) {
+ showQrCode.setVisible(false);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.action_show_qr_code:
+ showQrCode();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
protected void onStart() {
super.onStart();
if (getIntent() != null) {
@@ -387,7 +465,7 @@ public class EditAccountActivity extends XmppActivity {
@Override
public void onClick(View v) {
- if (copyTextToClipboard(fingerprint,R.string.otr_fingerprint)) {
+ if (copyTextToClipboard(fingerprint, R.string.otr_fingerprint)) {
Toast.makeText(
EditAccountActivity.this,
R.string.toast_message_otr_fingerprint,
diff --git a/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java
index 2dd74d9f..aa19ff0e 100644
--- a/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java
@@ -1,13 +1,5 @@
package eu.siacs.conversations.ui;
-import java.io.UnsupportedEncodingException;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLDecoder;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
import android.annotation.SuppressLint;
import android.app.ActionBar;
import android.app.ActionBar.Tab;
@@ -22,6 +14,7 @@ import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.net.Uri;
import android.nfc.NdefMessage;
+import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.os.Bundle;
import android.os.Parcelable;
@@ -29,7 +22,6 @@ import android.support.v13.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.text.Editable;
import android.text.TextWatcher;
-import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.KeyEvent;
@@ -47,7 +39,15 @@ import android.widget.EditText;
import android.widget.ListView;
import android.widget.Spinner;
-import eu.siacs.conversations.Config;
+import com.google.zxing.integration.android.IntentIntegrator;
+import com.google.zxing.integration.android.IntentResult;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Bookmark;
@@ -77,6 +77,8 @@ public class StartConversationActivity extends XmppActivity {
private List<String> mKnownHosts;
private List<String> mKnownConferenceHosts;
+ private Invite mPendingInvite = null;
+
private Menu mOptionsMenu;
private EditText mSearchEditText;
@@ -147,12 +149,12 @@ public class StartConversationActivity extends XmppActivity {
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
- int after) {
+ int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before,
- int count) {
+ int count) {
}
};
private OnRosterUpdate onRosterUpdate = new OnRosterUpdate() {
@@ -214,7 +216,7 @@ public class StartConversationActivity extends XmppActivity {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1,
- int position, long arg3) {
+ int position, long arg3) {
openConversationForBookmark(position);
}
});
@@ -227,7 +229,7 @@ public class StartConversationActivity extends XmppActivity {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1,
- int position, long arg3) {
+ int position, long arg3) {
openConversationForContact(position);
}
});
@@ -500,12 +502,15 @@ public class StartConversationActivity extends XmppActivity {
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
- case R.id.action_create_contact:
- showCreateContactDialog(null);
- break;
- case R.id.action_join_conference:
- showJoinConferenceDialog(null);
- break;
+ case R.id.action_create_contact:
+ showCreateContactDialog(null);
+ return true;
+ case R.id.action_join_conference:
+ showJoinConferenceDialog(null);
+ return true;
+ case R.id.action_scan_qr_code:
+ new IntentIntegrator(this).initiateScan();
+ return true;
}
return super.onOptionsItemSelected(item);
}
@@ -520,6 +525,29 @@ public class StartConversationActivity extends XmppActivity {
}
@Override
+ public void onActivityResult(int requestCode, int resultCode, Intent intent) {
+ if ((requestCode & 0xFFFF) == IntentIntegrator.REQUEST_CODE) {
+ IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
+ if (scanResult != null && scanResult.getFormatName() != null) {
+ String data = scanResult.getContents();
+ Invite invite = parseInviteUri(data);
+ if (xmppConnectionServiceBound) {
+ if (invite.muc) {
+ showJoinConferenceDialog(invite.jid);
+ } else {
+ handleJid(invite.jid);
+ }
+ } else if (invite.jid != null) {
+ this.mPendingInvite = invite;
+ } else {
+ this.mPendingInvite = null;
+ }
+ }
+ }
+ super.onActivityResult(requestCode, requestCode, intent);
+ }
+
+ @Override
protected void onBackendConnected() {
xmppConnectionService.setOnRosterUpdateListener(this.onRosterUpdate);
this.mActivatedAccounts.clear();
@@ -531,21 +559,31 @@ public class StartConversationActivity extends XmppActivity {
this.mKnownHosts = xmppConnectionService.getKnownHosts();
this.mKnownConferenceHosts = xmppConnectionService
.getKnownConferenceHosts();
- if (!handleIntent(getIntent())) {
+ if (this.mPendingInvite != null) {
+ if (this.mPendingInvite.muc) {
+ showJoinConferenceDialog(this.mPendingInvite.jid);
+ } else {
+ handleJid(this.mPendingInvite.jid);
+ }
+ this.mPendingInvite = null;
+ } else if (!handleIntent(getIntent())) {
if (mSearchEditText != null) {
filter(mSearchEditText.getText().toString());
} else {
filter(null);
}
}
+ setIntent(null);
}
protected boolean handleIntent(Intent intent) {
- if (intent==null || intent.getAction() == null) {
+ if (intent == null || intent.getAction() == null) {
return false;
}
String jid;
- switch(intent.getAction()) {
+ Uri uri;
+ Invite invite;
+ switch (intent.getAction()) {
case Intent.ACTION_SENDTO:
try {
jid = URLDecoder.decode(
@@ -556,26 +594,28 @@ public class StartConversationActivity extends XmppActivity {
return false;
}
case Intent.ACTION_VIEW:
- Uri uri = intent.getData();
- boolean muc = uri.getQuery() != null && uri.getQuery().equalsIgnoreCase("join");
- if (uri.getAuthority() != null) {
- jid = uri.getAuthority();
- } else {
- jid = uri.getSchemeSpecificPart().split("\\?")[0];
- }
- if (muc) {
- showJoinConferenceDialog(jid);
+ uri = intent.getData();
+ invite = parseInviteUri(uri);
+ if (invite.muc) {
+ showJoinConferenceDialog(invite.jid);
return false;
} else {
- return handleJid(jid);
+ return handleJid(invite.jid);
}
case NfcAdapter.ACTION_NDEF_DISCOVERED:
- Parcelable[] messages = getIntent().getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
- NdefMessage message = (NdefMessage) messages[0];
- String payload = message.getRecords()[0].toString();
- if (payload.startsWith("xmpp:")) {
- jid = payload.substring(5);
- return handleJid(jid);
+ if (android.os.Build.VERSION.SDK_INT >= 16) {
+ Parcelable[] messages = getIntent().getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
+ NdefMessage message = (NdefMessage) messages[0];
+ NdefRecord record = message.getRecords()[0];
+ invite = parseInviteUri(record.toUri());
+ if (invite != null) {
+ if (invite.muc) {
+ showJoinConferenceDialog(invite.jid);
+ return false;
+ } else {
+ return handleJid(invite.jid);
+ }
+ }
} else {
return false;
}
@@ -584,6 +624,25 @@ public class StartConversationActivity extends XmppActivity {
}
}
+ private Invite parseInviteUri(String uri) {
+ try {
+ return parseInviteUri(Uri.parse(uri));
+ } catch (IllegalArgumentException e) {
+ return null;
+ }
+ }
+
+ private Invite parseInviteUri(Uri uri) {
+ Invite invite = new Invite();
+ invite.muc = uri.getQuery() != null && uri.getQuery().equalsIgnoreCase("join");
+ if (uri.getAuthority() != null) {
+ invite.jid = uri.getAuthority();
+ } else {
+ invite.jid = uri.getSchemeSpecificPart().split("\\?")[0];
+ }
+ return invite;
+ }
+
private boolean handleJid(String jid) {
List<Contact> contacts = xmppConnectionService.findContacts(jid);
if (contacts.size() == 0) {
@@ -595,7 +654,8 @@ public class StartConversationActivity extends XmppActivity {
} else {
if (mMenuSearchView != null) {
mMenuSearchView.expandActionView();
- mSearchEditText.setText(jid);
+ mSearchEditText.setText("");
+ mSearchEditText.append(jid);
filter(jid);
} else {
mInitialJid = jid;
@@ -673,7 +733,7 @@ public class StartConversationActivity extends XmppActivity {
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
- ContextMenuInfo menuInfo) {
+ ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
StartConversationActivity activity = (StartConversationActivity) getActivity();
activity.getMenuInflater().inflate(mResContextMenu, menu);
@@ -689,22 +749,27 @@ public class StartConversationActivity extends XmppActivity {
public boolean onContextItemSelected(MenuItem item) {
StartConversationActivity activity = (StartConversationActivity) getActivity();
switch (item.getItemId()) {
- case R.id.context_start_conversation:
- activity.openConversationForContact();
- break;
- case R.id.context_contact_details:
- activity.openDetailsForContact();
- break;
- case R.id.context_delete_contact:
- activity.deleteContact();
- break;
- case R.id.context_join_conference:
- activity.openConversationForBookmark();
- break;
- case R.id.context_delete_conference:
- activity.deleteConference();
+ case R.id.context_start_conversation:
+ activity.openConversationForContact();
+ break;
+ case R.id.context_contact_details:
+ activity.openDetailsForContact();
+ break;
+ case R.id.context_delete_contact:
+ activity.deleteContact();
+ break;
+ case R.id.context_join_conference:
+ activity.openConversationForBookmark();
+ break;
+ case R.id.context_delete_conference:
+ activity.deleteConference();
}
return true;
}
}
+
+ private class Invite {
+ public String jid;
+ public boolean muc;
+ }
}
diff --git a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java
index 53602571..56aa47b0 100644
--- a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java
@@ -545,9 +545,11 @@ public abstract class XmppActivity extends Activity {
}
protected void registerNdefPushMessageCallback(NfcAdapter.CreateNdefMessageCallback callback) {
- NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
- if (nfcAdapter!=null && nfcAdapter.isEnabled()) {
- nfcAdapter.setNdefPushMessageCallback(callback,this);
+ if (android.os.Build.VERSION.SDK_INT >= 16) {
+ NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
+ if (nfcAdapter != null && nfcAdapter.isEnabled()) {
+ nfcAdapter.setNdefPushMessageCallback(callback, this);
+ }
}
}
diff --git a/src/main/res/menu/editaccount.xml b/src/main/res/menu/editaccount.xml
new file mode 100644
index 00000000..2301caf0
--- /dev/null
+++ b/src/main/res/menu/editaccount.xml
@@ -0,0 +1,8 @@
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item
+ android:id="@+id/action_show_qr_code"
+ android:title="@string/show_qr_code"
+ android:showAsAction="never" />
+
+</menu> \ No newline at end of file
diff --git a/src/main/res/menu/start_conversation.xml b/src/main/res/menu/start_conversation.xml
index f7230169..2c23af59 100644
--- a/src/main/res/menu/start_conversation.xml
+++ b/src/main/res/menu/start_conversation.xml
@@ -1,31 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
-<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/action_search"
android:actionLayout="@layout/actionview_search"
android:icon="@drawable/ic_action_search"
android:showAsAction="collapseActionView|always"
- android:title="@string/search"/>
+ android:title="@string/search" />
<item
android:id="@+id/action_create_contact"
android:icon="@drawable/ic_action_add_person"
android:showAsAction="always"
- android:title="@string/create_contact"/>
+ android:title="@string/create_contact" />
<item
android:id="@+id/action_join_conference"
android:icon="@drawable/ic_action_add_group"
android:showAsAction="always"
- android:title="@string/join_conference"/>
+ android:title="@string/join_conference" />
+ <item
+ android:id="@+id/action_scan_qr_code"
+ android:showAsAction="never"
+ android:title="@string/scan_qr_code" />
<item
android:id="@+id/action_accounts"
android:orderInCategory="90"
android:showAsAction="never"
- android:title="@string/action_accounts"/>
+ android:title="@string/action_accounts" />
<item
android:id="@+id/action_settings"
android:orderInCategory="100"
android:showAsAction="never"
- android:title="@string/action_settings"/>
+ android:title="@string/action_settings" />
</menu> \ No newline at end of file
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index e941ed6d..f8e4eef2 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -282,5 +282,6 @@
<string name="url_copied_to_clipboard">URL copied to clipboard</string>
<string name="message_copied_to_clipboard">Message copied to clipboard</string>
<string name="image_transmission_failed">Image transmission failed</string>
-
+ <string name="scan_qr_code">Scan QR code</string>
+ <string name="show_qr_code">Show QR code</string>
</resources> \ No newline at end of file