Commit 1c044555 authored by Suhail Alkowaileet's avatar Suhail Alkowaileet

Fix permission request in Android 6.0.1 / CM13.0 #43

parent 9d72ffac
......@@ -20,8 +20,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="ws.xsoh.etar"
android:installLocation="auto"
android:versionCode="7"
android:versionName="1.0.3">
android:versionCode="8"
android:versionName="1.0.4">
<!-- android:sharedUserLabel="@string/app_label"> -->
<!--
......
......@@ -274,4 +274,6 @@
</plurals>
<string name="acessibility_recurrence_choose_end_date_description" msgid="5899029840837836711">"تغيير تاريخ الانتهاء"</string>
<string name="goto_date">"الذهاب إلى…"</string>
<string name="calendar_permission_not_granted">"يتعذر التطبيق عن تشغيل هذه الخاصية، يتطلب تطبيق إيتار صلاحياتي القراءة والكتابة على التقويم حتى يعمل بالشكل المطلوب"</string>
<string name="user_rejected_calendar_write_permission">"يتعذر التطبيق عن التشغيل، إيتار يتطلب صلاحياتي القراءة والكتابة على التقويم حتى يعمل بالشكل المطلوب"</string>
</resources>
......@@ -741,4 +741,7 @@
<!-- Do Not Translate. Sender identity for global notification synchronization. -->
<string name="notification_sender_id" translatable="false"></string>
<string name="user_rejected_calendar_write_permission">Etar requires calendar read and write permissions to work properly. Please try again.</string>
<string name="calendar_permission_not_granted">Sorry this feature can\'t work. Etar requires calendar read and write permissions to work properly</string>
</resources>
......@@ -16,6 +16,7 @@
package com.android.calendar;
import android.Manifest;
import android.accounts.AccountManager;
import android.accounts.AccountManagerCallback;
import android.accounts.AccountManagerFuture;
......@@ -34,12 +35,14 @@ import android.content.ContentUris;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.database.Cursor;
import android.graphics.drawable.LayerDrawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.provider.CalendarContract;
......@@ -48,6 +51,8 @@ import android.provider.CalendarContract.Calendars;
import android.provider.CalendarContract.Events;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.NavigationView;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.MenuItemCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar;
......@@ -67,6 +72,7 @@ import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.RelativeLayout.LayoutParams;
import android.widget.TextView;
import android.widget.Toast;
import com.android.calendar.CalendarController.EventHandler;
import com.android.calendar.CalendarController.EventInfo;
......@@ -99,6 +105,7 @@ public class AllInOneActivity extends AbstractCalendarActivity implements EventH
private static final String BUNDLE_KEY_RESTORE_VIEW = "key_restore_view";
private static final String BUNDLE_KEY_CHECK_ACCOUNTS = "key_check_for_accounts";
private static final int HANDLER_KEY = 0;
private static final int PERMISSIONS_REQUEST_WRITE_CALENDAR = 0;
// Indices of buttons for the drop down menu (tabs replacement)
// Must match the strings in the array buttons_list in arrays.xml and the
......@@ -193,20 +200,20 @@ public class AllInOneActivity extends AbstractCalendarActivity implements EventH
private MenuItem mControlsMenu;
private Menu mOptionsMenu;
private QueryHandler mHandler;
// runs every midnight/time changes and refreshes the today icon
private final Runnable mTimeChangesUpdater = new Runnable() {
private final Runnable mHomeTimeUpdater = new Runnable() {
@Override
public void run() {
mTimeZone = Utils.getTimeZone(AllInOneActivity.this, mHomeTimeUpdater);
updateSecondaryTitleFields(-1);
AllInOneActivity.this.invalidateOptionsMenu();
Utils.setMidnightUpdater(mHandler, mTimeChangesUpdater, mTimeZone);
}
};
private final Runnable mHomeTimeUpdater = new Runnable() {
// runs every midnight/time changes and refreshes the today icon
private final Runnable mTimeChangesUpdater = new Runnable() {
@Override
public void run() {
mTimeZone = Utils.getTimeZone(AllInOneActivity.this, mHomeTimeUpdater);
updateSecondaryTitleFields(-1);
AllInOneActivity.this.invalidateOptionsMenu();
Utils.setMidnightUpdater(mHandler, mTimeChangesUpdater, mTimeZone);
}
......@@ -265,6 +272,8 @@ public class AllInOneActivity extends AbstractCalendarActivity implements EventH
// This needs to be created before setContentView
mController = CalendarController.getInstance(this);
// Check and ask for most needed permissions
checkAppPermissions();
// Get time from intent or icicle
long timeMillis = -1;
......@@ -379,6 +388,46 @@ public class AllInOneActivity extends AbstractCalendarActivity implements EventH
mContentResolver = getContentResolver();
}
private void checkAppPermissions() {
// Here, thisActivity is the current activity
if (Build.VERSION.SDK_INT >= 23 && ContextCompat.checkSelfPermission(this,
Manifest.permission.WRITE_CALENDAR)
!= PackageManager.PERMISSION_GRANTED) {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.WRITE_CALENDAR},
PERMISSIONS_REQUEST_WRITE_CALENDAR);
}
}
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case PERMISSIONS_REQUEST_WRITE_CALENDAR: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay!
} else {
Toast.makeText(getApplicationContext(), R.string.user_rejected_calendar_write_permission, Toast.LENGTH_LONG).show();
this.finish();
}
return;
}
// other 'case' lines to check for other
// permissions this app might request
}
}
private void setupToolbar(int viewType) {
mToolbar = (Toolbar) findViewById(R.id.toolbar);
if (mToolbar == null) {
......
......@@ -16,18 +16,22 @@
package com.android.calendar;
import android.Manifest;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Debug;
import android.provider.CalendarContract.Attendees;
import android.provider.CalendarContract.Calendars;
import android.provider.CalendarContract.Events;
import android.provider.CalendarContract.Instances;
import android.support.v4.content.ContextCompat;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.Log;
......@@ -178,6 +182,13 @@ public class Event implements Cloneable {
Debug.startMethodTracing("loadEvents");
}
if (Build.VERSION.SDK_INT >= 23 && ContextCompat.checkSelfPermission(context,
Manifest.permission.READ_CALENDAR)
!= PackageManager.PERMISSION_GRANTED) {
//If permission is not granted then just return.
return;
}
Cursor cEvents = null;
Cursor cAllday = null;
......
......@@ -16,18 +16,22 @@
package com.android.calendar.alerts;
import android.Manifest;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.provider.CalendarContract;
import android.provider.CalendarContract.Events;
import android.provider.CalendarContract.Instances;
import android.provider.CalendarContract.Reminders;
import android.support.v4.content.ContextCompat;
import android.text.format.DateUtils;
import android.text.format.Time;
import android.util.Log;
......@@ -44,31 +48,16 @@ import java.util.Map;
* and reminders tables for the next upcoming alert.
*/
public class AlarmScheduler {
private static final String TAG = "AlarmScheduler";
private static final String INSTANCES_WHERE = Events.VISIBLE + "=? AND "
+ Instances.BEGIN + ">=? AND " + Instances.BEGIN + "<=? AND "
+ Events.ALL_DAY + "=?";
static final String[] INSTANCES_PROJECTION = new String[] {
Instances.EVENT_ID,
Instances.BEGIN,
Instances.ALL_DAY,
};
private static final int INSTANCES_INDEX_EVENTID = 0;
private static final int INSTANCES_INDEX_BEGIN = 1;
private static final int INSTANCES_INDEX_ALL_DAY = 2;
private static final String REMINDERS_WHERE = Reminders.METHOD + "=1 AND "
+ Reminders.EVENT_ID + " IN ";
static final String[] REMINDERS_PROJECTION = new String[] {
Reminders.EVENT_ID,
Reminders.MINUTES,
Reminders.METHOD,
};
private static final int REMINDERS_INDEX_EVENT_ID = 0;
private static final int REMINDERS_INDEX_MINUTES = 1;
private static final int REMINDERS_INDEX_METHOD = 2;
// Add a slight delay for the EVENT_REMINDER_APP broadcast for a couple reasons:
// (1) so that the concurrent reminder broadcast from the provider doesn't result
// in a double ring, and (2) some OEMs modified the provider to not add an alert to
......@@ -76,7 +65,18 @@ public class AlarmScheduler {
// notifications to work on these devices, a delay ensures that AlertService won't
// read from the CalendarAlerts table until the alert is present.
static final int ALARM_DELAY_MS = 1000;
private static final String TAG = "AlarmScheduler";
private static final String INSTANCES_WHERE = Events.VISIBLE + "=? AND "
+ Instances.BEGIN + ">=? AND " + Instances.BEGIN + "<=? AND "
+ Events.ALL_DAY + "=?";
private static final int INSTANCES_INDEX_EVENTID = 0;
private static final int INSTANCES_INDEX_BEGIN = 1;
private static final int INSTANCES_INDEX_ALL_DAY = 2;
private static final String REMINDERS_WHERE = Reminders.METHOD + "=1 AND "
+ Reminders.EVENT_ID + " IN ";
private static final int REMINDERS_INDEX_EVENT_ID = 0;
private static final int REMINDERS_INDEX_MINUTES = 1;
private static final int REMINDERS_INDEX_METHOD = 2;
// The reminders query looks like "SELECT ... AND eventId IN 101,102,202,...". This
// sets the max # of events in the query before batching into multiple queries, to
// limit the SQL query length.
......@@ -137,6 +137,14 @@ public class AlarmScheduler {
final long utcStartMin = localStartMin - localOffset;
final long utcStartMax = utcStartMin + EVENT_LOOKAHEAD_WINDOW_MS;
if (Build.VERSION.SDK_INT >= 23 && ContextCompat.checkSelfPermission(context,
Manifest.permission.READ_CALENDAR)
!= PackageManager.PERMISSION_GRANTED) {
//If permission is not granted then just return.
Log.d(TAG, "Manifest.permission.READ_CALENDAR is not granted");
return null;
}
// Expand Instances table range by a day on either end to account for
// all-day events.
Uri.Builder uriBuilder = Instances.CONTENT_URI.buildUpon();
......
......@@ -16,6 +16,7 @@
package com.android.calendar.alerts;
import android.Manifest;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.Service;
......@@ -25,8 +26,10 @@ import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
......@@ -37,6 +40,7 @@ import android.os.Process;
import android.provider.CalendarContract;
import android.provider.CalendarContract.Attendees;
import android.provider.CalendarContract.CalendarAlerts;
import android.support.v4.content.ContextCompat;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.text.format.Time;
......@@ -145,6 +149,15 @@ public class AlertService extends Service {
Log.d(TAG, "Beginning updateAlertNotification");
}
if (Build.VERSION.SDK_INT >= 23 && ContextCompat.checkSelfPermission(context,
Manifest.permission.READ_CALENDAR)
!= PackageManager.PERMISSION_GRANTED) {
//If permission is not granted then just return.
Log.d(TAG, "Manifest.permission.READ_CALENDAR is not granted");
return false;
}
if (!prefs.getBoolean(GeneralPreferences.KEY_ALERTS, true)) {
if (DEBUG) {
Log.d(TAG, "alert preference is OFF");
......@@ -825,6 +838,15 @@ public class AlertService extends Service {
CalendarContract.CalendarAlerts.ALARM_TIME,
};
if (Build.VERSION.SDK_INT >= 23 && ContextCompat.checkSelfPermission(context,
Manifest.permission.READ_CALENDAR)
!= PackageManager.PERMISSION_GRANTED) {
//If permission is not granted then just return.
Log.d(TAG, "Manifest.permission.READ_CALENDAR is not granted");
return;
}
// TODO: construct an explicit SQL query so that we can add
// "GROUPBY" instead of doing a sort and de-dup
Cursor cursor = cr.query(CalendarAlerts.CONTENT_URI, projection,
......
......@@ -16,6 +16,7 @@
package com.android.calendar.event;
import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Fragment;
......@@ -30,15 +31,18 @@ import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.CalendarContract.Attendees;
import android.provider.CalendarContract.Calendars;
import android.provider.CalendarContract.Colors;
import android.provider.CalendarContract.Events;
import android.provider.CalendarContract.Reminders;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.text.format.Time;
......@@ -319,7 +323,16 @@ public class EditEventFragment extends Fragment implements EventHandler, OnColor
}
mView = new EditEventView(mContext, view, mOnDone, mTimeSelectedWasStartTime,
mDateSelectedWasStartDate);
startQuery();
if (Build.VERSION.SDK_INT >= 23 && ContextCompat.checkSelfPermission(mContext,
Manifest.permission.READ_CALENDAR)
!= PackageManager.PERMISSION_GRANTED) {
//If permission is not granted
Toast.makeText(mContext, R.string.calendar_permission_not_granted, Toast.LENGTH_LONG).show();
} else {
startQuery();
}
if (mUseCustomActionBar) {
View actionBarButtons = inflater.inflate(R.layout.edit_event_custom_actionbar,
......
......@@ -16,18 +16,22 @@
package com.android.calendar.event;
import android.Manifest;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.provider.CalendarContract.Events;
import android.provider.ContactsContract.CommonDataKinds;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.RawContacts;
import android.support.v4.content.ContextCompat;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
......@@ -100,6 +104,7 @@ public class EventLocationAdapter extends ArrayAdapter<EventLocationAdapter.Resu
+ Events.EVENT_LOCATION + " LIKE ?";
private static final int MAX_LOCATION_SUGGESTIONS = 4;
private static ArrayList<Result> EMPTY_LIST = new ArrayList<Result>();
private final Context mContext;
private final ContentResolver mResolver;
private final LayoutInflater mInflater;
private final ArrayList<Result> mResultList = new ArrayList<Result>();
......@@ -113,6 +118,7 @@ public class EventLocationAdapter extends ArrayAdapter<EventLocationAdapter.Resu
public EventLocationAdapter(Context context) {
super(context, R.layout.location_dropdown_item, EMPTY_LIST);
mContext = context;
mResolver = context.getContentResolver();
mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
......@@ -196,13 +202,21 @@ public class EventLocationAdapter extends ArrayAdapter<EventLocationAdapter.Resu
/**
* Matches the input string against recent locations.
*/
private static List<Result> queryRecentLocations(ContentResolver resolver, String input) {
private static List<Result> queryRecentLocations(ContentResolver resolver, String input, Context context) {
// TODO: also match each word in the address?
String filter = input == null ? "" : input + "%";
if (filter.isEmpty()) {
return null;
}
if (Build.VERSION.SDK_INT >= 23 && ContextCompat.checkSelfPermission(context,
Manifest.permission.READ_CALENDAR)
!= PackageManager.PERMISSION_GRANTED) {
//If permission is not granted then just return.
Log.d(TAG, "Manifest.permission.READ_CALENDAR is not granted");
return null;
}
// Query all locations prefixed with the constraint. There is no way to insert
// 'DISTINCT' or 'GROUP BY' to get rid of dupes, so use post-processing to
// remove dupes. We will order query results by descending event ID to show
......@@ -405,7 +419,7 @@ public class EventLocationAdapter extends ArrayAdapter<EventLocationAdapter.Resu
new AsyncTask<Void, Void, List<Result>>() {
@Override
protected List<Result> doInBackground(Void... params) {
return queryRecentLocations(mResolver, filter);
return queryRecentLocations(mResolver, filter, mContext);
}
}.execute();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment