ask for contact permissions when first opening StartConversationActivity
This commit is contained in:
parent
c3e8fb3446
commit
739648e909
|
@ -410,6 +410,8 @@ public class FileBackend {
|
||||||
}
|
}
|
||||||
return cropCenterSquare(input, size);
|
return cropCenterSquare(input, size);
|
||||||
}
|
}
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
return null; // happens for example on Android 6.0 if contacts permissions get revoked
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
return null;
|
return null;
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -424,7 +426,7 @@ public class FileBackend {
|
||||||
InputStream is = null;
|
InputStream is = null;
|
||||||
try {
|
try {
|
||||||
BitmapFactory.Options options = new BitmapFactory.Options();
|
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);
|
is = mXmppConnectionService.getContentResolver().openInputStream(image);
|
||||||
if (is == null) {
|
if (is == null) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -451,6 +453,8 @@ public class FileBackend {
|
||||||
source.recycle();
|
source.recycle();
|
||||||
}
|
}
|
||||||
return dest;
|
return dest;
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
return null; //android 6.0 with revoked permissions for example
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
return null;
|
return null;
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -479,7 +483,7 @@ public class FileBackend {
|
||||||
return output;
|
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();
|
BitmapFactory.Options options = new BitmapFactory.Options();
|
||||||
options.inJustDecodeBounds = true;
|
options.inJustDecodeBounds = true;
|
||||||
BitmapFactory.decodeStream(mXmppConnectionService.getContentResolver().openInputStream(image), null, options);
|
BitmapFactory.decodeStream(mXmppConnectionService.getContentResolver().openInputStream(image), null, options);
|
||||||
|
|
|
@ -468,9 +468,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
|
||||||
break;
|
break;
|
||||||
case ACTION_MERGE_PHONE_CONTACTS:
|
case ACTION_MERGE_PHONE_CONTACTS:
|
||||||
if (mRestoredFromDatabase) {
|
if (mRestoredFromDatabase) {
|
||||||
PhoneHelper.loadPhoneContacts(getApplicationContext(),
|
loadPhoneContacts();
|
||||||
new CopyOnWriteArrayList<Bundle>(),
|
|
||||||
this);
|
|
||||||
}
|
}
|
||||||
return START_STICKY;
|
return START_STICKY;
|
||||||
case Intent.ACTION_SHUTDOWN:
|
case Intent.ACTION_SHUTDOWN:
|
||||||
|
@ -1097,9 +1095,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
|
||||||
}
|
}
|
||||||
getBitmapCache().evictAll();
|
getBitmapCache().evictAll();
|
||||||
Looper.prepare();
|
Looper.prepare();
|
||||||
PhoneHelper.loadPhoneContacts(getApplicationContext(),
|
loadPhoneContacts();
|
||||||
new CopyOnWriteArrayList<Bundle>(),
|
|
||||||
XmppConnectionService.this);
|
|
||||||
Log.d(Config.LOGTAG, "restoring messages");
|
Log.d(Config.LOGTAG, "restoring messages");
|
||||||
for (Conversation conversation : conversations) {
|
for (Conversation conversation : conversations) {
|
||||||
conversation.addAll(0, databaseBackend.getMessages(conversation, Config.PAGE_SIZE));
|
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() {
|
public List<Conversation> getConversations() {
|
||||||
return this.conversations;
|
return this.conversations;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package eu.siacs.conversations.ui;
|
package eu.siacs.conversations.ui;
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.annotation.TargetApi;
|
import android.annotation.TargetApi;
|
||||||
import android.app.ActionBar;
|
import android.app.ActionBar;
|
||||||
|
@ -13,6 +14,7 @@ import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.DialogInterface.OnClickListener;
|
import android.content.DialogInterface.OnClickListener;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.nfc.NdefMessage;
|
import android.nfc.NdefMessage;
|
||||||
import android.nfc.NdefRecord;
|
import android.nfc.NdefRecord;
|
||||||
|
@ -51,6 +53,7 @@ import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
import eu.siacs.conversations.Config;
|
import eu.siacs.conversations.Config;
|
||||||
import eu.siacs.conversations.R;
|
import eu.siacs.conversations.R;
|
||||||
|
@ -89,6 +92,9 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
|
||||||
private Invite mPendingInvite = null;
|
private Invite mPendingInvite = null;
|
||||||
private Menu mOptionsMenu;
|
private Menu mOptionsMenu;
|
||||||
private EditText mSearchEditText;
|
private EditText mSearchEditText;
|
||||||
|
private AtomicBoolean mRequestedContactsPermission = new AtomicBoolean(false);
|
||||||
|
private final int REQUEST_SYNC_CONTACTS = 0x3b28cf;
|
||||||
|
|
||||||
private MenuItem.OnActionExpandListener mOnActionExpandListener = new MenuItem.OnActionExpandListener() {
|
private MenuItem.OnActionExpandListener mOnActionExpandListener = new MenuItem.OnActionExpandListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -245,6 +251,12 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStart() {
|
||||||
|
super.onStart();
|
||||||
|
askForContactsPermissions();
|
||||||
|
}
|
||||||
|
|
||||||
protected void openConversationForContact(int position) {
|
protected void openConversationForContact(int position) {
|
||||||
Contact contact = (Contact) contacts.get(position);
|
Contact contact = (Contact) contacts.get(position);
|
||||||
Conversation conversation = xmppConnectionService
|
Conversation conversation = xmppConnectionService
|
||||||
|
@ -369,7 +381,7 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
|
||||||
final Jid accountJid;
|
final Jid accountJid;
|
||||||
try {
|
try {
|
||||||
if (Config.DOMAIN_LOCK != null) {
|
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 {
|
} else {
|
||||||
accountJid = Jid.fromString((String) spinner.getSelectedItem());
|
accountJid = Jid.fromString((String) spinner.getSelectedItem());
|
||||||
}
|
}
|
||||||
|
@ -432,7 +444,7 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
|
||||||
final Jid accountJid;
|
final Jid accountJid;
|
||||||
try {
|
try {
|
||||||
if (Config.DOMAIN_LOCK != null) {
|
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 {
|
} else {
|
||||||
accountJid = Jid.fromString((String) spinner.getSelectedItem());
|
accountJid = Jid.fromString((String) spinner.getSelectedItem());
|
||||||
}
|
}
|
||||||
|
@ -447,7 +459,7 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final Account account = xmppConnectionService
|
final Account account = xmppConnectionService
|
||||||
.findAccountByJid(accountJid);
|
.findAccountByJid(accountJid);
|
||||||
if (account == null) {
|
if (account == null) {
|
||||||
dialog.dismiss();
|
dialog.dismiss();
|
||||||
return;
|
return;
|
||||||
|
@ -456,7 +468,7 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
|
||||||
if (account.hasBookmarkFor(conferenceJid)) {
|
if (account.hasBookmarkFor(conferenceJid)) {
|
||||||
jid.setError(getString(R.string.bookmark_already_exists));
|
jid.setError(getString(R.string.bookmark_already_exists));
|
||||||
} else {
|
} else {
|
||||||
final Bookmark bookmark = new Bookmark(account,conferenceJid.toBareJid());
|
final Bookmark bookmark = new Bookmark(account, conferenceJid.toBareJid());
|
||||||
bookmark.setAutojoin(true);
|
bookmark.setAutojoin(true);
|
||||||
String nick = conferenceJid.getResourcepart();
|
String nick = conferenceJid.getResourcepart();
|
||||||
if (nick != null && !nick.isEmpty()) {
|
if (nick != null && !nick.isEmpty()) {
|
||||||
|
@ -465,8 +477,8 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
|
||||||
account.getBookmarks().add(bookmark);
|
account.getBookmarks().add(bookmark);
|
||||||
xmppConnectionService.pushBookmarks(account);
|
xmppConnectionService.pushBookmarks(account);
|
||||||
final Conversation conversation = xmppConnectionService
|
final Conversation conversation = xmppConnectionService
|
||||||
.findOrCreateConversation(account,
|
.findOrCreateConversation(account,
|
||||||
conferenceJid, true);
|
conferenceJid, true);
|
||||||
conversation.setBookmark(bookmark);
|
conversation.setBookmark(bookmark);
|
||||||
if (!conversation.getMucOptions().online()) {
|
if (!conversation.getMucOptions().online()) {
|
||||||
xmppConnectionService.joinMuc(conversation);
|
xmppConnectionService.joinMuc(conversation);
|
||||||
|
@ -476,8 +488,8 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
final Conversation conversation = xmppConnectionService
|
final Conversation conversation = xmppConnectionService
|
||||||
.findOrCreateConversation(account,
|
.findOrCreateConversation(account,
|
||||||
conferenceJid, true);
|
conferenceJid, true);
|
||||||
if (!conversation.getMucOptions().online()) {
|
if (!conversation.getMucOptions().online()) {
|
||||||
xmppConnectionService.joinMuc(conversation);
|
xmppConnectionService.joinMuc(conversation);
|
||||||
}
|
}
|
||||||
|
@ -580,6 +592,41 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
|
||||||
super.onActivityResult(requestCode, requestCode, intent);
|
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
|
@Override
|
||||||
protected void onBackendConnected() {
|
protected void onBackendConnected() {
|
||||||
this.mActivatedAccounts.clear();
|
this.mActivatedAccounts.clear();
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package eu.siacs.conversations.utils;
|
package eu.siacs.conversations.utils;
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.CursorLoader;
|
import android.content.CursorLoader;
|
||||||
import android.content.Loader;
|
import android.content.Loader;
|
||||||
|
@ -7,6 +8,7 @@ import android.content.Loader.OnLoadCompleteListener;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.provider.ContactsContract;
|
import android.provider.ContactsContract;
|
||||||
import android.provider.ContactsContract.Profile;
|
import android.provider.ContactsContract.Profile;
|
||||||
|
@ -17,6 +19,11 @@ import java.util.concurrent.RejectedExecutionException;
|
||||||
public class PhoneHelper {
|
public class PhoneHelper {
|
||||||
|
|
||||||
public static void loadPhoneContacts(Context context,final List<Bundle> phoneContacts, final OnPhoneContactsLoadedListener listener) {
|
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,
|
final String[] PROJECTION = new String[] { ContactsContract.Data._ID,
|
||||||
ContactsContract.Data.DISPLAY_NAME,
|
ContactsContract.Data.DISPLAY_NAME,
|
||||||
ContactsContract.Data.PHOTO_URI,
|
ContactsContract.Data.PHOTO_URI,
|
||||||
|
@ -74,6 +81,10 @@ public class PhoneHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Uri getSefliUri(Context context) {
|
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 };
|
String[] mProjection = new String[] { Profile._ID, Profile.PHOTO_URI };
|
||||||
Cursor mProfileCursor = context.getContentResolver().query(
|
Cursor mProfileCursor = context.getContentResolver().query(
|
||||||
Profile.CONTENT_URI, mProjection, null, null, null);
|
Profile.CONTENT_URI, mProjection, null, null, null);
|
||||||
|
|
|
@ -558,4 +558,7 @@
|
||||||
<string name="shared_file_with_x">Shared file with %s</string>
|
<string name="shared_file_with_x">Shared file with %s</string>
|
||||||
<string name="shared_image_with_x">Shared image 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="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>
|
</resources>
|
||||||
|
|
Loading…
Reference in a new issue