aboutsummaryrefslogtreecommitdiffstats
path: root/src/main
diff options
context:
space:
mode:
authorDaniel Gultsch <daniel@gultsch.de>2015-12-07 00:33:50 +0100
committerChristian S <christian@pix-art.de>2015-12-12 15:49:11 +0100
commit9c2b7c76d2eb21212dd8f285f0699b34a835aff5 (patch)
tree4bcc86387b3e2e02d0e66eda4e2a4438b47ec1da /src/main
parent422df9062749296cc1dda3cc109cc7b330127634 (diff)
ask for contact permissions when first opening StartConversationActivity
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/eu/siacs/conversations/persistance/FileBackend.java8
-rw-r--r--src/main/java/eu/siacs/conversations/services/XmppConnectionService.java14
-rw-r--r--src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java63
-rw-r--r--src/main/java/eu/siacs/conversations/utils/PhoneHelper.java11
-rw-r--r--src/main/res/values/strings.xml3
5 files changed, 83 insertions, 16 deletions
diff --git a/src/main/java/eu/siacs/conversations/persistance/FileBackend.java b/src/main/java/eu/siacs/conversations/persistance/FileBackend.java
index febb09705..02b14c7df 100644
--- a/src/main/java/eu/siacs/conversations/persistance/FileBackend.java
+++ b/src/main/java/eu/siacs/conversations/persistance/FileBackend.java
@@ -410,6 +410,8 @@ public class FileBackend {
}
return cropCenterSquare(input, size);
}
+ } catch (SecurityException e) {
+ return null; // happens for example on Android 6.0 if contacts permissions get revoked
} catch (FileNotFoundException e) {
return null;
} finally {
@@ -424,7 +426,7 @@ public class FileBackend {
InputStream is = null;
try {
BitmapFactory.Options options = new BitmapFactory.Options();
- options.inSampleSize = calcSampleSize(image,Math.max(newHeight, newWidth));
+ options.inSampleSize = calcSampleSize(image, Math.max(newHeight, newWidth));
is = mXmppConnectionService.getContentResolver().openInputStream(image);
if (is == null) {
return null;
@@ -451,6 +453,8 @@ public class FileBackend {
source.recycle();
}
return dest;
+ } catch (SecurityException e) {
+ return null; //android 6.0 with revoked permissions for example
} catch (FileNotFoundException e) {
return null;
} finally {
@@ -479,7 +483,7 @@ public class FileBackend {
return output;
}
- private int calcSampleSize(Uri image, int size) throws FileNotFoundException {
+ private int calcSampleSize(Uri image, int size) throws FileNotFoundException, SecurityException {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(mXmppConnectionService.getContentResolver().openInputStream(image), null, options);
diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
index dbc4825c9..790e035c6 100644
--- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
+++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
@@ -468,9 +468,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
break;
case ACTION_MERGE_PHONE_CONTACTS:
if (mRestoredFromDatabase) {
- PhoneHelper.loadPhoneContacts(getApplicationContext(),
- new CopyOnWriteArrayList<Bundle>(),
- this);
+ loadPhoneContacts();
}
return START_STICKY;
case Intent.ACTION_SHUTDOWN:
@@ -1097,9 +1095,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
}
getBitmapCache().evictAll();
Looper.prepare();
- PhoneHelper.loadPhoneContacts(getApplicationContext(),
- new CopyOnWriteArrayList<Bundle>(),
- XmppConnectionService.this);
+ loadPhoneContacts();
Log.d(Config.LOGTAG, "restoring messages");
for (Conversation conversation : conversations) {
conversation.addAll(0, databaseBackend.getMessages(conversation, Config.PAGE_SIZE));
@@ -1121,6 +1117,12 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
}
}
+ public void loadPhoneContacts() {
+ PhoneHelper.loadPhoneContacts(getApplicationContext(),
+ new CopyOnWriteArrayList<Bundle>(),
+ XmppConnectionService.this);
+ }
+
public List<Conversation> getConversations() {
return this.conversations;
}
diff --git a/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java
index df04567f1..f6a386478 100644
--- a/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java
@@ -1,5 +1,6 @@
package eu.siacs.conversations.ui;
+import android.Manifest;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.ActionBar;
@@ -13,6 +14,7 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
+import android.content.pm.PackageManager;
import android.net.Uri;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
@@ -51,6 +53,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
@@ -89,6 +92,9 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
private Invite mPendingInvite = null;
private Menu mOptionsMenu;
private EditText mSearchEditText;
+ private AtomicBoolean mRequestedContactsPermission = new AtomicBoolean(false);
+ private final int REQUEST_SYNC_CONTACTS = 0x3b28cf;
+
private MenuItem.OnActionExpandListener mOnActionExpandListener = new MenuItem.OnActionExpandListener() {
@Override
@@ -245,6 +251,12 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
}
+ @Override
+ public void onStart() {
+ super.onStart();
+ askForContactsPermissions();
+ }
+
protected void openConversationForContact(int position) {
Contact contact = (Contact) contacts.get(position);
Conversation conversation = xmppConnectionService
@@ -369,7 +381,7 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
final Jid accountJid;
try {
if (Config.DOMAIN_LOCK != null) {
- accountJid = Jid.fromParts((String) spinner.getSelectedItem(),Config.DOMAIN_LOCK,null);
+ accountJid = Jid.fromParts((String) spinner.getSelectedItem(), Config.DOMAIN_LOCK, null);
} else {
accountJid = Jid.fromString((String) spinner.getSelectedItem());
}
@@ -432,7 +444,7 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
final Jid accountJid;
try {
if (Config.DOMAIN_LOCK != null) {
- accountJid = Jid.fromParts((String) spinner.getSelectedItem(),Config.DOMAIN_LOCK,null);
+ accountJid = Jid.fromParts((String) spinner.getSelectedItem(), Config.DOMAIN_LOCK, null);
} else {
accountJid = Jid.fromString((String) spinner.getSelectedItem());
}
@@ -447,7 +459,7 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
return;
}
final Account account = xmppConnectionService
- .findAccountByJid(accountJid);
+ .findAccountByJid(accountJid);
if (account == null) {
dialog.dismiss();
return;
@@ -456,7 +468,7 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
if (account.hasBookmarkFor(conferenceJid)) {
jid.setError(getString(R.string.bookmark_already_exists));
} else {
- final Bookmark bookmark = new Bookmark(account,conferenceJid.toBareJid());
+ final Bookmark bookmark = new Bookmark(account, conferenceJid.toBareJid());
bookmark.setAutojoin(true);
String nick = conferenceJid.getResourcepart();
if (nick != null && !nick.isEmpty()) {
@@ -465,8 +477,8 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
account.getBookmarks().add(bookmark);
xmppConnectionService.pushBookmarks(account);
final Conversation conversation = xmppConnectionService
- .findOrCreateConversation(account,
- conferenceJid, true);
+ .findOrCreateConversation(account,
+ conferenceJid, true);
conversation.setBookmark(bookmark);
if (!conversation.getMucOptions().online()) {
xmppConnectionService.joinMuc(conversation);
@@ -476,8 +488,8 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
}
} else {
final Conversation conversation = xmppConnectionService
- .findOrCreateConversation(account,
- conferenceJid, true);
+ .findOrCreateConversation(account,
+ conferenceJid, true);
if (!conversation.getMucOptions().online()) {
xmppConnectionService.joinMuc(conversation);
}
@@ -580,6 +592,41 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
super.onActivityResult(requestCode, requestCode, intent);
}
+ private void askForContactsPermissions() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ if (checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
+ if (mRequestedContactsPermission.compareAndSet(false, true)) {
+ if (shouldShowRequestPermissionRationale(Manifest.permission.READ_CONTACTS)) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle(R.string.sync_with_contacts);
+ builder.setMessage(R.string.sync_with_contacts_long);
+ builder.setPositiveButton(R.string.sync_now, new OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ requestPermissions(new String[]{Manifest.permission.READ_CONTACTS}, REQUEST_SYNC_CONTACTS);
+ }
+ }
+ });
+ builder.create().show();
+ } else {
+ requestPermissions(new String[]{Manifest.permission.READ_CONTACTS}, 0);
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
+ if (grantResults.length > 0)
+ if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+ if (requestCode == REQUEST_SYNC_CONTACTS && xmppConnectionServiceBound) {
+ xmppConnectionService.loadPhoneContacts();
+ }
+ }
+ }
+
@Override
protected void onBackendConnected() {
this.mActivatedAccounts.clear();
diff --git a/src/main/java/eu/siacs/conversations/utils/PhoneHelper.java b/src/main/java/eu/siacs/conversations/utils/PhoneHelper.java
index a37f60a0f..893f9eb89 100644
--- a/src/main/java/eu/siacs/conversations/utils/PhoneHelper.java
+++ b/src/main/java/eu/siacs/conversations/utils/PhoneHelper.java
@@ -1,5 +1,6 @@
package eu.siacs.conversations.utils;
+import android.Manifest;
import android.content.Context;
import android.content.CursorLoader;
import android.content.Loader;
@@ -7,6 +8,7 @@ import android.content.Loader.OnLoadCompleteListener;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
+import android.os.Build;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Profile;
@@ -17,6 +19,11 @@ import java.util.concurrent.RejectedExecutionException;
public class PhoneHelper {
public static void loadPhoneContacts(Context context,final List<Bundle> phoneContacts, final OnPhoneContactsLoadedListener listener) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
+ && context.checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
+ listener.onPhoneContactsLoaded(phoneContacts);
+ return;
+ }
final String[] PROJECTION = new String[] { ContactsContract.Data._ID,
ContactsContract.Data.DISPLAY_NAME,
ContactsContract.Data.PHOTO_URI,
@@ -74,6 +81,10 @@ public class PhoneHelper {
}
public static Uri getSefliUri(Context context) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
+ && context.checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
+ return null;
+ }
String[] mProjection = new String[] { Profile._ID, Profile.PHOTO_URI };
Cursor mProfileCursor = context.getContentResolver().query(
Profile.CONTENT_URI, mProjection, null, null, null);
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index 1a6d1f57e..75825cbf9 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -577,4 +577,7 @@
<string name="shared_file_with_x">Shared file with %s</string>
<string name="shared_image_with_x">Shared image with %s</string>
<string name="no_storage_permission">Conversations need access to external storage</string>
+ <string name="sync_with_contacts">Synchronize with contacts</string>
+ <string name="sync_with_contacts_long">Conversations wants to match your XMPP roster with your contacts to show their full names and avatars.\n\nConversations will only read your contacts and match them locally without uploading them to your server.</string>
+ <string name="sync_now">Synchronize now</string>
</resources>