diff --git a/.gitignore b/.gitignore index 00051f0..7af5853 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,34 @@ +# Gradle files +.gradle/ +build/ + +# Local configuration file (sdk path, etc) +local.properties + +# Log/OS Files +*.log + +# Android Studio generated files and folders +captures/ +.externalNativeBuild/ +.cxx/ +*.apk +output.json + +# IntelliJ *.iml -.gradle -/local.properties -/.idea/workspace.xml -/.idea/vcs.xml -/.idea/libraries -.DS_Store -/build -/captures +.idea/ +misc.xml +deploymentTargetDropDown.xml +render.experimental.xml + +# Keystore files +*.jks +*.keystore + +# Google Services (e.g. APIs or Firebase) +google-services.json + +# Android Profiling +*.hprof + diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser new file mode 100644 index 0000000..467d2e1 Binary files /dev/null and b/.idea/caches/build_file_checksums.ser differ diff --git a/.idea/caches/gradle_models.ser b/.idea/caches/gradle_models.ser new file mode 100644 index 0000000..f15ad18 Binary files /dev/null and b/.idea/caches/gradle_models.ser differ diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..681f41a --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,116 @@ + + + + + + + +
+ + + + xmlns:android + + ^$ + + + +
+
+ + + + xmlns:.* + + ^$ + + + BY_NAME + +
+
+ + + + .*:id + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:name + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + name + + ^$ + + + +
+
+ + + + style + + ^$ + + + +
+
+ + + + .* + + ^$ + + + BY_NAME + +
+
+ + + + .* + + http://schemas.android.com/apk/res/android + + + ANDROID_ATTRIBUTE_ORDER + +
+
+ + + + .* + + .* + + + BY_NAME + +
+
+
+
+
+
\ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..a55e7a1 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml index 96cc43e..fb7f4a8 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -1,22 +1,6 @@ - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml index 0e23f8e..1ddcc05 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -1,9 +1,11 @@ + diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml new file mode 100644 index 0000000..a5f05cd --- /dev/null +++ b/.idea/jarRepositories.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index fbb6828..a86764b 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,43 +1,47 @@ - - - - - - - - - - - - - - + diff --git a/.idea/modules.xml b/.idea/modules.xml index 07a95c8..3154d6a 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -2,8 +2,11 @@ - - + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml deleted file mode 100644 index 7f68460..0000000 --- a/.idea/runConfigurations.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 17e0574..d58adb4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,29 +1,38 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 25 - buildToolsVersion "25.0.1" + compileSdk 33 defaultConfig { - applicationId "com.cyngn.designertools" - minSdkVersion 23 - targetSdkVersion 25 - versionCode 2 - versionName "2.0.0" + applicationId "com.scheffsblend.designertools" + minSdkVersion 24 + targetSdkVersion 33 + versionCode 6 + versionName "2.2.2" + setProperty("archivesBaseName", "DesignerTools-$versionName") } buildTypes { release { - minifyEnabled false + minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + dependenciesInfo { + includeInApk true + includeInBundle true + } + buildToolsVersion '33.0.0' + namespace 'org.cyanogenmod.designertools' } dependencies { - compile fileTree(include: ['*.jar'], dir: 'libs') - testCompile 'junit:junit:4.12' - compile 'com.android.support:appcompat-v7:25.1.0' - compile 'org.cyanogenmod:platform.sdk:6.0' - compile 'com.larswerkman:lobsterpicker:1.0.1' - compile 'fr.avianey.com.viewpagerindicator:library:2.4.1.1@aar' + implementation fileTree(include: ['*.jar'], dir: 'libs') + testImplementation 'junit:junit:4.12' + implementation 'androidx.appcompat:appcompat:1.5.1' + implementation 'com.larswerkman:lobsterpicker:1.0.1' + implementation 'fr.avianey.com.viewpagerindicator:library:2.4.1.1@aar' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 1a39748..d4aa178 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,12 +1,16 @@ - - - - - + + + + + + - + + - - - - - - - - - - - - - - - - - + - + @@ -80,6 +78,7 @@ android:name=".service.qs.GridOverlayTileService" android:icon="@drawable/ic_qs_grid_off" android:label="@string/grid_qs_tile_label" + android:exported="true" android:permission="android.permission.BIND_QUICK_SETTINGS_TILE"> @@ -90,6 +89,7 @@ android:name=".service.qs.MockOverlayTileService" android:icon="@drawable/ic_qs_overlay_off" android:label="@string/mock_qs_tile_label" + android:exported="true" android:permission="android.permission.BIND_QUICK_SETTINGS_TILE"> @@ -100,6 +100,7 @@ android:name=".service.qs.ColorPickerTileService" android:icon="@drawable/ic_qs_colorpicker_off" android:label="@string/color_picker_qs_tile_label" + android:exported="true" android:permission="android.permission.BIND_QUICK_SETTINGS_TILE"> diff --git a/app/src/main/java/org/cyanogenmod/designertools/DesignerToolsApplication.java b/app/src/main/java/org/cyanogenmod/designertools/DesignerToolsApplication.java index 3f78152..f447423 100644 --- a/app/src/main/java/org/cyanogenmod/designertools/DesignerToolsApplication.java +++ b/app/src/main/java/org/cyanogenmod/designertools/DesignerToolsApplication.java @@ -19,6 +19,10 @@ import android.app.Application; import android.content.Intent; +import org.cyanogenmod.designertools.utils.PreferenceUtils.ColorPickerPreferences; +import org.cyanogenmod.designertools.utils.PreferenceUtils.GridPreferences; +import org.cyanogenmod.designertools.utils.PreferenceUtils.MockPreferences; + public class DesignerToolsApplication extends Application { private int mResultCode = Activity.RESULT_CANCELED; @@ -47,7 +51,7 @@ public void setGridOverlayOn(boolean on) { } public boolean getGridOverlayOn() { - return mGridOverlayOn; + return mGridOverlayOn || GridPreferences.getGridQsTileEnabled(this, false); } public void setMockOverlayOn(boolean on) { @@ -55,7 +59,7 @@ public void setMockOverlayOn(boolean on) { } public boolean getMockOverlayOn() { - return mMockOverlayOn; + return mMockOverlayOn || MockPreferences.getMockQsTileEnabled(this, false); } public void setColorPickerOn(boolean on) { @@ -63,7 +67,7 @@ public void setColorPickerOn(boolean on) { } public boolean getColorPickerOn() { - return mColorPickerOn; + return mColorPickerOn || ColorPickerPreferences.getColorPickerQsTileEnabled(this, false); } public void setScreenshotOn(boolean on) { diff --git a/app/src/main/java/org/cyanogenmod/designertools/overlays/ColorPickerOverlay.java b/app/src/main/java/org/cyanogenmod/designertools/overlays/ColorPickerOverlay.java index 93a2428..73840c6 100644 --- a/app/src/main/java/org/cyanogenmod/designertools/overlays/ColorPickerOverlay.java +++ b/app/src/main/java/org/cyanogenmod/designertools/overlays/ColorPickerOverlay.java @@ -15,14 +15,15 @@ */ package org.cyanogenmod.designertools.overlays; +import android.animation.Animator; +import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; +import android.annotation.SuppressLint; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; -import android.content.BroadcastReceiver; -import android.content.Context; import android.content.Intent; -import android.content.IntentFilter; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Bitmap; @@ -39,16 +40,19 @@ import android.media.projection.MediaProjectionManager; import android.os.Handler; import android.os.IBinder; +import androidx.interpolator.view.animation.FastOutSlowInInterpolator; import android.util.DisplayMetrics; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; +import android.view.ViewTreeObserver; import android.view.WindowManager; +import android.view.animation.OvershootInterpolator; import org.cyanogenmod.designertools.DesignerToolsApplication; -import org.cyanogenmod.designertools.qs.ColorPickerQuickSettingsTile; -import org.cyanogenmod.designertools.qs.OnOffTileState; import org.cyanogenmod.designertools.R; +import org.cyanogenmod.designertools.utils.NotificationUtils; +import org.cyanogenmod.designertools.utils.ViewUtils; import org.cyanogenmod.designertools.widget.MagnifierNodeView; import org.cyanogenmod.designertools.widget.MagnifierView; @@ -56,6 +60,7 @@ public class ColorPickerOverlay extends Service { private static final int NOTIFICATION_ID = ColorPickerOverlay.class.hashCode(); + private static final String CHANNEL_ID = "DesignerTools.ColorPickerOverlay"; private static final String ACTION_HIDE_PICKER = "hide_picker"; private static final String ACTION_SHOW_PICKER = "show_picker"; @@ -66,7 +71,6 @@ public class ColorPickerOverlay extends Service { private WindowManager.LayoutParams mNodeParams; private WindowManager.LayoutParams mMagnifierParams; - private MediaProjectionManager mMediaProjectionManager; private MediaProjection mMediaProjection; private VirtualDisplay mVirtualDisplay; private ImageReader mImageReader; @@ -88,6 +92,8 @@ public class ColorPickerOverlay extends Service { private final Object mScreenCaptureLock = new Object(); + private boolean mAnimating = false; + @Override public IBinder onBind(Intent intent) { return null; @@ -108,21 +114,22 @@ public void onDestroy() { mMediaProjection = null; mVirtualDisplay = null; - if (mReceiver != null) { - unregisterReceiver(mReceiver); - mReceiver = null; - } if (mImageReader != null) { mImageReader.close(); mImageReader = null; } if (mMagnifierView != null) { - removeViewIfAttached(mMagnifierView); - mMagnifierView = null; - } - if (mMagnifierNodeView != null) { - removeViewIfAttached(mMagnifierNodeView); - mMagnifierNodeView = null; + animateColorPickerOut(new Runnable() { + @Override + public void run() { + removeViewIfAttached(mMagnifierView); + mMagnifierView = null; + if (mMagnifierNodeView != null) { + removeViewIfAttached(mMagnifierNodeView); + mMagnifierNodeView = null; + } + } + }); } ((DesignerToolsApplication) getApplicationContext()).setColorPickerOn(false); } @@ -138,6 +145,7 @@ public void onConfigurationChanged(Configuration newConfig) { } private void setup() { + startForeground(NOTIFICATION_ID, getPersistentNotification(true)); mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE); setupMediaProjection(); @@ -152,14 +160,14 @@ private void setup() { mNodeParams = new WindowManager.LayoutParams( nodeViewSize, nodeViewSize, - WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, + ViewUtils.getWindowType(true), WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN, PixelFormat.TRANSLUCENT); mNodeParams.gravity = Gravity.TOP | Gravity.LEFT; mMagnifierParams = new WindowManager.LayoutParams( magnifierWidth, magnifierHeight, - WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, + ViewUtils.getWindowType(true), WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN, PixelFormat.TRANSLUCENT); @@ -171,13 +179,21 @@ private void setup() { mNodeParams.y = y - nodeViewSize / 2; mMagnifierParams.x = x - magnifierWidth / 2; - mMagnifierParams.y = mNodeParams.y - magnifierHeight; + mMagnifierParams.y = mNodeParams.y - (magnifierHeight + nodeViewSize / 2); mMagnifierView = (MagnifierView) View.inflate(this, R.layout.color_picker_magnifier, null); mMagnifierView.setOnTouchListener(mDampenedOnTouchListener); mMagnifierNodeView = new MagnifierNodeView(this); mMagnifierNodeView.setOnTouchListener(mOnTouchListener); addOverlayViewsIfDetached(); + mMagnifierView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { + @Override + public boolean onPreDraw() { + animateColorPickerIn(); + mMagnifierView.getViewTreeObserver().removeOnPreDrawListener(this); + return false; + } + }); mPreviewSampleWidth = res.getInteger(R.integer.color_picker_sample_width); mPreviewSampleHeight = res.getInteger(R.integer.color_picker_sample_height); @@ -188,13 +204,6 @@ private void setup() { mLastPosition = new PointF(); mStartPosition = new PointF(); mDampeningFactor = DAMPENING_FACTOR_DP * dm.density; - - IntentFilter filter = new IntentFilter(ColorPickerQuickSettingsTile.ACTION_TOGGLE_STATE); - filter.addAction(ColorPickerQuickSettingsTile.ACTION_UNPUBLISH); - filter.addAction(ACTION_HIDE_PICKER); - filter.addAction(ACTION_SHOW_PICKER); - registerReceiver(mReceiver, filter); - startForeground(NOTIFICATION_ID, getPersistentNotification(true)); } private void removeViewIfAttached(View v) { @@ -209,12 +218,138 @@ private void removeOverlayViewsIfAttached() { } private void addOverlayViewsIfDetached () { + if (mMagnifierNodeView != null && !mMagnifierNodeView.isAttachedToWindow()) { + mWindowManager.addView(mMagnifierNodeView, mNodeParams); + } if (mMagnifierView != null && !mMagnifierView.isAttachedToWindow()) { mWindowManager.addView(mMagnifierView, mMagnifierParams); } - if (mMagnifierNodeView != null && !mMagnifierNodeView.isAttachedToWindow()) { - mWindowManager.addView(mMagnifierNodeView, mNodeParams); + } + + private void animateColorPickerIn() { + mMagnifierView.setScaleX(0); + mMagnifierView.setScaleY(0); + mMagnifierView.setVisibility(View.VISIBLE); + mMagnifierNodeView.setVisibility(View.GONE); + + final int startX = mMagnifierParams.x + (mMagnifierParams.width - mNodeParams.width) / 2; + final int startY = mMagnifierParams.y + (mMagnifierParams.height - mNodeParams.height) / 2; + final int endX = mNodeParams.x; + final int endY = mNodeParams.y; + mNodeParams.x = startX; + mNodeParams.y = startY; + mWindowManager.updateViewLayout(mMagnifierNodeView, mNodeParams); + final ValueAnimator animator = ObjectAnimator.ofFloat(null, "", 0f, 1f); + animator.setDuration(200); + animator.setInterpolator(new OvershootInterpolator()); + animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator valueAnimator) { + float fraction = valueAnimator.getAnimatedFraction(); + mNodeParams.x = startX + (int) (fraction * (endX - startX)); + mNodeParams.y = startY + (int) (fraction * (endY - startY)); + mWindowManager.updateViewLayout(mMagnifierNodeView, mNodeParams); + } + }); + animator.addListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animator) { + mAnimating = true; + mMagnifierNodeView.setVisibility(View.VISIBLE); + } + + @Override + public void onAnimationEnd(Animator animator) { + mAnimating = false; + } + + @Override + public void onAnimationCancel(Animator animator) { + } + + @Override + public void onAnimationRepeat(Animator animator) { + } + }); + + mMagnifierView.animate() + .scaleX(1f) + .scaleY(1f) + .setInterpolator(new OvershootInterpolator()) + .setDuration(250) + .withEndAction(new Runnable() { + @Override + public void run() { + animator.start(); + } + }); + + } + + private void animateColorPickerOut(final Runnable endAction) { + if (mMagnifierView == null || !mMagnifierView.isAttachedToWindow()) { + if (endAction != null) { + endAction.run(); + return; + } } + final int endX = mMagnifierParams.x + (mMagnifierParams.width - mNodeParams.width) / 2; + final int endY = mMagnifierParams.y + (mMagnifierParams.height - mNodeParams.height) / 2; + final int startX = mNodeParams.x; + final int startY = mNodeParams.y; + mNodeParams.x = startX; + mNodeParams.y = startY; + mWindowManager.updateViewLayout(mMagnifierNodeView, mNodeParams); + final ValueAnimator animator = ObjectAnimator.ofFloat(null, "", 0f, 1f); + animator.setDuration(200); + animator.setInterpolator(new FastOutSlowInInterpolator()); + animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator valueAnimator) { + float fraction = valueAnimator.getAnimatedFraction(); + mNodeParams.x = startX + (int) (fraction * (endX - startX)); + mNodeParams.y = startY + (int) (fraction * (endY - startY)); + mWindowManager.updateViewLayout(mMagnifierNodeView, mNodeParams); + } + }); + animator.addListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animator) { + mAnimating = true; + mMagnifierNodeView.setVisibility(View.VISIBLE); + } + + @Override + public void onAnimationEnd(Animator animator) { + mAnimating = false; + mMagnifierNodeView.setVisibility(View.GONE); + mNodeParams.x = startX; + mNodeParams.y = startY; + mMagnifierView.animate() + .scaleX(0) + .scaleY(0) + .setInterpolator(new FastOutSlowInInterpolator()) + .withEndAction(new Runnable() { + @Override + public void run() { + mMagnifierView.setVisibility(View.GONE); + if (endAction != null) { + endAction.run(); + } + } + }); + + } + + @Override + public void onAnimationCancel(Animator animator) { + } + + @Override + public void onAnimationRepeat(Animator animator) { + } + }); + animator.start(); } public Bitmap getScreenBitmapRegion(Image image, Rect region) { @@ -249,6 +384,7 @@ public Bitmap getScreenBitmapRegion(Image image, Rect region) { return bmp; } + @SuppressLint("WrongConstant") private void setupMediaProjection() { final DesignerToolsApplication app = (DesignerToolsApplication) getApplication(); final DisplayMetrics dm = getResources().getDisplayMetrics(); @@ -257,8 +393,8 @@ private void setupMediaProjection() { mImageReader = ImageReader.newInstance(size.x, size.y, PixelFormat.RGBA_8888, 2); mImageReader.setOnImageAvailableListener(mImageAvailableListener, new Handler()); - mMediaProjectionManager = getSystemService(MediaProjectionManager.class); - mMediaProjection = mMediaProjectionManager.getMediaProjection(app.getScreenRecordResultCode(), + MediaProjectionManager mediaProjectionManager = getSystemService(MediaProjectionManager.class); + mMediaProjection = mediaProjectionManager.getMediaProjection(app.getScreenRecordResultCode(), app.getScreenRecordResultData()); mVirtualDisplay = mMediaProjection.createVirtualDisplay( ColorPickerOverlay.class.getSimpleName(), @@ -287,20 +423,23 @@ private void updateNotification(boolean actionIsHide) { } private Notification getPersistentNotification(boolean actionIsHide) { - PendingIntent pi = PendingIntent.getBroadcast(this, 0, - new Intent(actionIsHide ? ACTION_HIDE_PICKER : ACTION_SHOW_PICKER), 0); - Notification.Builder builder = new Notification.Builder(this); - builder.setPriority(Notification.PRIORITY_MIN) - .setSmallIcon(actionIsHide ? R.drawable.ic_qs_colorpicker_on - : R.drawable.ic_qs_colorpicker_off) - .setContentTitle(getString(R.string.color_picker_qs_tile_label)) - .setContentText(getString(actionIsHide ? R.string.notif_content_hide_picker - : R.string.notif_content_show_picker)) - .setStyle(new Notification.BigTextStyle().bigText( - getString(actionIsHide ? R.string.notif_content_hide_picker - : R.string.notif_content_show_picker))) - .setContentIntent(pi); - return builder.build(); + int icon = actionIsHide ? R.drawable.ic_qs_colorpicker_on + : R.drawable.ic_qs_colorpicker_off; + final String contentText = getString(actionIsHide ? R.string.notif_content_hide_picker + : R.string.notif_content_show_picker); + final PendingIntent pi = PendingIntent.getBroadcast( + this, + 0, + new Intent(actionIsHide ? ACTION_HIDE_PICKER : ACTION_SHOW_PICKER), + PendingIntent.FLAG_IMMUTABLE); + + return NotificationUtils.createForegroundServiceNotification( + this, + CHANNEL_ID, + icon, + getString(R.string.color_picker_qs_tile_label), + contentText, + pi); } private void updateMagnifierViewPosition(int x, int y, float angle) { @@ -327,45 +466,21 @@ public void onImageAvailable(ImageReader reader) { synchronized (mScreenCaptureLock) { Image newImage = reader.acquireNextImage(); if (newImage != null) { - if (mMagnifierView != null) { + if (!mAnimating && mMagnifierView != null) { mMagnifierView.setPixels(getScreenBitmapRegion(newImage, mPreviewArea)); - newImage.close(); } + newImage.close(); } } } }; - private BroadcastReceiver mReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - final String action = intent.getAction(); - if (ColorPickerQuickSettingsTile.ACTION_UNPUBLISH.equals(action)) { - stopSelf(); - } else if (ColorPickerQuickSettingsTile.ACTION_TOGGLE_STATE.equals(action)) { - int state = - intent.getIntExtra(OnOffTileState.EXTRA_STATE, OnOffTileState.STATE_OFF); - if (state == OnOffTileState.STATE_ON) { - stopSelf(); - } - } else if (ACTION_HIDE_PICKER.equals(action)) { - removeOverlayViewsIfAttached(); - teardownMediaProjection(); - updateNotification(false); - } else if (ACTION_SHOW_PICKER.equals(action)) { - addOverlayViewsIfDetached(); - setupMediaProjection(); - updateNotification(true); - } - } - }; - private View.OnTouchListener mOnTouchListener = new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: - mMagnifierNodeView.setVisibility(View.INVISIBLE); + mMagnifierNodeView.setAlpha(0); break; case MotionEvent.ACTION_MOVE: final float rawX = event.getRawX(); @@ -377,7 +492,7 @@ public boolean onTouch(View v, MotionEvent event) { break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: - mMagnifierNodeView.setVisibility(View.VISIBLE); + mMagnifierNodeView.setAlpha(1.0f); break; } return true; diff --git a/app/src/main/java/org/cyanogenmod/designertools/overlays/GridOverlay.java b/app/src/main/java/org/cyanogenmod/designertools/overlays/GridOverlay.java index 3e87f81..93fa5ea 100644 --- a/app/src/main/java/org/cyanogenmod/designertools/overlays/GridOverlay.java +++ b/app/src/main/java/org/cyanogenmod/designertools/overlays/GridOverlay.java @@ -19,10 +19,8 @@ import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; -import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; -import android.content.IntentFilter; import android.content.SharedPreferences; import android.graphics.Canvas; import android.graphics.Paint; @@ -38,14 +36,16 @@ import android.view.WindowManager; import org.cyanogenmod.designertools.DesignerToolsApplication; -import org.cyanogenmod.designertools.qs.GridQuickSettingsTile; -import org.cyanogenmod.designertools.qs.OnOffTileState; import org.cyanogenmod.designertools.R; import org.cyanogenmod.designertools.utils.ColorUtils; +import org.cyanogenmod.designertools.utils.NotificationUtils; import org.cyanogenmod.designertools.utils.PreferenceUtils; +import org.cyanogenmod.designertools.utils.PreferenceUtils.GridPreferences; +import org.cyanogenmod.designertools.utils.ViewUtils; public class GridOverlay extends Service { private static final int NOTIFICATION_ID = GridOverlay.class.hashCode(); + private static final String CHANNEL_ID = "DesignerTools.GridOverlay"; private static final String ACTION_HIDE_OVERLAY = "hide_grid_overlay"; private static final String ACTION_SHOW_OVERLAY = "show_grid_overlay"; @@ -70,12 +70,13 @@ public void onCreate() { public void onDestroy() { super.onDestroy(); if (mOverlayView != null) { - removeViewIfAttached(mOverlayView); - mOverlayView = null; - } - if (mReceiver != null) { - unregisterReceiver(mReceiver); - mReceiver = null; + hideOverlay(new Runnable() { + @Override + public void run() { + removeViewIfAttached(mOverlayView); + mOverlayView = null; + } + }); } ((DesignerToolsApplication) getApplicationContext()).setGridOverlayOn(false); } @@ -83,7 +84,7 @@ public void onDestroy() { private void setup() { mParams = new WindowManager.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, - WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY, + ViewUtils.getWindowType(), WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT); mOverlayView = new GridOverlayView(this); @@ -98,11 +99,6 @@ public boolean onPreDraw() { return false; } }); - IntentFilter filter = new IntentFilter(GridQuickSettingsTile.ACTION_TOGGLE_STATE); - filter.addAction(GridQuickSettingsTile.ACTION_UNPUBLISH); - filter.addAction(ACTION_HIDE_OVERLAY); - filter.addAction(ACTION_SHOW_OVERLAY); - registerReceiver(mReceiver, filter); startForeground(NOTIFICATION_ID, getPersistentNotification(true)); } @@ -118,50 +114,23 @@ private void updateNotification(boolean actionIsHide) { } private Notification getPersistentNotification(boolean actionIsHide) { - PendingIntent pi = PendingIntent.getBroadcast(this, 0, - new Intent(actionIsHide ? ACTION_HIDE_OVERLAY : ACTION_SHOW_OVERLAY), 0); - Notification.Builder builder = new Notification.Builder(this); - String text = getString(actionIsHide ? R.string.notif_content_hide_grid_overlay + int icon = actionIsHide ? R.drawable.ic_qs_grid_on + : R.drawable.ic_qs_grid_off; + final String contentText = getString(actionIsHide ? R.string.notif_content_hide_grid_overlay : R.string.notif_content_show_grid_overlay); - builder.setPriority(Notification.PRIORITY_MIN) - .setSmallIcon(actionIsHide ? R.drawable.ic_qs_grid_on - : R.drawable.ic_qs_grid_off) - .setContentTitle(getString(R.string.grid_qs_tile_label)) - .setContentText(text) - .setStyle(new Notification.BigTextStyle().bigText(text)) - .setContentIntent(pi); - return builder.build(); - } - - private BroadcastReceiver mReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - final String action = intent.getAction(); - if (GridQuickSettingsTile.ACTION_UNPUBLISH.equals(action)) { - stopSelf(); - } else if (GridQuickSettingsTile.ACTION_TOGGLE_STATE.equals(action)) { - int state = - intent.getIntExtra(OnOffTileState.EXTRA_STATE, OnOffTileState.STATE_OFF); - if (state == OnOffTileState.STATE_ON) { - stopSelf(); - } - } else if (ACTION_HIDE_OVERLAY.equals(action)) { - hideOverlay(new Runnable() { - @Override - public void run() { - updateNotification(false); - } - }); - } else if (ACTION_SHOW_OVERLAY.equals(action)) { - showOverlay(); - } - } - }; - - private void showOverlay() { - mWindowManager.addView(mOverlayView, mParams); - updateNotification(true); - mOverlayView.animate().alpha(1f); + final PendingIntent pi = PendingIntent.getBroadcast( + this, + 0, + new Intent(actionIsHide ? ACTION_HIDE_OVERLAY : ACTION_SHOW_OVERLAY), + PendingIntent.FLAG_IMMUTABLE); + + return NotificationUtils.createForegroundServiceNotification( + this, + CHANNEL_ID, + icon, + getString(R.string.grid_qs_tile_label), + contentText, + pi); } private void hideOverlay(final Runnable endAction) { @@ -193,10 +162,9 @@ static class GridOverlayView extends View { private Rect mSecondKeylineMarkerBounds; private Rect mThirdKeylineMarkerBounds; - private boolean mShowGrid = false; - private boolean mShowKeylines = false; + private boolean mShowGrid; + private boolean mShowKeylines; - private float mGridLineWidth; private float mColumnSize; private float mRowSize; private float mDensity; @@ -206,10 +174,10 @@ public GridOverlayView(Context context) { super(context); mDensity = getResources().getDisplayMetrics().density; - mGridLineWidth = mDensity; mGridPaint = new Paint(); mGridPaint.setColor(ColorUtils.getGridLineColor(context)); - mGridPaint.setStrokeWidth(mGridLineWidth); + float gridLineWidth = mDensity; + mGridPaint.setStrokeWidth(gridLineWidth); mKeylinePaint = new Paint(); mKeylinePaint.setColor(ColorUtils.getKeylineColor(context)); @@ -218,18 +186,17 @@ public GridOverlayView(Context context) { mHorizontalMarkerRight = context.getDrawable(R.drawable.ic_marker_horiz_right); mVerticalMarker = context.getDrawable(R.drawable.ic_marker_vert); - SharedPreferences prefs = PreferenceUtils.getShardedPreferences(context); - mShowGrid = PreferenceUtils.getShowGrid(context, false); - mShowKeylines = PreferenceUtils.getShowKeylines(context, false); + mShowGrid = GridPreferences.getShowGrid(context, false); + mShowKeylines = GridPreferences.getShowKeylines(context, false); - boolean useCustom = PreferenceUtils.getUseCustomGridSize(getContext(), + boolean useCustom = GridPreferences.getUseCustomGridSize(getContext(), false); int defColumnSize = getResources().getInteger( R.integer.default_column_size); int defRowSize = getResources().getInteger(R.integer.default_row_size); - mColumnSize = mDensity * (!useCustom ? defColumnSize : PreferenceUtils + mColumnSize = mDensity * (!useCustom ? defColumnSize : GridPreferences .getGridColumnSize(getContext(), defColumnSize)); - mRowSize = mDensity * (!useCustom ? defRowSize : PreferenceUtils + mRowSize = mDensity * (!useCustom ? defRowSize : GridPreferences .getGridRowSize(getContext(), defRowSize)); mKeylineWidth = 1.5f * mDensity; } @@ -269,10 +236,12 @@ protected void onSizeChanged(int w, int h, int oldw, int oldh) { x = dm.widthPixels - (int)(16 * dm.density); mThirdKeylineMarkerBounds = new Rect(x, y, x + width, y + height); - mFirstKeylineRect = new RectF(0, 0, 16 * dm.density, dm.heightPixels); - mSecondKeylineRect = new RectF(56 * dm.density, 0, 72 * dm.density, dm.heightPixels); + int keylineHeight = getHeight(); + mFirstKeylineRect = new RectF(0, 0, 16 * dm.density, keylineHeight); + mSecondKeylineRect = new RectF(56 * dm.density, 0, 72 * dm.density, + keylineHeight); mThirdKeylineRect = new RectF(dm.widthPixels - 16 * dm.density, 0, dm.widthPixels, - dm.heightPixels); + keylineHeight); } @Override @@ -295,43 +264,43 @@ protected void onDetachedFromWindow() { @Override public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { - if (PreferenceUtils.KEY_SHOW_GRID.equals(key)) { + if (GridPreferences.KEY_SHOW_GRID.equals(key)) { boolean enabled = - prefs.getBoolean(PreferenceUtils.KEY_SHOW_GRID, false); + prefs.getBoolean(GridPreferences.KEY_SHOW_GRID, false); if (mShowGrid != enabled) { mShowGrid = enabled; invalidate(); } - } else if (PreferenceUtils.KEY_SHOW_KEYLINES.equals(key)) { + } else if (GridPreferences.KEY_SHOW_KEYLINES.equals(key)) { boolean enabled = - prefs.getBoolean(PreferenceUtils.KEY_SHOW_KEYLINES, false); + prefs.getBoolean(GridPreferences.KEY_SHOW_KEYLINES, false); if (enabled != mShowKeylines) { mShowKeylines = enabled; invalidate(); } - } else if (PreferenceUtils.KEY_GRID_COLUMN_SIZE.equals(key)) { - mColumnSize = mDensity * PreferenceUtils.getGridColumnSize(getContext(), + } else if (GridPreferences.KEY_GRID_COLUMN_SIZE.equals(key)) { + mColumnSize = mDensity * GridPreferences.getGridColumnSize(getContext(), getResources().getInteger(R.integer.default_column_size)); invalidate(); - } else if (PreferenceUtils.KEY_GRID_ROW_SIZE.equals(key)) { - mRowSize = mDensity * PreferenceUtils.getGridRowSize(getContext(), + } else if (GridPreferences.KEY_GRID_ROW_SIZE.equals(key)) { + mRowSize = mDensity * GridPreferences.getGridRowSize(getContext(), getResources().getInteger(R.integer.default_row_size)); invalidate(); - } else if (PreferenceUtils.KEY_GRID_LINE_COLOR.equals(key)) { + } else if (GridPreferences.KEY_GRID_LINE_COLOR.equals(key)) { mGridPaint.setColor(ColorUtils.getGridLineColor(getContext())); invalidate(); - } else if (PreferenceUtils.KEY_KEYLINE_COLOR.equals(key)) { + } else if (GridPreferences.KEY_KEYLINE_COLOR.equals(key)) { mKeylinePaint.setColor(ColorUtils.getKeylineColor(getContext())); invalidate(); - } else if (PreferenceUtils.KEY_USE_CUSTOM_GRID_SIZE.equals(key)) { - boolean useCustom = PreferenceUtils.getUseCustomGridSize(getContext(), + } else if (GridPreferences.KEY_USE_CUSTOM_GRID_SIZE.equals(key)) { + boolean useCustom = GridPreferences.getUseCustomGridSize(getContext(), false); int defColumnSize = getResources().getInteger( R.integer.default_column_size); int defRowSize = getResources().getInteger(R.integer.default_row_size); - mColumnSize = mDensity * (!useCustom ? defColumnSize : PreferenceUtils + mColumnSize = mDensity * (!useCustom ? defColumnSize : GridPreferences .getGridColumnSize(getContext(), defColumnSize)); - mRowSize = mDensity * (!useCustom ? defRowSize : PreferenceUtils + mRowSize = mDensity * (!useCustom ? defRowSize : GridPreferences .getGridRowSize(getContext(), defRowSize)); invalidate(); } diff --git a/app/src/main/java/org/cyanogenmod/designertools/overlays/MockOverlay.java b/app/src/main/java/org/cyanogenmod/designertools/overlays/MockOverlay.java index 35836bc..571dafb 100644 --- a/app/src/main/java/org/cyanogenmod/designertools/overlays/MockOverlay.java +++ b/app/src/main/java/org/cyanogenmod/designertools/overlays/MockOverlay.java @@ -19,40 +19,34 @@ import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; -import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; -import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.res.Configuration; import android.graphics.Bitmap; -import android.graphics.BitmapFactory; import android.graphics.PixelFormat; +import android.graphics.Point; import android.os.IBinder; +import androidx.appcompat.widget.AppCompatImageView; import android.view.View; -import android.view.ViewGroup; +import android.view.ViewTreeObserver; import android.view.WindowManager; -import android.widget.ImageView; import org.cyanogenmod.designertools.DesignerToolsApplication; import org.cyanogenmod.designertools.R; -import org.cyanogenmod.designertools.qs.MockQuickSettingsTile; -import org.cyanogenmod.designertools.qs.OnOffTileState; import org.cyanogenmod.designertools.utils.MockupUtils; +import org.cyanogenmod.designertools.utils.NotificationUtils; import org.cyanogenmod.designertools.utils.PreferenceUtils; - -import java.io.File; +import org.cyanogenmod.designertools.utils.PreferenceUtils.MockPreferences; +import org.cyanogenmod.designertools.utils.ViewUtils; public class MockOverlay extends Service { private static final int NOTIFICATION_ID = MockOverlay.class.hashCode(); + private static final String CHANNEL_ID = "DesignerTools.MockOverlay"; private static final String ACTION_HIDE_OVERLAY = "hide_mock_overlay"; private static final String ACTION_SHOW_OVERLAY = "show_mock_overlay"; - private static final String MOCK_OVERLAY_FILENAME = "mock_overlay.png"; - - private static Bitmap sOverlayImage; - private WindowManager mWindowManager; private MockOverlayView mOverlayView; private WindowManager.LayoutParams mParams; @@ -73,32 +67,39 @@ public void onCreate() { public void onDestroy() { super.onDestroy(); if (mOverlayView != null) { - removeViewIfAttached(mOverlayView); - mOverlayView = null; - } - if (mReceiver != null) { - unregisterReceiver(mReceiver); - mReceiver = null; + hideOverlay(new Runnable() { + @Override + public void run() { + removeViewIfAttached(mOverlayView); + mOverlayView = null; + } + }); } ((DesignerToolsApplication) getApplicationContext()).setMockOverlayOn(false); } private void setup() { + mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE); + Point size = new Point(); + mWindowManager.getDefaultDisplay().getRealSize(size); mParams = new WindowManager.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, - WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY, + size.x, size.y, + ViewUtils.getWindowType(), WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN, PixelFormat.TRANSPARENT); mOverlayView = new MockOverlayView(this); - mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE); + mOverlayView.setAlpha(0f); mWindowManager.addView(mOverlayView, mParams); - IntentFilter filter = new IntentFilter(MockQuickSettingsTile.ACTION_TOGGLE_STATE); - filter.addAction(MockQuickSettingsTile.ACTION_UNPUBLISH); - filter.addAction(ACTION_HIDE_OVERLAY); - filter.addAction(ACTION_SHOW_OVERLAY); - registerReceiver(mReceiver, filter); + mOverlayView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { + @Override + public boolean onPreDraw() { + mOverlayView.animate().alpha(1f); + mOverlayView.getViewTreeObserver().removeOnPreDrawListener(this); + return false; + } + }); startForeground(NOTIFICATION_ID, getPersistentNotification(true)); } @@ -114,56 +115,43 @@ private void updateNotification(boolean actionIsHide) { } private Notification getPersistentNotification(boolean actionIsHide) { - PendingIntent pi = PendingIntent.getBroadcast(this, 0, - new Intent(actionIsHide ? ACTION_HIDE_OVERLAY : ACTION_SHOW_OVERLAY), 0); - Notification.Builder builder = new Notification.Builder(this); - String text = getString(actionIsHide ? R.string.notif_content_hide_mock_overlay + int icon = actionIsHide ? R.drawable.ic_qs_overlay_on + : R.drawable.ic_qs_overlay_off; + final String contentText = getString(actionIsHide ? R.string.notif_content_hide_mock_overlay : R.string.notif_content_show_mock_overlay); - builder.setPriority(Notification.PRIORITY_MIN) - .setSmallIcon(actionIsHide ? R.drawable.ic_qs_overlay_on - : R.drawable.ic_qs_overlay_off) - .setContentTitle(getString(R.string.mock_qs_tile_label)) - .setContentText(text) - .setStyle(new Notification.BigTextStyle().bigText(text)) - .setContentIntent(pi); - return builder.build(); + final PendingIntent pi = PendingIntent.getBroadcast( + this, + 0, + new Intent(actionIsHide ? ACTION_HIDE_OVERLAY : ACTION_SHOW_OVERLAY), + PendingIntent.FLAG_IMMUTABLE); + + return NotificationUtils.createForegroundServiceNotification( + this, + CHANNEL_ID, + icon, + getString(R.string.mock_qs_tile_label), + contentText, + pi); } - private BroadcastReceiver mReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - final String action = intent.getAction(); - if (MockQuickSettingsTile.ACTION_UNPUBLISH.equals(action)) { - stopSelf(); - } else if (MockQuickSettingsTile.ACTION_TOGGLE_STATE.equals(action)) { - int state = - intent.getIntExtra(OnOffTileState.EXTRA_STATE, OnOffTileState.STATE_OFF); - if (state == OnOffTileState.STATE_ON) { - stopSelf(); - } - } else if (ACTION_HIDE_OVERLAY.equals(action)) { + private void showOverlay() { + mWindowManager.addView(mOverlayView, mParams); + updateNotification(true); + mOverlayView.animate().alpha(1f); + } + + private void hideOverlay(final Runnable endAction) { + mOverlayView.animate().alpha(0f).withEndAction(new Runnable() { + @Override + public void run() { + mOverlayView.setAlpha(0f); removeViewIfAttached(mOverlayView); - updateNotification(false); - } else if (ACTION_SHOW_OVERLAY.equals(action)) { - mWindowManager.addView(mOverlayView, mParams); - updateNotification(true); + if (endAction != null) endAction.run(); } - } - }; - - public static Bitmap getMockOverlayBitmap(Context context) { - if (sOverlayImage == null) { - File filesDir = context.getFilesDir(); - File mockOverlayFile = new File(filesDir, MOCK_OVERLAY_FILENAME); - if (mockOverlayFile.exists()) { - sOverlayImage = BitmapFactory.decodeFile(mockOverlayFile.getAbsolutePath()); - } - } - - return sOverlayImage; + }); } - static class MockOverlayView extends ImageView { + static class MockOverlayView extends AppCompatImageView { public MockOverlayView(Context context) { super(context); } @@ -174,7 +162,7 @@ protected void onAttachedToWindow() { SharedPreferences prefs = PreferenceUtils.getShardedPreferences(getContext()); prefs.registerOnSharedPreferenceChangeListener(mPreferenceChangeListener); setImageBitmap(getBitmapForOrientation(getResources().getConfiguration().orientation)); - setAlpha(PreferenceUtils.getMockOpacity(getContext(), 10) / 100f); + setImageAlpha(MockPreferences.getMockOpacity(getContext(), 10)); invalidate(); } @@ -202,14 +190,13 @@ private Bitmap getBitmapForOrientation(int orientation) { @Override public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { - if (PreferenceUtils.KEY_MOCKUP_OVERLAY_PORTRAIT.equals(key) || - PreferenceUtils.KEY_MOCKUP_OVERLAY_LANDSCAPE.equals(key)) { + if (MockPreferences.KEY_MOCKUP_OVERLAY_PORTRAIT.equals(key) || + MockPreferences.KEY_MOCKUP_OVERLAY_LANDSCAPE.equals(key)) { setImageBitmap(getBitmapForOrientation( getResources().getConfiguration().orientation)); invalidate(); - } else if (PreferenceUtils.KEY_MOCK_OPACITY.equals(key)) { - int opacity = PreferenceUtils.getMockOpacity(getContext(), 10); - setAlpha(opacity / 100f); + } else if (MockPreferences.KEY_MOCK_OPACITY.equals(key)) { + setImageAlpha(MockPreferences.getMockOpacity(getContext(), 10)); invalidate(); } } diff --git a/app/src/main/java/org/cyanogenmod/designertools/qs/ColorPickerQuickSettingsTile.java b/app/src/main/java/org/cyanogenmod/designertools/qs/ColorPickerQuickSettingsTile.java deleted file mode 100644 index e56291f..0000000 --- a/app/src/main/java/org/cyanogenmod/designertools/qs/ColorPickerQuickSettingsTile.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (C) 2016 The CyanogenMod Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.cyanogenmod.designertools.qs; - -import android.app.Activity; -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; - -import org.cyanogenmod.designertools.DesignerToolsApplication; -import org.cyanogenmod.designertools.overlays.ColorPickerOverlay; -import org.cyanogenmod.designertools.ui.ScreenRecordRequestActivity; -import org.cyanogenmod.designertools.utils.PreferenceUtils; -import org.cyanogenmod.designertools.R; - -import cyanogenmod.app.CMStatusBarManager; -import cyanogenmod.app.CustomTile; - -public class ColorPickerQuickSettingsTile { - private static final String TAG = ColorPickerQuickSettingsTile.class.getSimpleName(); - - public static final String ACTION_TOGGLE_STATE = - "org.cyanogenmod.designertools.action.TOGGLE_COLOR_PICKER_STATE"; - - public static final String ACTION_UNPUBLISH = - "org.cyanogenmod.designertools.action.UNPUBLISH_COLOR_PICKER_TILE"; - - public static final int TILE_ID = 5000; - - public static void publishColorPickerTile(Context context) { - publishColorPickerTile(context, OnOffTileState.STATE_OFF); - } - - public static void publishColorPickerTile(Context context, int state) { - Intent intent = new Intent(ACTION_TOGGLE_STATE); - intent.putExtra(OnOffTileState.EXTRA_STATE, state); - PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, - PendingIntent.FLAG_UPDATE_CURRENT); - int iconResId = - state == OnOffTileState.STATE_OFF ? R.drawable.ic_qs_colorpicker_off : - R.drawable.ic_qs_colorpicker_on; - CustomTile tile = new CustomTile.Builder(context) - .setOnClickIntent(pi) - .setLabel(context.getString(R.string.color_picker_qs_tile_label)) - .setIcon(iconResId) - .build(); - CMStatusBarManager.getInstance(context).publishTile(TAG, TILE_ID, tile); - PreferenceUtils.setColorPickerQsTileEnabled(context, true); - } - - public static void unpublishColorPickerTile(Context context) { - CMStatusBarManager.getInstance(context).removeTile(TAG, TILE_ID); - PreferenceUtils.setColorPickerQsTileEnabled(context, false); - Intent intent = new Intent(ColorPickerQuickSettingsTile.ACTION_UNPUBLISH); - context.sendBroadcast(intent); - } - - public static class ClickBroadcastReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - if (PreferenceUtils.getColorPickerQsTileEnabled(context, false)) { - int state = - intent.getIntExtra(OnOffTileState.EXTRA_STATE, OnOffTileState.STATE_OFF); - if (state == OnOffTileState.STATE_OFF) { - publishColorPickerTile(context, OnOffTileState.STATE_ON); - startColorPickerOrRequestPermission(context); - } else { - publishColorPickerTile(context, OnOffTileState.STATE_OFF); - PreferenceUtils.setColorPickerActive(context, false); - } - } - } - - private void startColorPickerOrRequestPermission(Context context) { - DesignerToolsApplication app = - (DesignerToolsApplication) context.getApplicationContext(); - if (app.getScreenRecordResultCode() == Activity.RESULT_OK && app.getScreenRecordResultData() != null) { - Intent newIntent = new Intent(context, ColorPickerOverlay.class); - context.startService(newIntent); - PreferenceUtils.setColorPickerActive(context, true); - } else { - Intent intent = new Intent(context, ScreenRecordRequestActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - context.startActivity(intent); - } - } - } -} diff --git a/app/src/main/java/org/cyanogenmod/designertools/qs/GridQuickSettingsTile.java b/app/src/main/java/org/cyanogenmod/designertools/qs/GridQuickSettingsTile.java deleted file mode 100644 index 9893487..0000000 --- a/app/src/main/java/org/cyanogenmod/designertools/qs/GridQuickSettingsTile.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2016 The CyanogenMod Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.cyanogenmod.designertools.qs; - -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; - -import org.cyanogenmod.designertools.R; -import org.cyanogenmod.designertools.overlays.GridOverlay; -import org.cyanogenmod.designertools.utils.PreferenceUtils; - -import cyanogenmod.app.CMStatusBarManager; -import cyanogenmod.app.CustomTile; - -public class GridQuickSettingsTile { - private static final String TAG = GridQuickSettingsTile.class.getSimpleName(); - - public static final String ACTION_TOGGLE_STATE = - "org.cyanogenmod.designertools.action.TOGGLE_GRID_STATE"; - - public static final String ACTION_UNPUBLISH = - "org.cyanogenmod.designertools.action.UNPUBLISH_GRID_TILE"; - - public static final int TILE_ID = 1000; - - public static void publishGridTile(Context context) { - publishGridTile(context, OnOffTileState.STATE_OFF); - } - - public static void publishGridTile(Context context, int state) { - Intent intent = new Intent(ACTION_TOGGLE_STATE); - intent.putExtra(OnOffTileState.EXTRA_STATE, state); - PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, - PendingIntent.FLAG_UPDATE_CURRENT); - int iconResId = state == OnOffTileState.STATE_OFF ? R.drawable.ic_qs_grid_off : - R.drawable.ic_qs_grid_on; - CustomTile tile = new CustomTile.Builder(context) - .setOnClickIntent(pi) - .setLabel(context.getString(R.string.grid_qs_tile_label)) - .setIcon(iconResId) - .build(); - CMStatusBarManager.getInstance(context).publishTile(TAG, TILE_ID, tile); - PreferenceUtils.setGridQsTileEnabled(context, true); - } - - public static void unpublishGridTile(Context context) { - CMStatusBarManager.getInstance(context).removeTile(TAG, TILE_ID); - PreferenceUtils.setGridQsTileEnabled(context, false); - Intent intent = new Intent(GridQuickSettingsTile.ACTION_UNPUBLISH); - context.sendBroadcast(intent); - } - - public static class ClickBroadcastReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - int state = intent.getIntExtra(OnOffTileState.EXTRA_STATE, OnOffTileState.STATE_OFF); - if (state == OnOffTileState.STATE_OFF) { - publishGridTile(context, OnOffTileState.STATE_ON); - Intent newIntent = new Intent(context, GridOverlay.class); - context.startService(newIntent); - PreferenceUtils.setGridOverlayActive(context, true); - } else { - publishGridTile(context, OnOffTileState.STATE_OFF); - PreferenceUtils.setGridOverlayActive(context, false); - } - } - } -} diff --git a/app/src/main/java/org/cyanogenmod/designertools/qs/MockQuickSettingsTile.java b/app/src/main/java/org/cyanogenmod/designertools/qs/MockQuickSettingsTile.java deleted file mode 100644 index 0e769be..0000000 --- a/app/src/main/java/org/cyanogenmod/designertools/qs/MockQuickSettingsTile.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2016 The CyanogenMod Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.cyanogenmod.designertools.qs; - -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; - -import org.cyanogenmod.designertools.R; -import org.cyanogenmod.designertools.overlays.MockOverlay; -import org.cyanogenmod.designertools.utils.PreferenceUtils; - -import cyanogenmod.app.CMStatusBarManager; -import cyanogenmod.app.CustomTile; - -public class MockQuickSettingsTile { - private static final String TAG = MockQuickSettingsTile.class.getSimpleName(); - - public static final String ACTION_TOGGLE_STATE = - "org.cyanogenmod.designertools.action.TOGGLE_MOCK_STATE"; - - public static final String ACTION_UNPUBLISH = - "org.cyanogenmod.designertools.action.UNPUBLISH_MOCK_TILE"; - - public static final int TILE_ID = 2000; - - public static void publishMockTile(Context context) { - publishMockTile(context, OnOffTileState.STATE_OFF); - } - - public static void publishMockTile(Context context, int state) { - Intent intent = new Intent(ACTION_TOGGLE_STATE); - intent.putExtra(OnOffTileState.EXTRA_STATE, state); - PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, - PendingIntent.FLAG_UPDATE_CURRENT); - int iconResId = state == OnOffTileState.STATE_OFF ? R.drawable.ic_qs_overlay_off : - R.drawable.ic_qs_overlay_on; - CustomTile tile = new CustomTile.Builder(context) - .setOnClickIntent(pi) - .setLabel(context.getString(R.string.mock_qs_tile_label)) - .setIcon(iconResId) - .build(); - CMStatusBarManager.getInstance(context).publishTile(TAG, TILE_ID, tile); - PreferenceUtils.setMockQsTileEnabled(context, true); - } - - public static void unpublishMockTile(Context context) { - CMStatusBarManager.getInstance(context).removeTile(TAG, TILE_ID); - PreferenceUtils.setMockQsTileEnabled(context, false); - Intent intent = new Intent(MockQuickSettingsTile.ACTION_UNPUBLISH); - context.sendBroadcast(intent); - } - - public static class ClickBroadcastReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - int state = intent.getIntExtra(OnOffTileState.EXTRA_STATE, OnOffTileState.STATE_OFF); - if (state == OnOffTileState.STATE_OFF) { - publishMockTile(context, OnOffTileState.STATE_ON); - Intent newIntent = new Intent(context, MockOverlay.class); - context.startService(newIntent); - PreferenceUtils.setMockOverlayActive(context, true); - } else { - publishMockTile(context, OnOffTileState.STATE_OFF); - PreferenceUtils.setMockOverlayActive(context, false); - } - } - } -} diff --git a/app/src/main/java/org/cyanogenmod/designertools/qs/OnOffTileState.java b/app/src/main/java/org/cyanogenmod/designertools/qs/OnOffTileState.java deleted file mode 100644 index 52d4277..0000000 --- a/app/src/main/java/org/cyanogenmod/designertools/qs/OnOffTileState.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2016 The CyanogenMod Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.cyanogenmod.designertools.qs; - -public class OnOffTileState { - public static final String EXTRA_STATE = "state"; - - public static final int STATE_OFF = 0; - public static final int STATE_ON = 1; -} diff --git a/app/src/main/java/org/cyanogenmod/designertools/receiver/BootReceiver.java b/app/src/main/java/org/cyanogenmod/designertools/receiver/BootReceiver.java index 3ef58d1..7e30725 100644 --- a/app/src/main/java/org/cyanogenmod/designertools/receiver/BootReceiver.java +++ b/app/src/main/java/org/cyanogenmod/designertools/receiver/BootReceiver.java @@ -19,11 +19,7 @@ import android.content.Context; import android.content.Intent; -import org.cyanogenmod.designertools.qs.ColorPickerQuickSettingsTile; -import org.cyanogenmod.designertools.qs.GridQuickSettingsTile; -import org.cyanogenmod.designertools.qs.MockQuickSettingsTile; import org.cyanogenmod.designertools.service.ScreenshotListenerService; -import org.cyanogenmod.designertools.utils.LaunchUtils; import org.cyanogenmod.designertools.utils.PreferenceUtils; public class BootReceiver extends BroadcastReceiver { @@ -32,20 +28,16 @@ public BootReceiver() { @Override public void onReceive(Context context, Intent intent) { - final boolean isCm = LaunchUtils.isCyanogenMod(context); - if (PreferenceUtils.getGridQsTileEnabled(context, false)) { - PreferenceUtils.setGridOverlayActive(context, false); - if (isCm) GridQuickSettingsTile.publishGridTile(context); + if (PreferenceUtils.GridPreferences.getGridQsTileEnabled(context, false)) { + PreferenceUtils.GridPreferences.setGridOverlayActive(context, false); } - if (PreferenceUtils.getMockQsTileEnabled(context, false)) { - PreferenceUtils.setMockOverlayActive(context, false); - if (isCm) MockQuickSettingsTile.publishMockTile(context); + if (PreferenceUtils.MockPreferences.getMockQsTileEnabled(context, false)) { + PreferenceUtils.MockPreferences.setMockOverlayActive(context, false); } - if (PreferenceUtils.getColorPickerQsTileEnabled(context, false)) { - PreferenceUtils.setColorPickerActive(context, false); - if (isCm) ColorPickerQuickSettingsTile.publishColorPickerTile(context); + if (PreferenceUtils.ColorPickerPreferences.getColorPickerQsTileEnabled(context, false)) { + PreferenceUtils.ColorPickerPreferences.setColorPickerActive(context, false); } - if (PreferenceUtils.getScreenshotInfoEnabled(context, false)) { + if (PreferenceUtils.ScreenshotPreferences.getScreenshotInfoEnabled(context, false)) { Intent newIntent = new Intent(context, ScreenshotListenerService.class); context.startService(newIntent); } diff --git a/app/src/main/java/org/cyanogenmod/designertools/service/ScreenshotInfoService.java b/app/src/main/java/org/cyanogenmod/designertools/service/ScreenshotInfoService.java index 92d689d..af336b9 100644 --- a/app/src/main/java/org/cyanogenmod/designertools/service/ScreenshotInfoService.java +++ b/app/src/main/java/org/cyanogenmod/designertools/service/ScreenshotInfoService.java @@ -16,13 +16,16 @@ package org.cyanogenmod.designertools.service; import android.app.IntentService; +import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Point; +import android.net.Uri; import android.os.Build; +import android.os.ParcelFileDescriptor; import android.util.DisplayMetrics; import android.util.Log; import android.view.Display; @@ -35,11 +38,10 @@ import org.cyanogenmod.designertools.utils.LayoutRenderUtils; import java.io.BufferedReader; -import java.io.File; -import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; +import java.io.InputStream; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.text.DateFormat; @@ -51,7 +53,7 @@ public class ScreenshotInfoService extends IntentService { private static final String TAG = ScreenshotInfoService.class.getSimpleName(); private static final String FILENAME_PROC_VERSION = "/proc/version"; - public static final String EXTRA_PATH = "path"; + public static final String EXTRA_URI = "uri"; public ScreenshotInfoService() { super("ScreenshotInfoService"); @@ -59,40 +61,42 @@ public ScreenshotInfoService() { @Override protected void onHandleIntent(Intent intent) { - if (intent.hasExtra(EXTRA_PATH)) { - File screenshot = new File(intent.getStringExtra(EXTRA_PATH)); - Bitmap paneBmp = getInfoPane(screenshot); - Bitmap screenshotBmp = BitmapFactory.decodeFile(screenshot.getAbsolutePath()); - try { - saveModifiedScreenshot(screenshotBmp, paneBmp, screenshot.getAbsolutePath()); - } catch (FileNotFoundException e) { - e.printStackTrace(); + if (intent != null && intent.hasExtra((EXTRA_URI))) { + Uri uri = intent.getParcelableExtra(EXTRA_URI); + ContentResolver resolver = getApplicationContext() + .getContentResolver(); + try (InputStream stream = resolver.openInputStream(uri)) { + Bitmap paneBmp = getInfoPane(); + Bitmap screenshotBmp = BitmapFactory.decodeStream(stream); + saveModifiedScreenshot(screenshotBmp, paneBmp, uri); + } catch (IOException e) { + Log.e(TAG, "Failed to store screenshot info", e); } } } - private Bitmap getInfoPane(File screenshot) { - Date date = new Date(screenshot.lastModified()); + private Bitmap getInfoPane() { + Date date = new Date(); String dateTime = String.format("%s at %s", DateFormat.getDateInstance().format(date), DateFormat.getTimeInstance().format(date)); String device = Build.MODEL; String codeName = Build.DEVICE; - String build = getCmVersionString(this); + String build = Build.ID; String density = getDensityString(); String kernelVersion = getFormattedKernelVersion(); View pane = View.inflate(this, R.layout.screenshot_info, null); - TextView tv = (TextView) pane.findViewById(R.id.date_time_info); + TextView tv = pane.findViewById(R.id.date_time_info); tv.setText(dateTime); - tv = (TextView) pane.findViewById(R.id.device_name); + tv = pane.findViewById(R.id.device_name); tv.setText(device); - tv = (TextView) pane.findViewById(R.id.code_name); + tv = pane.findViewById(R.id.code_name); tv.setText(codeName); - tv = (TextView) pane.findViewById(R.id.build); + tv = pane.findViewById(R.id.build); tv.setText(build); - tv = (TextView) pane.findViewById(R.id.density); + tv = pane.findViewById(R.id.density); tv.setText(density); - tv = (TextView) pane.findViewById(R.id.kernel); + tv = pane.findViewById(R.id.kernel); tv.setText(kernelVersion); return LayoutRenderUtils.renderViewToBitmap(pane); @@ -158,7 +162,7 @@ public static String getFormattedKernelVersion() { "IO Exception when getting kernel version for Device Info screen", e); - return "Unavailable"; + return ""; } } @@ -179,56 +183,42 @@ public static String formatKernelVersion(String rawKernelVersion) { Matcher m = Pattern.compile(PROC_VERSION_REGEX).matcher(rawKernelVersion); if (!m.matches()) { Log.e(TAG, "Regex did not match on /proc/version: " + rawKernelVersion); - return "Unavailable"; + return ""; } else if (m.groupCount() < 4) { Log.e(TAG, "Regex match on /proc/version only returned " + m.groupCount() + " groups"); - return "Unavailable"; + return ""; } return m.group(1) + "\n" + // 3.0.31-g6fb96c9 m.group(2) + " " + m.group(3) + "\n" + // x@y.com #1 m.group(4); // Thu Jun 28 11:02:39 PDT 2012 } - private void saveModifiedScreenshot(Bitmap screenshot, Bitmap infoPane, String filePath) - throws FileNotFoundException { + private void saveModifiedScreenshot(Bitmap screenshot, Bitmap infoPane, Uri uri) + throws IOException { + ContentResolver resolver = getApplicationContext().getContentResolver(); + ParcelFileDescriptor pfd = resolver.openFileDescriptor(uri, "w"); + + WindowManager wm = getSystemService(WindowManager.class); + Point size = new Point(); + wm.getDefaultDisplay().getRealSize(size); + if (screenshot.getWidth() != size.x || screenshot.getHeight() != size.y) { + Log.d(TAG, "Not adding info, screenshot too large"); + return; + } + Bitmap newBmp = Bitmap.createBitmap(screenshot.getWidth() + infoPane.getWidth(), screenshot.getHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(newBmp); canvas.drawColor(getColor(R.color.screenshot_info_background_color)); canvas.drawBitmap(screenshot, 0, 0, null); - screenshot.recycle(); canvas.drawBitmap(infoPane, screenshot.getWidth(), 0, null); + screenshot.recycle(); infoPane.recycle(); - newBmp.compress(Bitmap.CompressFormat.PNG, 100, new FileOutputStream(filePath)); - newBmp.recycle(); - } - - private String getCmVersionString(Context context) { - if (LaunchUtils.isCyanogenMod(context)) { - ClassLoader cl = context.getClassLoader(); - Class SystemProperties = null; - try { - SystemProperties = cl.loadClass("android.os.SystemProperties"); - //Parameters Types - Class[] paramTypes = new Class[1]; - paramTypes[0] = String.class; - - Method get = SystemProperties.getMethod("get", paramTypes); - - //Parameters - Object[] params = new Object[1]; - params[0] = "ro.cm.version"; - - return (String) get.invoke(SystemProperties, params); - } catch (ClassNotFoundException | - NoSuchMethodException | - IllegalAccessException | - InvocationTargetException e) { - /* don't care, will fallback to Build.ID */ - } + if (pfd != null) { + newBmp.compress(Bitmap.CompressFormat.PNG, 100, new FileOutputStream(pfd.getFileDescriptor())); + pfd.close(); } - - return Build.ID; + newBmp.recycle(); } } diff --git a/app/src/main/java/org/cyanogenmod/designertools/service/ScreenshotListenerService.java b/app/src/main/java/org/cyanogenmod/designertools/service/ScreenshotListenerService.java index 81d1be8..7c236d5 100644 --- a/app/src/main/java/org/cyanogenmod/designertools/service/ScreenshotListenerService.java +++ b/app/src/main/java/org/cyanogenmod/designertools/service/ScreenshotListenerService.java @@ -30,12 +30,13 @@ import org.cyanogenmod.designertools.R; import org.cyanogenmod.designertools.ui.DesignerToolsActivity; +import org.cyanogenmod.designertools.utils.NotificationUtils; import org.cyanogenmod.designertools.utils.PreferenceUtils; - -import java.io.File; +import org.cyanogenmod.designertools.utils.PreferenceUtils.ScreenshotPreferences; public class ScreenshotListenerService extends Service implements SharedPreferences.OnSharedPreferenceChangeListener { + private static final String CHANNEL_ID = "DesignerTools.ScreenshotListenerService"; private ScreenShotObserver mScreenshotObserver; @@ -73,8 +74,8 @@ public void onDestroy() { @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { - if (PreferenceUtils.KEY_SCREENSHOT_INFO.equals(key)) { - boolean enabled = PreferenceUtils.getScreenshotInfoEnabled(this, false); + if (ScreenshotPreferences.KEY_SCREENSHOT_INFO.equals(key)) { + boolean enabled = ScreenshotPreferences.getScreenshotInfoEnabled(this, false); if (!enabled) { stopSelf(); } @@ -82,17 +83,20 @@ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, Strin } private Notification getPersistentNotification() { - PendingIntent pi = PendingIntent.getActivity(this, 0, - new Intent(this, DesignerToolsActivity.class), 0); - Notification.Builder builder = new Notification.Builder(this); - String text = getString(R.string.notif_content_screenshot_info); - builder.setPriority(Notification.PRIORITY_MIN) - .setSmallIcon(R.drawable.ic_qs_screenshotinfo_on) - .setContentTitle(getString(R.string.screenshot_qs_tile_label)) - .setContentText(text) - .setStyle(new Notification.BigTextStyle().bigText(text)) - .setContentIntent(pi); - return builder.build(); + final PendingIntent pi = PendingIntent.getActivity( + this, + 0, + new Intent(this, DesignerToolsActivity.class), + PendingIntent.FLAG_IMMUTABLE); + final String contentText = getString(R.string.notif_content_screenshot_info); + + return NotificationUtils.createForegroundServiceNotification( + this, + CHANNEL_ID, + R.drawable.ic_qs_screenshotinfo_on, + getString(R.string.screenshot_qs_tile_label), + contentText, + pi); } private class ScreenShotObserver extends ContentObserver { @@ -101,14 +105,15 @@ private class ScreenShotObserver extends ContentObserver { MediaStore.Images.Media.EXTERNAL_CONTENT_URI.toString(); private final String[] PROJECTION = new String[] { MediaStore.Images.Media.DISPLAY_NAME, MediaStore.Images.Media.DATA, - MediaStore.Images.Media.DATE_ADDED + MediaStore.Images.Media.DATE_TAKEN }; private static final String SORT_ORDER = MediaStore.Images.Media.DATE_ADDED + " DESC"; - private static final long DEFAULT_DETECT_WINDOW_SECONDS = 10; + private static final long ADD_INFO_DELAY_MS = 1000; + private String mLastProcessedImage = null; private Handler mHandler; - public ScreenShotObserver(Handler handler) { + ScreenShotObserver(Handler handler) { super(handler); mHandler = handler; } @@ -116,38 +121,29 @@ public ScreenShotObserver(Handler handler) { @Override public void onChange(boolean selfChange, Uri uri) { if (uri.toString().startsWith(EXTERNAL_CONTENT_URI_MATCHER)) { - Cursor cursor = null; - try { - cursor = getContentResolver().query(uri, PROJECTION, null, null, - SORT_ORDER); + try (Cursor cursor = getContentResolver().query(uri, PROJECTION, null, null, + SORT_ORDER)) { if (cursor != null && cursor.moveToFirst()) { String path = cursor.getString( - cursor.getColumnIndex(MediaStore.Images.Media.DATA)); - long dateAdded = cursor.getLong(cursor.getColumnIndex( - MediaStore.Images.Media.DATE_ADDED)); - long currentTime = System.currentTimeMillis() / 1000; - Log.d(TAG, "path: " + path + ", dateAdded: " + dateAdded + - ", currentTime: " + currentTime); - if (path.toLowerCase().contains("screenshot") && - Math.abs(currentTime - dateAdded) <= - DEFAULT_DETECT_WINDOW_SECONDS) { - Intent intent = + cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)); + if (path.substring(path.lastIndexOf("/") + 1).toLowerCase().startsWith("screenshot") && + !path.equals(mLastProcessedImage)) { + mLastProcessedImage = path; + final Intent intent = new Intent(ScreenshotListenerService.this, ScreenshotInfoService.class); - intent.putExtra(ScreenshotInfoService.EXTRA_PATH, path); - final File file = new File(path); - while (!file.exists()) { - Thread.sleep(100); - } - startService(intent); + intent.putExtra(ScreenshotInfoService.EXTRA_URI, uri); + // give time for screenshot to be fully written to storage + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + startService(intent); + } + }, ADD_INFO_DELAY_MS); } } } catch (Exception e) { - Log.d(TAG, "open cursor fail"); - } finally { - if (cursor != null) { - cursor.close(); - } + Log.e(TAG, "open cursor fail", e); } } super.onChange(selfChange, uri); diff --git a/app/src/main/java/org/cyanogenmod/designertools/service/qs/ColorPickerTileService.java b/app/src/main/java/org/cyanogenmod/designertools/service/qs/ColorPickerTileService.java index d77109c..c304dac 100644 --- a/app/src/main/java/org/cyanogenmod/designertools/service/qs/ColorPickerTileService.java +++ b/app/src/main/java/org/cyanogenmod/designertools/service/qs/ColorPickerTileService.java @@ -15,21 +15,15 @@ */ package org.cyanogenmod.designertools.service.qs; -import android.annotation.TargetApi; import android.graphics.drawable.Icon; -import android.os.Build; import android.service.quicksettings.Tile; import android.service.quicksettings.TileService; -import android.util.Log; import org.cyanogenmod.designertools.DesignerToolsApplication; import org.cyanogenmod.designertools.R; import org.cyanogenmod.designertools.utils.LaunchUtils; -@TargetApi(Build.VERSION_CODES.N) public class ColorPickerTileService extends TileService { - private static final String TAG = ColorPickerTileService.class.getSimpleName(); - public ColorPickerTileService() { super(); } @@ -37,6 +31,8 @@ public ColorPickerTileService() { @Override public void onTileAdded() { super.onTileAdded(); + final Tile tile = getQsTile(); + tile.setIcon(Icon.createWithResource(this, R.drawable.ic_qs_colorpicker_on)); } @Override @@ -60,18 +56,16 @@ public void onClick() { super.onClick(); boolean isOn = ((DesignerToolsApplication) getApplicationContext()).getColorPickerOn(); if (isOn) { - LaunchUtils.cancelColorPickerOrUnpublishTile(this); + LaunchUtils.cancelColorPickerOverlay(this); } else { - LaunchUtils.lauchColorPickerOrPublishTile(this, 0); + LaunchUtils.launchColorPickerOverlay(this); } updateTile(!isOn); } private void updateTile(boolean isOn) { final Tile tile = getQsTile(); - tile.setIcon(Icon.createWithResource(this, isOn - ? R.drawable.ic_qs_colorpicker_on - : R.drawable.ic_qs_colorpicker_off)); + tile.setState(isOn ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE); tile.updateTile(); } } diff --git a/app/src/main/java/org/cyanogenmod/designertools/service/qs/GridOverlayTileService.java b/app/src/main/java/org/cyanogenmod/designertools/service/qs/GridOverlayTileService.java index 18a1950..9016b0d 100644 --- a/app/src/main/java/org/cyanogenmod/designertools/service/qs/GridOverlayTileService.java +++ b/app/src/main/java/org/cyanogenmod/designertools/service/qs/GridOverlayTileService.java @@ -15,21 +15,15 @@ */ package org.cyanogenmod.designertools.service.qs; -import android.annotation.TargetApi; import android.graphics.drawable.Icon; -import android.os.Build; import android.service.quicksettings.Tile; import android.service.quicksettings.TileService; -import android.util.Log; import org.cyanogenmod.designertools.DesignerToolsApplication; import org.cyanogenmod.designertools.R; import org.cyanogenmod.designertools.utils.LaunchUtils; -@TargetApi(Build.VERSION_CODES.N) public class GridOverlayTileService extends TileService { - private static final String TAG = GridOverlayTileService.class.getSimpleName(); - public GridOverlayTileService() { super(); } @@ -37,6 +31,8 @@ public GridOverlayTileService() { @Override public void onTileAdded() { super.onTileAdded(); + final Tile tile = getQsTile(); + tile.setIcon(Icon.createWithResource(this, R.drawable.ic_qs_grid_on)); } @Override @@ -61,18 +57,16 @@ public void onClick() { super.onClick(); boolean isOn = ((DesignerToolsApplication) getApplicationContext()).getGridOverlayOn(); if (isOn) { - LaunchUtils.cancelGridOverlayOrUnpublishTile(this); + LaunchUtils.cancelGridOverlay(this); } else { - LaunchUtils.lauchGridOverlayOrPublishTile(this, 0); + LaunchUtils.launchGridOverlay(this); } updateTile(!isOn); } private void updateTile(boolean isOn) { final Tile tile = getQsTile(); - tile.setIcon(Icon.createWithResource(this, isOn - ? R.drawable.ic_qs_grid_on - : R.drawable.ic_qs_grid_off)); + tile.setState(isOn ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE); tile.updateTile(); } } diff --git a/app/src/main/java/org/cyanogenmod/designertools/service/qs/MockOverlayTileService.java b/app/src/main/java/org/cyanogenmod/designertools/service/qs/MockOverlayTileService.java index c9d60a5..3500dfc 100644 --- a/app/src/main/java/org/cyanogenmod/designertools/service/qs/MockOverlayTileService.java +++ b/app/src/main/java/org/cyanogenmod/designertools/service/qs/MockOverlayTileService.java @@ -15,21 +15,15 @@ */ package org.cyanogenmod.designertools.service.qs; -import android.annotation.TargetApi; import android.graphics.drawable.Icon; -import android.os.Build; import android.service.quicksettings.Tile; import android.service.quicksettings.TileService; -import android.util.Log; import org.cyanogenmod.designertools.DesignerToolsApplication; import org.cyanogenmod.designertools.R; import org.cyanogenmod.designertools.utils.LaunchUtils; -@TargetApi(Build.VERSION_CODES.N) public class MockOverlayTileService extends TileService { - private static final String TAG = MockOverlayTileService.class.getSimpleName(); - public MockOverlayTileService() { super(); } @@ -37,6 +31,8 @@ public MockOverlayTileService() { @Override public void onTileAdded() { super.onTileAdded(); + final Tile tile = getQsTile(); + tile.setIcon(Icon.createWithResource(this, R.drawable.ic_qs_overlay_on)); } @Override @@ -60,18 +56,16 @@ public void onClick() { super.onClick(); boolean isOn = ((DesignerToolsApplication) getApplicationContext()).getMockOverlayOn(); if (isOn) { - LaunchUtils.cancelMockOverlayOrUnpublishTile(this); + LaunchUtils.cancelMockOverlay(this); } else { - LaunchUtils.lauchMockPverlayOrPublishTile(this, 0); + LaunchUtils.launchMockOverlay(this); } updateTile(!isOn); } private void updateTile(boolean isOn) { final Tile tile = getQsTile(); - tile.setIcon(Icon.createWithResource(this, isOn - ? R.drawable.ic_qs_overlay_on - : R.drawable.ic_qs_overlay_off)); + tile.setState(isOn ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE); tile.updateTile(); } } diff --git a/app/src/main/java/org/cyanogenmod/designertools/ui/AppShortcutsActivity.java b/app/src/main/java/org/cyanogenmod/designertools/ui/AppShortcutsActivity.java new file mode 100644 index 0000000..a89d4c4 --- /dev/null +++ b/app/src/main/java/org/cyanogenmod/designertools/ui/AppShortcutsActivity.java @@ -0,0 +1,64 @@ +package org.cyanogenmod.designertools.ui; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; + +import org.cyanogenmod.designertools.DesignerToolsApplication; +import org.cyanogenmod.designertools.utils.LaunchUtils; + +/** + * Created by clark on 12/19/16. + */ + +public class AppShortcutsActivity extends Activity { + private static final String ACTION_SHOW_GRID_OVERLAY = + "com.scheffsblend.designertools.action.SHOW_GRID_OVERLAY"; + private static final String ACTION_SHOW_MOCK_OVERLAY = + "com.scheffsblend.designertools.action.SHOW_MOCK_OVERLAY"; + private static final String ACTION_SHOW_COLOR_PICKER_OVERLAY = + "com.scheffsblend.designertools.action.SHOW_COLOR_PICKER_OVERLAY"; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + final Intent intent = getIntent(); + final String action = intent.getAction(); + if (ACTION_SHOW_GRID_OVERLAY.equals(action)) { + toggleGridOverlay(); + } else if (ACTION_SHOW_MOCK_OVERLAY.equals(action)) { + toggleMockOverlay(); + } else if (ACTION_SHOW_COLOR_PICKER_OVERLAY.equals(action)) { + toggleColorPickerOverlay(); + } + finish(); + } + + private DesignerToolsApplication getDesignerToolsApplication() { + return (DesignerToolsApplication) getApplication(); + } + + private void toggleGridOverlay() { + if (getDesignerToolsApplication().getGridOverlayOn()) { + LaunchUtils.cancelGridOverlay(this); + } else { + LaunchUtils.launchGridOverlay(this); + } + } + + private void toggleMockOverlay() { + if (getDesignerToolsApplication().getMockOverlayOn()) { + LaunchUtils.cancelMockOverlay(this); + } else { + LaunchUtils.launchMockOverlay(this); + } + } + + private void toggleColorPickerOverlay() { + if (getDesignerToolsApplication().getColorPickerOn()) { + LaunchUtils.cancelColorPickerOverlay(this); + } else { + LaunchUtils.launchColorPickerOverlay(this); + } + } +} diff --git a/app/src/main/java/org/cyanogenmod/designertools/ui/ColorPickerCardFragment.java b/app/src/main/java/org/cyanogenmod/designertools/ui/ColorPickerCardFragment.java index 6dc8f8f..2fa6db8 100644 --- a/app/src/main/java/org/cyanogenmod/designertools/ui/ColorPickerCardFragment.java +++ b/app/src/main/java/org/cyanogenmod/designertools/ui/ColorPickerCardFragment.java @@ -25,9 +25,7 @@ import android.widget.CompoundButton; import org.cyanogenmod.designertools.R; -import org.cyanogenmod.designertools.qs.OnOffTileState; import org.cyanogenmod.designertools.utils.LaunchUtils; -import org.cyanogenmod.designertools.utils.PreferenceUtils; public class ColorPickerCardFragment extends DesignerToolCardFragment { private static final int REQUEST_OVERLAY_PERMISSION = 0x42; @@ -40,7 +38,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, setTitleSummary(R.string.header_summary_color_picker); setIconResource(R.drawable.ic_qs_colorpicker_on); base.setBackgroundTintList(ColorStateList.valueOf( - getResources().getColor(R.color.colorColorPickerCardTint))); + getActivity().getColor(R.color.colorColorPickerCardTint))); return base; } @@ -78,14 +76,14 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); } + private void isEnabled() { + } + private void enableFeature(boolean enable) { if (enable) { - LaunchUtils.lauchColorPickerOrPublishTile(getContext(), - PreferenceUtils.getColorPickerActive(getContext(), false) - ? OnOffTileState.STATE_ON - : OnOffTileState.STATE_OFF); + LaunchUtils.launchColorPickerOverlay(getContext()); } else { - LaunchUtils.cancelColorPickerOrUnpublishTile(getContext()); + LaunchUtils.cancelColorPickerOverlay(getContext()); } } } diff --git a/app/src/main/java/org/cyanogenmod/designertools/ui/CreditsActivity.java b/app/src/main/java/org/cyanogenmod/designertools/ui/CreditsActivity.java index e917fef..c26cd4e 100644 --- a/app/src/main/java/org/cyanogenmod/designertools/ui/CreditsActivity.java +++ b/app/src/main/java/org/cyanogenmod/designertools/ui/CreditsActivity.java @@ -20,7 +20,7 @@ import android.animation.ObjectAnimator; import android.app.Activity; import android.os.Bundle; -import android.support.v4.view.animation.FastOutSlowInInterpolator; +import androidx.interpolator.view.animation.FastOutSlowInInterpolator; import android.view.View; import android.view.ViewAnimationUtils; import android.view.ViewTreeObserver; @@ -36,8 +36,6 @@ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); overridePendingTransition(0, 0); setContentView(R.layout.activity_credits); - if (savedInstanceState == null) { - } } private void circularRevealActivity(View v) { diff --git a/app/src/main/java/org/cyanogenmod/designertools/ui/DesignerToolCardFragment.java b/app/src/main/java/org/cyanogenmod/designertools/ui/DesignerToolCardFragment.java index df4ac35..bd60d2d 100644 --- a/app/src/main/java/org/cyanogenmod/designertools/ui/DesignerToolCardFragment.java +++ b/app/src/main/java/org/cyanogenmod/designertools/ui/DesignerToolCardFragment.java @@ -49,11 +49,11 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, inflater.cloneInContext(ctx); View v = inflater.inflate(R.layout.card_layout, container, true); mParentLayout = v.findViewById(R.id.parent_layout); - mIcon = (ImageView) v.findViewById(R.id.header_icon); - mHeaderTitle = (TextView) v.findViewById(R.id.header_title); - mHeaderSummary = (TextView) v.findViewById(R.id.header_summary); - mEnabledSwitch = (Switch) v.findViewById(R.id.enable_switch); - mCardContent = (FrameLayout) v.findViewById(R.id.card_content); + mIcon = v.findViewById(R.id.header_icon); + mHeaderTitle = v.findViewById(R.id.header_title); + mHeaderSummary = v.findViewById(R.id.header_summary); + mEnabledSwitch = v.findViewById(R.id.enable_switch); + mCardContent = v.findViewById(R.id.card_content); mEnabledSwitch.setOnCheckedChangeListener(this); diff --git a/app/src/main/java/org/cyanogenmod/designertools/ui/DesignerToolsActivity.java b/app/src/main/java/org/cyanogenmod/designertools/ui/DesignerToolsActivity.java index b4e8855..5fcfad5 100644 --- a/app/src/main/java/org/cyanogenmod/designertools/ui/DesignerToolsActivity.java +++ b/app/src/main/java/org/cyanogenmod/designertools/ui/DesignerToolsActivity.java @@ -30,10 +30,6 @@ public class DesignerToolsActivity extends Activity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_designer_tools); - if (!LaunchUtils.isCyanogenMod(this)) { - TextView tv = (TextView) findViewById(R.id.qs_tiles_section); - tv.setText(R.string.overlays_section_text); - } View headerGlyph = findViewById(R.id.header_glyph); if (headerGlyph != null) { headerGlyph.setOnClickListener(mGlyphClickListener); diff --git a/app/src/main/java/org/cyanogenmod/designertools/ui/DualColorPickerDialog.java b/app/src/main/java/org/cyanogenmod/designertools/ui/DualColorPickerDialog.java index b738423..e17bf6b 100644 --- a/app/src/main/java/org/cyanogenmod/designertools/ui/DualColorPickerDialog.java +++ b/app/src/main/java/org/cyanogenmod/designertools/ui/DualColorPickerDialog.java @@ -20,8 +20,8 @@ import android.app.DialogFragment; import android.content.DialogInterface; import android.os.Bundle; -import android.support.v4.view.PagerAdapter; -import android.support.v4.view.ViewPager; +import androidx.viewpager.widget.PagerAdapter; +import androidx.viewpager.widget.ViewPager; import android.view.ContextThemeWrapper; import android.view.MotionEvent; import android.view.View; @@ -29,7 +29,7 @@ import org.cyanogenmod.designertools.R; import org.cyanogenmod.designertools.utils.ColorUtils; -import org.cyanogenmod.designertools.utils.PreferenceUtils; +import org.cyanogenmod.designertools.utils.PreferenceUtils.GridPreferences; import com.larswerkman.lobsterpicker.LobsterPicker; import com.larswerkman.lobsterpicker.sliders.LobsterOpacitySlider; import com.viewpagerindicator.CirclePageIndicator; @@ -46,11 +46,11 @@ public Dialog onCreateDialog(Bundle savedInstanceState) { initColorPickerViews(); - mViewPager = (ViewPager) v.findViewById(R.id.view_pager); + mViewPager = v.findViewById(R.id.view_pager); mAdapter = new ColorPickerPagerAdapter(); mViewPager.setAdapter(mAdapter); - mPageIndicator = (CirclePageIndicator) v.findViewById(R.id.view_pager_indicator); + mPageIndicator = v.findViewById(R.id.view_pager_indicator); mPageIndicator.setViewPager(mViewPager); mPageIndicator.setFillColor(getContext().getColor(R.color.colorGridOverlayCardTint)); @@ -113,9 +113,9 @@ public boolean onTouch(View v, MotionEvent event) { public void onClick(DialogInterface dialog, int which) { switch (which) { case AlertDialog.BUTTON_POSITIVE: - PreferenceUtils.setGridLineColor(getContext(), + GridPreferences.setGridLineColor(getContext(), mColorPickerViews[0].picker.getColor()); - PreferenceUtils.setKeylineColor(getContext(), + GridPreferences.setKeylineColor(getContext(), mColorPickerViews[1].picker.getColor()); break; case AlertDialog.BUTTON_NEGATIVE: diff --git a/app/src/main/java/org/cyanogenmod/designertools/ui/GridOverlayCardFragment.java b/app/src/main/java/org/cyanogenmod/designertools/ui/GridOverlayCardFragment.java index a7ed36c..8a9718b 100644 --- a/app/src/main/java/org/cyanogenmod/designertools/ui/GridOverlayCardFragment.java +++ b/app/src/main/java/org/cyanogenmod/designertools/ui/GridOverlayCardFragment.java @@ -32,10 +32,10 @@ import org.cyanogenmod.designertools.R; -import org.cyanogenmod.designertools.qs.OnOffTileState; import org.cyanogenmod.designertools.utils.ColorUtils; import org.cyanogenmod.designertools.utils.LaunchUtils; import org.cyanogenmod.designertools.utils.PreferenceUtils; +import org.cyanogenmod.designertools.utils.PreferenceUtils.GridPreferences; import org.cyanogenmod.designertools.widget.DualColorPicker; import org.cyanogenmod.designertools.widget.GridPreview; @@ -61,23 +61,23 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, context.getColor(R.color.colorGridOverlayCardTint))); View v = inflater.inflate(R.layout.grid_overlay_content, mCardContent, true); - mIncludeKeylines = (CheckBox) v.findViewById(R.id.include_keylines); - mIncudeCustomGrid = (CheckBox) v.findViewById(R.id.include_custom_grid_size); - mColumnSizer = (SeekBar) v.findViewById(R.id.column_sizer); - mColumnSizer.setProgress((PreferenceUtils.getGridColumnSize(getContext(), 8) - 4) / 2); - mRowSizer = (SeekBar) v.findViewById(R.id.row_sizer); - mRowSizer.setProgress((PreferenceUtils.getGridRowSize(getContext(), 8) - 4) / 2); - mGridPreview = (GridPreview) v.findViewById(R.id.grid_preview); - mGridPreview.setColumnSize(PreferenceUtils.getGridColumnSize(getContext(), 8)); - mGridPreview.setRowSize(PreferenceUtils.getGridRowSize(getContext(), 8)); + mIncludeKeylines = v.findViewById(R.id.include_keylines); + mIncudeCustomGrid = v.findViewById(R.id.include_custom_grid_size); + mColumnSizer = v.findViewById(R.id.column_sizer); + mColumnSizer.setProgress((GridPreferences.getGridColumnSize(getContext(), 8) - 4) / 2); + mRowSizer = v.findViewById(R.id.row_sizer); + mRowSizer.setProgress((GridPreferences.getGridRowSize(getContext(), 8) - 4) / 2); + mGridPreview = v.findViewById(R.id.grid_preview); + mGridPreview.setColumnSize(GridPreferences.getGridColumnSize(getContext(), 8)); + mGridPreview.setRowSize(GridPreferences.getGridRowSize(getContext(), 8)); mColumnSizer.setOnSeekBarChangeListener(mSeekBarChangeListener); mRowSizer.setOnSeekBarChangeListener(mSeekBarChangeListener); - mIncludeKeylines.setChecked(PreferenceUtils.getShowKeylines(context, false)); + mIncludeKeylines.setChecked(GridPreferences.getShowKeylines(context, false)); mIncludeKeylines.setOnCheckedChangeListener(mCheckChangedListener); - setIncludeCustomGridLines(PreferenceUtils.getUseCustomGridSize(context, false)); + setIncludeCustomGridLines(GridPreferences.getUseCustomGridSize(context, false)); mIncudeCustomGrid.setOnCheckedChangeListener(mCheckChangedListener); mRowSizer.setOnTouchListener(new View.OnTouchListener() { @@ -96,7 +96,7 @@ public boolean onTouch(View v, MotionEvent event) { } }); - mDualColorPicker = (DualColorPicker) v.findViewById(R.id.color_picker); + mDualColorPicker = v.findViewById(R.id.color_picker); mDualColorPicker.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -131,14 +131,10 @@ protected int getCardStyleResourceId() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - if (isChecked == getApplicationContext().getGridOverlayOn()) return; if (isChecked) { - LaunchUtils.lauchGridOverlayOrPublishTile(getContext(), - PreferenceUtils.getGridOverlayActive(getContext(), false) - ? OnOffTileState.STATE_ON - : OnOffTileState.STATE_OFF); + LaunchUtils.launchGridOverlay(getContext()); } else { - LaunchUtils.cancelGridOverlayOrUnpublishTile(getContext()); + LaunchUtils.cancelGridOverlay(getContext()); } } @@ -153,12 +149,12 @@ private void setIncludeCustomGridLines(boolean include) { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (buttonView == mIncludeKeylines) { - PreferenceUtils.setShowKeylines(getContext(), isChecked); + GridPreferences.setShowKeylines(getContext(), isChecked); } else if (buttonView == mIncudeCustomGrid){ - PreferenceUtils.setUseCustomGridSize(getContext(), isChecked); + GridPreferences.setUseCustomGridSize(getContext(), isChecked); if (isChecked) { - PreferenceUtils.setGridColumnSize(getContext(), mGridPreview.getColumnSize()); - PreferenceUtils.setGridRowSize(getContext(), mGridPreview.getRowSize()); + GridPreferences.setGridColumnSize(getContext(), mGridPreview.getColumnSize()); + GridPreferences.setGridRowSize(getContext(), mGridPreview.getRowSize()); } mColumnSizer.setEnabled(isChecked); mRowSizer.setEnabled(isChecked); @@ -172,10 +168,10 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { int size = 4 + progress * 2; if (seekBar == mColumnSizer) { mGridPreview.setColumnSize(size); - PreferenceUtils.setGridColumnSize(getContext(), size); + GridPreferences.setGridColumnSize(getContext(), size); } else if (seekBar == mRowSizer) { mGridPreview.setRowSize(size); - PreferenceUtils.setGridRowSize(getContext(), size); + GridPreferences.setGridRowSize(getContext(), size); } } @@ -188,17 +184,15 @@ public void onStopTrackingTouch(SeekBar seekBar) {} @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { - if (PreferenceUtils.KEY_GRID_LINE_COLOR.equals(key)) { + if (GridPreferences.KEY_GRID_LINE_COLOR.equals(key)) { mDualColorPicker.setPrimaryColor(ColorUtils.getGridLineColor(getContext())); - } else if(PreferenceUtils.KEY_KEYLINE_COLOR.equals(key)) { + } else if(GridPreferences.KEY_KEYLINE_COLOR.equals(key)) { mDualColorPicker.setSecondaryColor(ColorUtils.getKeylineColor(getContext())); } } private BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override - public void onReceive(Context context, Intent intent) { - - } + public void onReceive(Context context, Intent intent) {} }; } diff --git a/app/src/main/java/org/cyanogenmod/designertools/ui/MockupOverlayCardFragmnt.java b/app/src/main/java/org/cyanogenmod/designertools/ui/MockupOverlayCardFragmnt.java index eb32c12..75ee76b 100644 --- a/app/src/main/java/org/cyanogenmod/designertools/ui/MockupOverlayCardFragmnt.java +++ b/app/src/main/java/org/cyanogenmod/designertools/ui/MockupOverlayCardFragmnt.java @@ -32,11 +32,10 @@ import org.cyanogenmod.designertools.R; -import org.cyanogenmod.designertools.qs.OnOffTileState; import org.cyanogenmod.designertools.utils.ImageUtils; import org.cyanogenmod.designertools.utils.LaunchUtils; import org.cyanogenmod.designertools.utils.MockupUtils; -import org.cyanogenmod.designertools.utils.PreferenceUtils; +import org.cyanogenmod.designertools.utils.PreferenceUtils.MockPreferences; import java.io.IOException; @@ -67,13 +66,13 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, getResources().getColor(R.color.colorMockupOverlayCardTint))); View v =inflater.inflate(R.layout.mockup_overlay_content, mCardContent); - mPortraitImage = (ImageView) v.findViewById(R.id.portrait_image); + mPortraitImage = v.findViewById(R.id.portrait_image); mPortraitImage.setImageBitmap(MockupUtils.getPortraitMockup(getContext())); mPortraitImage.setOnClickListener(mImageClickListener); - mLandscapeImage = (ImageView) v.findViewById(R.id.landscape_image); + mLandscapeImage = v.findViewById(R.id.landscape_image); mLandscapeImage.setImageBitmap(MockupUtils.getLandscapeMockup(getContext())); mLandscapeImage.setOnClickListener(mImageClickListener); - mReset = (Button) v.findViewById(R.id.reset); + mReset = v.findViewById(R.id.reset); mReset.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -87,13 +86,13 @@ public void onClick(View v) { } } }); - mOpacityText = (TextView) v.findViewById(R.id.opacity_text); - mOpacityLevel = (SeekBar) v.findViewById(R.id.opacity); + mOpacityText = v.findViewById(R.id.opacity_text); + mOpacityLevel = v.findViewById(R.id.opacity); mOpacityLevel.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { int opacity = (progress + 1) *10; - PreferenceUtils.setMockOpacity(getContext(), opacity); + MockPreferences.setMockOpacity(getContext(), opacity); setOpacityLevel(opacity); } @@ -107,7 +106,7 @@ public void onStopTrackingTouch(SeekBar seekBar) { } }); - int opacity = PreferenceUtils.getMockOpacity(getContext(), 10); + int opacity = MockPreferences.getMockOpacity(getContext(), 10); setOpacityLevel(opacity); return base; @@ -120,14 +119,10 @@ protected int getCardStyleResourceId() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - if (isChecked == getApplicationContext().getMockOverlayOn()) return; if (isChecked) { - LaunchUtils.lauchMockPverlayOrPublishTile(getContext(), - PreferenceUtils.getMockOverlayActive(getContext(), false) - ? OnOffTileState.STATE_ON - : OnOffTileState.STATE_OFF); + LaunchUtils.launchMockOverlay(getContext()); } else { - LaunchUtils.cancelMockOverlayOrUnpublishTile(getContext()); + LaunchUtils.cancelMockOverlay(getContext()); } } diff --git a/app/src/main/java/org/cyanogenmod/designertools/ui/ScreenRecordRequestActivity.java b/app/src/main/java/org/cyanogenmod/designertools/ui/ScreenRecordRequestActivity.java index 25499f1..d1b49f0 100644 --- a/app/src/main/java/org/cyanogenmod/designertools/ui/ScreenRecordRequestActivity.java +++ b/app/src/main/java/org/cyanogenmod/designertools/ui/ScreenRecordRequestActivity.java @@ -22,7 +22,7 @@ import org.cyanogenmod.designertools.DesignerToolsApplication; import org.cyanogenmod.designertools.overlays.ColorPickerOverlay; -import org.cyanogenmod.designertools.utils.PreferenceUtils; +import org.cyanogenmod.designertools.utils.PreferenceUtils.ColorPickerPreferences; public class ScreenRecordRequestActivity extends Activity { @Override @@ -39,7 +39,7 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) { resultCode, data); Intent newIntent = new Intent(this, ColorPickerOverlay.class); this.startService(newIntent); - PreferenceUtils.setColorPickerActive(this, true); + ColorPickerPreferences.setColorPickerActive(this, true); } finish(); } diff --git a/app/src/main/java/org/cyanogenmod/designertools/ui/ScreenshotCardFragment.java b/app/src/main/java/org/cyanogenmod/designertools/ui/ScreenshotCardFragment.java index d2f23cf..92e31a4 100644 --- a/app/src/main/java/org/cyanogenmod/designertools/ui/ScreenshotCardFragment.java +++ b/app/src/main/java/org/cyanogenmod/designertools/ui/ScreenshotCardFragment.java @@ -16,10 +16,14 @@ package org.cyanogenmod.designertools.ui; import android.Manifest; +import android.app.AlertDialog; import android.content.Intent; import android.content.pm.PackageManager; import android.content.res.ColorStateList; +import android.os.Build; import android.os.Bundle; +import android.os.Environment; +import android.provider.Settings; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -27,13 +31,14 @@ import org.cyanogenmod.designertools.R; import org.cyanogenmod.designertools.service.ScreenshotListenerService; -import org.cyanogenmod.designertools.utils.PreferenceUtils; +import org.cyanogenmod.designertools.utils.PreferenceUtils.ScreenshotPreferences; public class ScreenshotCardFragment extends DesignerToolCardFragment { + private static final int REQUEST_CODE = 0x42; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { + Bundle savedInstanceState) { View base = super.onCreateView(inflater, container, savedInstanceState); setTitleText(R.string.header_title_screenshot); setTitleSummary(R.string.header_summary_screenshot); @@ -41,16 +46,17 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, base.setBackgroundTintList(ColorStateList.valueOf( getResources().getColor(R.color.colorScreenshotCardTint))); - mEnabledSwitch.setChecked(PreferenceUtils.getScreenshotInfoEnabled(getContext(), false)); + mEnabledSwitch.setChecked(ScreenshotPreferences.getScreenshotInfoEnabled(getContext(), + false)); return base; } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, - int[] grantResults) { - if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { - PreferenceUtils.setScreenshotInfoEnabled(getContext(), true); + int[] grantResults) { + if (hasRequiredPermissions()) { + ScreenshotPreferences.setScreenshotInfoEnabled(getContext(), true); Intent newIntent = new Intent(getContext(), ScreenshotListenerService.class); getContext().startService(newIntent); mEnabledSwitch.setChecked(true); @@ -66,20 +72,49 @@ protected int getCardStyleResourceId() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - if (!isVisible()) return; - if (isChecked) { - if (getActivity().checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) - == PackageManager.PERMISSION_GRANTED) { - PreferenceUtils.setScreenshotInfoEnabled(getContext(), isChecked); + if (hasRequiredPermissions()) { + ScreenshotPreferences.setScreenshotInfoEnabled(getContext(), true); Intent newIntent = new Intent(getContext(), ScreenshotListenerService.class); getContext().startService(newIntent); } else { mEnabledSwitch.setChecked(false); - requestPermissions(new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, 42); + if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q) { + requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE); + } else { + showReasoningDialog(); + } } } else { - PreferenceUtils.setScreenshotInfoEnabled(getContext(), false); + ScreenshotPreferences.setScreenshotInfoEnabled(getContext(), false); + } + } + + private boolean hasRequiredPermissions() { + if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q) { + return getApplicationContext().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) + == PackageManager.PERMISSION_GRANTED; + } else { + return Environment.isExternalStorageManager(); } } + + private void requestAccessAllFilesPermission() { + Intent intent = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + getApplicationContext().startActivity(intent); + } + + private void showReasoningDialog() { + AlertDialog.Builder builder = + new AlertDialog.Builder(getActivity(), R.style.AlertDialog); + builder.setTitle(R.string.dialog_request_file_permission_title) + .setMessage(R.string.dialog_request_file_permission_message) + .setPositiveButton(R.string.dialog_request_file_permission_grant, (dialog, which) -> { + requestAccessAllFilesPermission(); + }) + .setNegativeButton(R.string.dialog_request_file_permission_deny, (dialog, which) -> {}) + .setIcon(R.drawable.ic_launcher) + .show(); + } } diff --git a/app/src/main/java/org/cyanogenmod/designertools/ui/StartOverlayActivity.java b/app/src/main/java/org/cyanogenmod/designertools/ui/StartOverlayActivity.java index c069098..f22547c 100644 --- a/app/src/main/java/org/cyanogenmod/designertools/ui/StartOverlayActivity.java +++ b/app/src/main/java/org/cyanogenmod/designertools/ui/StartOverlayActivity.java @@ -1,22 +1,36 @@ +/* + * Copyright (C) 2016 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.cyanogenmod.designertools.ui; import android.app.Activity; +import android.app.AlertDialog; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.provider.Settings; +import org.cyanogenmod.designertools.R; import org.cyanogenmod.designertools.overlays.GridOverlay; import org.cyanogenmod.designertools.overlays.MockOverlay; import org.cyanogenmod.designertools.utils.LaunchUtils; -import org.cyanogenmod.designertools.utils.PreferenceUtils; - -/** - * Created by clark on 12/19/16. - */ +import org.cyanogenmod.designertools.utils.PreferenceUtils.GridPreferences; +import org.cyanogenmod.designertools.utils.PreferenceUtils.MockPreferences; public class StartOverlayActivity extends Activity { - private static final int REQUEST_OVERLAY_PERMSSISION = 42; + private static final int REQUEST_OVERLAY_PERMISSION = StartOverlayActivity.class.hashCode(); public static final String EXTRA_OVERLAY_TYPE = "overlayType"; public static final int GRID_OVERLAY = 0; @@ -35,11 +49,7 @@ protected void onCreate(Bundle savedInstanceState) { startOverlayService(mOverlayType); finish(); } else { - Intent closeDialogsIntent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); - sendBroadcast(closeDialogsIntent); - Intent newIntent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, - Uri.parse("package:" + getPackageName())); - startActivityForResult(newIntent, REQUEST_OVERLAY_PERMSSISION); + showReasoningDialog(); } } else { finish(); @@ -48,7 +58,7 @@ protected void onCreate(Bundle savedInstanceState) { @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { - if (requestCode == REQUEST_OVERLAY_PERMSSISION) { + if (requestCode == REQUEST_OVERLAY_PERMISSION) { if (Settings.canDrawOverlays(this)) { startOverlayService(mOverlayType); } @@ -62,18 +72,39 @@ private void startOverlayService(int overlayType) { case GRID_OVERLAY: Intent newIntent = new Intent(this, GridOverlay.class); this.startService(newIntent); - PreferenceUtils.setGridOverlayActive(this, true); - PreferenceUtils.setGridQsTileEnabled(this, true); + GridPreferences.setGridOverlayActive(this, true); + GridPreferences.setGridQsTileEnabled(this, true); break; case MOCK_OVERLAY: newIntent = new Intent(this, MockOverlay.class); this.startService(newIntent); - PreferenceUtils.setMockOverlayActive(this, true); - PreferenceUtils.setMockQsTileEnabled(this, true); + MockPreferences.setMockOverlayActive(this, true); + MockPreferences.setMockQsTileEnabled(this, true); break; case COLOR_PICKER_OVERLAY: LaunchUtils.startColorPickerOrRequestPermission(this); break; } } + + private void requestOverlayPermission() { + Intent newIntent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, + Uri.parse("package:" + getPackageName())); + startActivityForResult(newIntent, REQUEST_OVERLAY_PERMISSION); + } + + private void showReasoningDialog() { + AlertDialog.Builder builder = + new AlertDialog.Builder(this, R.style.AlertDialog); + builder.setTitle(R.string.dialog_request_overlay_permission_title) + .setMessage(R.string.dialog_request_overlay_permission_message) + .setPositiveButton(R.string.dialog_request_overlay_permission_grant, (dialog, which) -> { + requestOverlayPermission(); + }) + .setNegativeButton(R.string.dialog_request_overlay_permission_deny, (dialog, which) -> { + finish(); + }) + .setIcon(R.drawable.ic_launcher) + .show(); + } } diff --git a/app/src/main/java/org/cyanogenmod/designertools/utils/ColorUtils.java b/app/src/main/java/org/cyanogenmod/designertools/utils/ColorUtils.java index 7bc2095..ab265dd 100644 --- a/app/src/main/java/org/cyanogenmod/designertools/utils/ColorUtils.java +++ b/app/src/main/java/org/cyanogenmod/designertools/utils/ColorUtils.java @@ -21,12 +21,12 @@ public class ColorUtils { public static int getGridLineColor(Context context) { - return PreferenceUtils.getGridLineColor(context, + return PreferenceUtils.GridPreferences.getGridLineColor(context, context.getColor(R.color.dualColorPickerDefaultPrimaryColor)); } public static int getKeylineColor(Context context) { - return PreferenceUtils.getKeylineColor(context, + return PreferenceUtils.GridPreferences.getKeylineColor(context, context.getColor(R.color.dualColorPickerDefaultSecondaryColor)); } } diff --git a/app/src/main/java/org/cyanogenmod/designertools/utils/ImageUtils.java b/app/src/main/java/org/cyanogenmod/designertools/utils/ImageUtils.java index 147b19f..a8ccc9d 100644 --- a/app/src/main/java/org/cyanogenmod/designertools/utils/ImageUtils.java +++ b/app/src/main/java/org/cyanogenmod/designertools/utils/ImageUtils.java @@ -59,6 +59,6 @@ public static boolean saveBitmap(Bitmap bmp, String path) throws FileNotFoundExc if (bmp == null || path == null) return false; FileOutputStream outputStream = new FileOutputStream(path); - return bmp.compress(Bitmap.CompressFormat.JPEG, 80, outputStream); + return bmp.compress(Bitmap.CompressFormat.PNG, 80, outputStream); } } diff --git a/app/src/main/java/org/cyanogenmod/designertools/utils/LaunchUtils.java b/app/src/main/java/org/cyanogenmod/designertools/utils/LaunchUtils.java index a5eb0ed..6aadf22 100644 --- a/app/src/main/java/org/cyanogenmod/designertools/utils/LaunchUtils.java +++ b/app/src/main/java/org/cyanogenmod/designertools/utils/LaunchUtils.java @@ -18,78 +18,49 @@ import android.app.Activity; import android.content.Context; import android.content.Intent; -import android.os.Build; import org.cyanogenmod.designertools.DesignerToolsApplication; import org.cyanogenmod.designertools.overlays.ColorPickerOverlay; import org.cyanogenmod.designertools.overlays.GridOverlay; import org.cyanogenmod.designertools.overlays.MockOverlay; -import org.cyanogenmod.designertools.qs.ColorPickerQuickSettingsTile; -import org.cyanogenmod.designertools.qs.GridQuickSettingsTile; -import org.cyanogenmod.designertools.qs.MockQuickSettingsTile; import org.cyanogenmod.designertools.ui.ScreenRecordRequestActivity; import org.cyanogenmod.designertools.ui.StartOverlayActivity; +import org.cyanogenmod.designertools.utils.PreferenceUtils.ColorPickerPreferences; +import org.cyanogenmod.designertools.utils.PreferenceUtils.GridPreferences; +import org.cyanogenmod.designertools.utils.PreferenceUtils.MockPreferences; public class LaunchUtils { - public static boolean isCyanogenMod(Context context) { - return context.getPackageManager().hasSystemFeature("org.cyanogenmod.theme"); + public static void launchGridOverlay(Context context) { + startOverlayActivity(context, StartOverlayActivity.GRID_OVERLAY); } - public static void lauchGridOverlayOrPublishTile(Context context, int state) { - if (isCyanogenMod(context) && Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { - GridQuickSettingsTile.publishGridTile(context, state); - } else { - startOverlayActivity(context, StartOverlayActivity.GRID_OVERLAY); - } + public static void cancelGridOverlay(Context context) { + Intent newIntent = new Intent(context, GridOverlay.class); + context.stopService(newIntent); + GridPreferences.setGridOverlayActive(context, false); + GridPreferences.setGridQsTileEnabled(context, false); } - public static void cancelGridOverlayOrUnpublishTile(Context context) { - if (isCyanogenMod(context) && Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { - GridQuickSettingsTile.unpublishGridTile(context); - } else { - Intent newIntent = new Intent(context, GridOverlay.class); - context.stopService(newIntent); - PreferenceUtils.setGridOverlayActive(context, false); - PreferenceUtils.setGridQsTileEnabled(context, false); - } + public static void launchMockOverlay(Context context) { + startOverlayActivity(context, StartOverlayActivity.MOCK_OVERLAY); } - public static void lauchMockPverlayOrPublishTile(Context context, int state) { - if (isCyanogenMod(context) && Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { - MockQuickSettingsTile.publishMockTile(context, state); - } else { - startOverlayActivity(context, StartOverlayActivity.MOCK_OVERLAY); - } + public static void cancelMockOverlay(Context context) { + Intent newIntent = new Intent(context, MockOverlay.class); + context.stopService(newIntent); + MockPreferences.setMockOverlayActive(context, false); + MockPreferences.setMockQsTileEnabled(context, false); } - public static void cancelMockOverlayOrUnpublishTile(Context context) { - if (isCyanogenMod(context) && Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { - MockQuickSettingsTile.unpublishMockTile(context); - } else { - Intent newIntent = new Intent(context, MockOverlay.class); - context.stopService(newIntent); - PreferenceUtils.setMockOverlayActive(context, false); - PreferenceUtils.setMockQsTileEnabled(context, false); - } + public static void launchColorPickerOverlay(Context context) { + startOverlayActivity(context, StartOverlayActivity.COLOR_PICKER_OVERLAY); } - public static void lauchColorPickerOrPublishTile(Context context, int state) { - if (isCyanogenMod(context) && Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { - ColorPickerQuickSettingsTile.publishColorPickerTile(context, state); - } else { - startOverlayActivity(context, StartOverlayActivity.COLOR_PICKER_OVERLAY); - } - } - - public static void cancelColorPickerOrUnpublishTile(Context context) { - if (isCyanogenMod(context) && Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { - ColorPickerQuickSettingsTile.unpublishColorPickerTile(context); - } else { - Intent newIntent = new Intent(context, ColorPickerOverlay.class); - context.stopService(newIntent); - PreferenceUtils.setColorPickerActive(context, false); - PreferenceUtils.setColorPickerQsTileEnabled(context, false); - } + public static void cancelColorPickerOverlay(Context context) { + Intent newIntent = new Intent(context, ColorPickerOverlay.class); + context.stopService(newIntent); + ColorPickerPreferences.setColorPickerActive(context, false); + ColorPickerPreferences.setColorPickerQsTileEnabled(context, false); } public static void startColorPickerOrRequestPermission(Context context) { @@ -98,8 +69,8 @@ public static void startColorPickerOrRequestPermission(Context context) { if (app.getScreenRecordResultCode() == Activity.RESULT_OK && app.getScreenRecordResultData() != null) { Intent newIntent = new Intent(context, ColorPickerOverlay.class); context.startService(newIntent); - PreferenceUtils.setColorPickerActive(context, true); - PreferenceUtils.setColorPickerQsTileEnabled(context, true); + ColorPickerPreferences.setColorPickerActive(context, true); + ColorPickerPreferences.setColorPickerQsTileEnabled(context, true); } else { Intent intent = new Intent(context, ScreenRecordRequestActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); diff --git a/app/src/main/java/org/cyanogenmod/designertools/utils/MockupUtils.java b/app/src/main/java/org/cyanogenmod/designertools/utils/MockupUtils.java index bad7f66..18db970 100644 --- a/app/src/main/java/org/cyanogenmod/designertools/utils/MockupUtils.java +++ b/app/src/main/java/org/cyanogenmod/designertools/utils/MockupUtils.java @@ -19,6 +19,8 @@ import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import org.cyanogenmod.designertools.utils.PreferenceUtils.MockPreferences; + import java.io.File; import java.io.IOException; @@ -57,18 +59,18 @@ private static void saveMockup(Context context, Bitmap bmp, String fileName) if (bmp != null) { ImageUtils.saveBitmap(bmp, path + File.separator + fileName); if (PORTRAIT_MOCKUP_FILENAME.equals(fileName)) { - PreferenceUtils.setPortraitMocupkOverlay(context, filePath); + MockPreferences.setPortraitMocupkOverlay(context, filePath); } else if (LANDSCAPE_MOCKUP_FILENAME.equals(fileName)) { - PreferenceUtils.setLandscapeMocupkOverlay(context, filePath); + MockPreferences.setLandscapeMocupkOverlay(context, filePath); } } else { if (PORTRAIT_MOCKUP_FILENAME.equals(fileName)) { if (new File(filePath).delete()) { - PreferenceUtils.setPortraitMocupkOverlay(context, ""); + MockPreferences.setPortraitMocupkOverlay(context, ""); } } else if (LANDSCAPE_MOCKUP_FILENAME.equals(fileName)) { if (new File(filePath).delete()) { - PreferenceUtils.setLandscapeMocupkOverlay(context, ""); + MockPreferences.setLandscapeMocupkOverlay(context, ""); } } } diff --git a/app/src/main/java/org/cyanogenmod/designertools/utils/NotificationUtils.java b/app/src/main/java/org/cyanogenmod/designertools/utils/NotificationUtils.java new file mode 100644 index 0000000..17d46e1 --- /dev/null +++ b/app/src/main/java/org/cyanogenmod/designertools/utils/NotificationUtils.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2019 Scheff's Blend + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.cyanogenmod.designertools.utils; + +import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.Context; +import android.os.Build; +import androidx.annotation.DrawableRes; +import androidx.annotation.NonNull; +import androidx.core.app.NotificationCompat; + +public class NotificationUtils { + @NonNull + public static Notification createForegroundServiceNotification( + @NonNull Context context, + @NonNull String channelId, + @DrawableRes int icon, + @NonNull String title, + @NonNull String contentText, + @NonNull PendingIntent contentIntent) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + NotificationManager nm = context.getSystemService(NotificationManager.class); + NotificationChannel channel = nm.getNotificationChannel(channelId); + if (channel == null) { + channel = new NotificationChannel(channelId, channelId, + NotificationManager.IMPORTANCE_NONE); + channel.enableLights(false); + nm.createNotificationChannel(channel); + } + } + + NotificationCompat.Builder builder = new NotificationCompat.Builder(context, channelId); + builder.setPriority(Notification.PRIORITY_MIN) + .setSmallIcon(icon) + .setContentTitle(title) + .setContentText(contentText) + .setStyle(new NotificationCompat.BigTextStyle().bigText(contentText)) + .setContentIntent(contentIntent); + + return builder.build(); + } +} diff --git a/app/src/main/java/org/cyanogenmod/designertools/utils/PreferenceUtils.java b/app/src/main/java/org/cyanogenmod/designertools/utils/PreferenceUtils.java index 6d316fa..ecac7e1 100644 --- a/app/src/main/java/org/cyanogenmod/designertools/utils/PreferenceUtils.java +++ b/app/src/main/java/org/cyanogenmod/designertools/utils/PreferenceUtils.java @@ -21,188 +21,197 @@ public class PreferenceUtils { private static final String PREFERENCES_FILE = "com.cyngn.designertools_preferences"; - public static final String KEY_GRID_QS_TILE = "grid_qs_tile"; - public static final String KEY_MOCK_QS_TILE = "mock_qs_tile"; - public static final String KEY_SCREENSHOT_QS_TILE = "screenshot_qs_tile"; - public static final String KEY_SHOW_GRID = "grid_increments"; - public static final String KEY_SHOW_KEYLINES = "keylines"; - public static final String KEY_SCREENSHOT_INFO = "screenshot_info"; - public static final String KEY_GRID_STEP_SIZE = "grid_step_size"; - public static final String KEY_MOCK_OPACITY = "mock_opacity"; - public static final String KEY_MOCKUP_OVERLAY_PORTRAIT = "mockup_overlay_portrait"; - public static final String KEY_MOCKUP_OVERLAY_LANDSCAPE = "mock_overlay_landscape"; - public static final String KEY_COLOR_PICKER_QS_TILE = "color_picker_qs_tile"; - public static final String KEY_USE_CUSTOM_GRID_SIZE = "use_custom_grid_size"; - public static final String KEY_GRID_COLUMN_SIZE = "grid_column_size"; - public static final String KEY_GRID_ROW_SIZE = "grid_row_size"; - public static final String KEY_GRID_LINE_COLOR = "grid_line_color"; - public static final String KEY_KEYLINE_COLOR = "keyline_color"; - public static final String KEY_GRID_OVERLAY_ACTIVE = "grid_overlay_active"; - public static final String KEY_MOCK_OVERLAY_ACTIVE = "mock_overlay_active"; - public static final String KEY_COLOR_PICKER_ACTIVE = "color_picker_active"; - public static SharedPreferences getShardedPreferences(Context context) { return context.getSharedPreferences(PREFERENCES_FILE, 0); } - public static void setGridQsTileEnabled(Context context, boolean enabled) { - putBoolean(context, KEY_GRID_QS_TILE, enabled); + private static void putBoolean(Context context, String key, boolean value) { + getShardedPreferences(context).edit().putBoolean(key, value).apply(); } - public static boolean getGridQsTileEnabled(Context context, boolean defValue) { - return getBoolean(context, KEY_GRID_QS_TILE, defValue); + private static boolean getBoolean(Context context, String key, boolean defValue) { + return getShardedPreferences(context).getBoolean(key, defValue); } - public static void setMockQsTileEnabled(Context context, boolean enabled) { - putBoolean(context, KEY_MOCK_QS_TILE, enabled); + private static void putInt(Context context, String key, int value) { + getShardedPreferences(context).edit().putInt(key, value).apply(); } - public static boolean getMockQsTileEnabled(Context context, boolean defValue) { - return getBoolean(context, KEY_MOCK_QS_TILE, defValue); + private static int getInt(Context context, String key, int defValue) { + return getShardedPreferences(context).getInt(key, defValue); } - public static void setColorPickerQsTileEnabled(Context context, boolean enabled) { - putBoolean(context, KEY_COLOR_PICKER_QS_TILE, enabled); + private static void putString(Context context, String key, String value) { + getShardedPreferences(context).edit().putString(key, value).apply(); } - public static boolean getColorPickerQsTileEnabled(Context context, boolean defValue) { - return getBoolean(context, KEY_COLOR_PICKER_QS_TILE, defValue); + private static String getString(Context context, String key, String defValue) { + return getShardedPreferences(context).getString(key, defValue); } - public static void setShowGrid(Context context, boolean show) { - putBoolean(context, KEY_SHOW_GRID, show); - } + public static class GridPreferences { + public static final String KEY_GRID_QS_TILE = "grid_qs_tile"; + public static final String KEY_SHOW_GRID = "grid_increments"; + public static final String KEY_SHOW_KEYLINES = "keylines"; + public static final String KEY_GRID_STEP_SIZE = "grid_step_size"; + public static final String KEY_USE_CUSTOM_GRID_SIZE = "use_custom_grid_size"; + public static final String KEY_GRID_COLUMN_SIZE = "grid_column_size"; + public static final String KEY_GRID_ROW_SIZE = "grid_row_size"; + public static final String KEY_GRID_LINE_COLOR = "grid_line_color"; + public static final String KEY_KEYLINE_COLOR = "keyline_color"; + public static final String KEY_GRID_OVERLAY_ACTIVE = "grid_overlay_active"; - public static boolean getShowGrid(Context context, boolean defValue) { - return getBoolean(context, KEY_SHOW_GRID, defValue); - } + public static void setGridQsTileEnabled(Context context, boolean enabled) { + putBoolean(context, KEY_GRID_QS_TILE, enabled); + } - public static void setShowKeylines(Context context, boolean show) { - putBoolean(context, KEY_SHOW_KEYLINES, show); - } + public static boolean getGridQsTileEnabled(Context context, boolean defValue) { + return getBoolean(context, KEY_GRID_QS_TILE, defValue); + } - public static boolean getShowKeylines(Context context, boolean defValue) { - return getBoolean(context, KEY_SHOW_KEYLINES, defValue); - } + public static void setShowGrid(Context context, boolean show) { + putBoolean(context, KEY_SHOW_GRID, show); + } - public static void setScreenshotInfoEnabled(Context context, boolean enabled) { - putBoolean(context, KEY_SCREENSHOT_INFO, enabled); - } + public static boolean getShowGrid(Context context, boolean defValue) { + return getBoolean(context, KEY_SHOW_GRID, defValue); + } - public static boolean getScreenshotInfoEnabled(Context context, boolean defValue) { - return getBoolean(context, KEY_SCREENSHOT_INFO, defValue); - } + public static void setShowKeylines(Context context, boolean show) { + putBoolean(context, KEY_SHOW_KEYLINES, show); + } - public static void setMockOpacity(Context context, int opacity) { - putInt(context, KEY_MOCK_OPACITY, opacity); - } + public static boolean getShowKeylines(Context context, boolean defValue) { + return getBoolean(context, KEY_SHOW_KEYLINES, defValue); + } - public static int getMockOpacity(Context context, int defValue) { - return getInt(context, KEY_MOCK_OPACITY, defValue); - } + public static void setUseCustomGridSize(Context context, boolean use) { + putBoolean(context, KEY_USE_CUSTOM_GRID_SIZE, use); + } - public static void setPortraitMocupkOverlay(Context context, String pathOrUri) { - putString(context, KEY_MOCKUP_OVERLAY_PORTRAIT, pathOrUri); - } + public static boolean getUseCustomGridSize(Context context, boolean defValue) { + return getBoolean(context, KEY_USE_CUSTOM_GRID_SIZE, defValue); + } - public static String getPortraitMockupOverlay(Context context, String defValue) { - return getString(context, KEY_MOCKUP_OVERLAY_PORTRAIT, defValue); - } + public static void setGridColumnSize(Context context, int stepSize) { + putInt(context, KEY_GRID_COLUMN_SIZE, stepSize); + } - public static void setLandscapeMocupkOverlay(Context context, String pathOrUri) { - putString(context, KEY_MOCKUP_OVERLAY_LANDSCAPE, pathOrUri); - } + public static int getGridColumnSize(Context context, int defValue) { + return getInt(context, KEY_GRID_COLUMN_SIZE, defValue); + } - public static String getLandscapeMockupOverlay(Context context, String defValue) { - return getString(context, KEY_MOCKUP_OVERLAY_LANDSCAPE, defValue); - } + public static void setGridRowSize(Context context, int stepSize) { + putInt(context, KEY_GRID_ROW_SIZE, stepSize); + } - public static void setUseCustomGridSize(Context context, boolean use) { - putBoolean(context, KEY_USE_CUSTOM_GRID_SIZE, use); - } + public static int getGridRowSize(Context context, int defValue) { + return getInt(context, KEY_GRID_ROW_SIZE, defValue); + } - public static boolean getUseCustomGridSize(Context context, boolean defValue) { - return getBoolean(context, KEY_USE_CUSTOM_GRID_SIZE, defValue); - } + public static void setGridLineColor(Context context, int color) { + putInt(context, KEY_GRID_LINE_COLOR, color); + } - public static void setGridColumnSize(Context context, int stepSize) { - putInt(context, KEY_GRID_COLUMN_SIZE, stepSize); - } + public static int getGridLineColor(Context context, int defValue) { + return getInt(context, KEY_GRID_LINE_COLOR, defValue); + } - public static int getGridColumnSize(Context context, int defValue) { - return getInt(context, KEY_GRID_COLUMN_SIZE, defValue); - } + public static void setKeylineColor(Context context, int color) { + putInt(context, KEY_KEYLINE_COLOR, color); + } - public static void setGridRowSize(Context context, int stepSize) { - putInt(context, KEY_GRID_ROW_SIZE, stepSize); - } + public static int getKeylineColor(Context context, int defValue) { + return getInt(context, KEY_KEYLINE_COLOR, defValue); + } - public static int getGridRowSize(Context context, int defValue) { - return getInt(context, KEY_GRID_ROW_SIZE, defValue); - } + public static void setGridOverlayActive(Context context, boolean active) { + putBoolean(context, KEY_GRID_OVERLAY_ACTIVE, active); + } - public static void setGridLineColor(Context context, int color) { - putInt(context, KEY_GRID_LINE_COLOR, color); + public static boolean getGridOverlayActive(Context context, boolean defValue) { + return getBoolean(context, KEY_GRID_OVERLAY_ACTIVE, defValue); + } } - public static int getGridLineColor(Context context, int defValue) { - return getInt(context, KEY_GRID_LINE_COLOR, defValue); - } + public static class MockPreferences { + public static final String KEY_MOCK_OPACITY = "mock_opacity"; + public static final String KEY_MOCKUP_OVERLAY_PORTRAIT = "mockup_overlay_portrait"; + public static final String KEY_MOCKUP_OVERLAY_LANDSCAPE = "mock_overlay_landscape"; + public static final String KEY_MOCK_OVERLAY_ACTIVE = "mock_overlay_active"; + public static final String KEY_MOCK_QS_TILE = "mock_qs_tile"; - public static void setKeylineColor(Context context, int color) { - putInt(context, KEY_KEYLINE_COLOR, color); - } + public static void setMockOpacity(Context context, int opacity) { + putInt(context, KEY_MOCK_OPACITY, opacity); + } - public static int getKeylineColor(Context context, int defValue) { - return getInt(context, KEY_KEYLINE_COLOR, defValue); - } + public static int getMockOpacity(Context context, int defValue) { + return getInt(context, KEY_MOCK_OPACITY, defValue); + } - public static void setGridOverlayActive(Context context, boolean active) { - putBoolean(context, KEY_GRID_OVERLAY_ACTIVE, active); - } + public static void setPortraitMocupkOverlay(Context context, String pathOrUri) { + putString(context, KEY_MOCKUP_OVERLAY_PORTRAIT, pathOrUri); + } - public static boolean getGridOverlayActive(Context context, boolean defValue) { - return getBoolean(context, KEY_GRID_OVERLAY_ACTIVE, defValue); - } + public static String getPortraitMockupOverlay(Context context, String defValue) { + return getString(context, KEY_MOCKUP_OVERLAY_PORTRAIT, defValue); + } - public static void setMockOverlayActive(Context context, boolean active) { - putBoolean(context, KEY_MOCK_OVERLAY_ACTIVE, active); - } + public static void setLandscapeMocupkOverlay(Context context, String pathOrUri) { + putString(context, KEY_MOCKUP_OVERLAY_LANDSCAPE, pathOrUri); + } - public static boolean getMockOverlayActive(Context context, boolean defValue) { - return getBoolean(context, KEY_MOCK_OVERLAY_ACTIVE, defValue); - } + public static String getLandscapeMockupOverlay(Context context, String defValue) { + return getString(context, KEY_MOCKUP_OVERLAY_LANDSCAPE, defValue); + } - public static void setColorPickerActive(Context context, boolean active) { - putBoolean(context, KEY_COLOR_PICKER_ACTIVE, active); - } + public static void setMockOverlayActive(Context context, boolean active) { + putBoolean(context, KEY_MOCK_OVERLAY_ACTIVE, active); + } - public static boolean getColorPickerActive(Context context, boolean defValue) { - return getBoolean(context, KEY_COLOR_PICKER_ACTIVE, defValue); - } + public static boolean getMockOverlayActive(Context context, boolean defValue) { + return getBoolean(context, KEY_MOCK_OVERLAY_ACTIVE, defValue); + } - private static void putBoolean(Context context, String key, boolean value) { - getShardedPreferences(context).edit().putBoolean(key, value).commit(); - } + public static void setMockQsTileEnabled(Context context, boolean enabled) { + putBoolean(context, KEY_MOCK_QS_TILE, enabled); + } - private static boolean getBoolean(Context context, String key, boolean defValue) { - return getShardedPreferences(context).getBoolean(key, defValue); + public static boolean getMockQsTileEnabled(Context context, boolean defValue) { + return getBoolean(context, KEY_MOCK_QS_TILE, defValue); + } } - private static void putInt(Context context, String key, int value) { - getShardedPreferences(context).edit().putInt(key, value).commit(); - } + public static class ColorPickerPreferences { + public static final String KEY_COLOR_PICKER_QS_TILE = "color_picker_qs_tile"; + public static final String KEY_COLOR_PICKER_ACTIVE = "color_picker_active"; - private static int getInt(Context context, String key, int defValue) { - return getShardedPreferences(context).getInt(key, defValue); - } + public static void setColorPickerQsTileEnabled(Context context, boolean enabled) { + putBoolean(context, KEY_COLOR_PICKER_QS_TILE, enabled); + } - private static void putString(Context context, String key, String value) { - getShardedPreferences(context).edit().putString(key, value).commit(); - } + public static boolean getColorPickerQsTileEnabled(Context context, boolean defValue) { + return getBoolean(context, KEY_COLOR_PICKER_QS_TILE, defValue); + } - private static String getString(Context context, String key, String defValue) { - return getShardedPreferences(context).getString(key, defValue); + public static void setColorPickerActive(Context context, boolean active) { + putBoolean(context, KEY_COLOR_PICKER_ACTIVE, active); + } + + public static boolean getColorPickerActive(Context context, boolean defValue) { + return getBoolean(context, KEY_COLOR_PICKER_ACTIVE, defValue); + } } + public static class ScreenshotPreferences { + public static final String KEY_SCREENSHOT_INFO = "screenshot_info"; + + public static void setScreenshotInfoEnabled(Context context, boolean enabled) { + putBoolean(context, KEY_SCREENSHOT_INFO, enabled); + } + + public static boolean getScreenshotInfoEnabled(Context context, boolean defValue) { + return getBoolean(context, KEY_SCREENSHOT_INFO, defValue); + } + } } diff --git a/app/src/main/java/org/cyanogenmod/designertools/utils/ViewUtils.java b/app/src/main/java/org/cyanogenmod/designertools/utils/ViewUtils.java new file mode 100644 index 0000000..67ad09a --- /dev/null +++ b/app/src/main/java/org/cyanogenmod/designertools/utils/ViewUtils.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2019 Scheff's Blend + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.cyanogenmod.designertools.utils; + +import android.os.Build; +import android.view.WindowManager; + +public class ViewUtils { + + public static int getWindowType() { + return getWindowType(false); + } + + public static int getWindowType(boolean useSystemAlert) { + return (Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1) + ? (useSystemAlert + ? WindowManager.LayoutParams.TYPE_SYSTEM_ALERT + : WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY) + : WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; + } +} diff --git a/app/src/main/java/org/cyanogenmod/designertools/widget/DualColorPicker.java b/app/src/main/java/org/cyanogenmod/designertools/widget/DualColorPicker.java index 07f9cc3..013840c 100644 --- a/app/src/main/java/org/cyanogenmod/designertools/widget/DualColorPicker.java +++ b/app/src/main/java/org/cyanogenmod/designertools/widget/DualColorPicker.java @@ -8,12 +8,11 @@ import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; -import android.graphics.Region; import android.util.AttributeSet; import android.view.View; import org.cyanogenmod.designertools.R; -import org.cyanogenmod.designertools.utils.PreferenceUtils; +import org.cyanogenmod.designertools.utils.PreferenceUtils.GridPreferences; public class DualColorPicker extends View { private static final float STROKE_WIDTH = 5f; @@ -40,11 +39,11 @@ public DualColorPicker(Context context, AttributeSet attrs, int defStyleAttr, in super(context, attrs, defStyleAttr, defStyleRes); TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.DualColorPicker, 0, 0); int primaryColor = ta.getColor(R.styleable.DualColorPicker_primaryColor, - PreferenceUtils.getGridLineColor(context, getResources() - .getColor(R.color.dualColorPickerDefaultPrimaryColor))); + GridPreferences.getGridLineColor(context, + context.getColor(R.color.dualColorPickerDefaultPrimaryColor))); int secondaryColor = ta.getColor(R.styleable.DualColorPicker_primaryColor, - PreferenceUtils.getKeylineColor(context, getResources() - .getColor(R.color.dualColorPickerDefaultSecondaryColor))); + GridPreferences.getKeylineColor(context, + context.getColor(R.color.dualColorPickerDefaultSecondaryColor))); mPrimaryFillPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG); mPrimaryFillPaint.setStyle(Paint.Style.FILL); @@ -75,18 +74,22 @@ protected void onDraw(Canvas canvas) { canvas.drawColor(0); // draw the left half - canvas.clipRect(0, 0, widthDiv2, height, Region.Op.REPLACE); + canvas.save(); + canvas.clipRect(0, 0, widthDiv2, height); canvas.drawCircle(widthDiv2, heightDiv2, radius, mPrimaryFillPaint); canvas.drawCircle(widthDiv2, heightDiv2, radius, mPrimaryStrokePaint); canvas.drawLine(widthDiv2 - STROKE_WIDTH / 2f, heightDiv2 - radius, widthDiv2 - STROKE_WIDTH / 2f, heightDiv2 + radius, mPrimaryStrokePaint); + canvas.restore(); /// draw the right half - canvas.clipRect(widthDiv2, 0, width, height, Region.Op.REPLACE); + canvas.save(); + canvas.clipRect(widthDiv2, 0, width, height); canvas.drawCircle(widthDiv2, heightDiv2, radius, mSecondaryFillPaint); canvas.drawCircle(widthDiv2, heightDiv2, radius, mSecondaryStrokePaint); canvas.drawLine(widthDiv2 + STROKE_WIDTH / 2f, heightDiv2 - radius, widthDiv2 + STROKE_WIDTH / 2f, heightDiv2 + radius, mSecondaryStrokePaint); + canvas.restore(); } private int getDarkenedColor(int color) { diff --git a/app/src/main/java/org/cyanogenmod/designertools/widget/MagnifierNodeView.java b/app/src/main/java/org/cyanogenmod/designertools/widget/MagnifierNodeView.java index 7512774..7691467 100644 --- a/app/src/main/java/org/cyanogenmod/designertools/widget/MagnifierNodeView.java +++ b/app/src/main/java/org/cyanogenmod/designertools/widget/MagnifierNodeView.java @@ -44,24 +44,24 @@ public MagnifierNodeView(Context context, AttributeSet attrs, int defStyleAttr, float twoDp = 2f * dm.density; mReticlePaint = new Paint(); mReticlePaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mReticlePaint.setColor(0x50ffffff); + mReticlePaint.setColor(context.getColor(R.color.colorPickerNodeReticleColor)); mReticlePaint.setStrokeWidth(twoDp); mReticlePaint.setStyle(Paint.Style.STROKE); mOutlinePaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mOutlinePaint.setColor(0x80ffffff); + mOutlinePaint.setColor(context.getColor(R.color.colorPickerNodeOutlineColor)); mOutlinePaint.setStrokeWidth(twoDp); mOutlinePaint.setStyle(Paint.Style.STROKE); mOutlinePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.XOR)); mFillPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mFillPaint.setColor(0x80000000); + mFillPaint.setColor(context.getColor(R.color.colorPickerNodeFillColor)); mFillPaint.setStrokeWidth(twoDp); mFillPaint.setStyle(Paint.Style.FILL_AND_STROKE); mFillPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DARKEN)); mClearPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mClearPaint.setColor(0); + mClearPaint.setColor(context.getColor(R.color.colorPickerNodeClearColor)); mClearPaint.setStrokeWidth(twoDp); mClearPaint.setStyle(Paint.Style.FILL); mClearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); diff --git a/app/src/main/java/org/cyanogenmod/designertools/widget/MagnifierView.java b/app/src/main/java/org/cyanogenmod/designertools/widget/MagnifierView.java index 6321e46..12f79bc 100644 --- a/app/src/main/java/org/cyanogenmod/designertools/widget/MagnifierView.java +++ b/app/src/main/java/org/cyanogenmod/designertools/widget/MagnifierView.java @@ -67,14 +67,14 @@ public MagnifierView(Context context, AttributeSet attrs, int defStyleAttr, int DisplayMetrics dm = getResources().getDisplayMetrics(); mGridPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mGridPaint.setColor(0xff000000); + mGridPaint.setColor(context.getColor(R.color.colorPickerMagnifierGridColor)); mGridPaint.setAlpha(128); mGridPaint.setStyle(Paint.Style.STROKE); mGridPaint.setStrokeWidth(1f * dm.density); mGridPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DARKEN)); mPixelOutlinePaint = new Paint(); - mPixelOutlinePaint.setColor(0xff000000); + mPixelOutlinePaint.setColor(context.getColor(R.color.colorPickerMagnifierGridColor)); mPixelOutlinePaint.setStyle(Paint.Style.STROKE); mPixelOutlinePaint.setStrokeWidth(2f * dm.density); mPixelOutlinePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DARKEN)); @@ -94,7 +94,7 @@ public MagnifierView(Context context, AttributeSet attrs, int defStyleAttr, int @Override protected void onFinishInflate() { super.onFinishInflate(); - mColorValueTextView = (TextView) findViewById(R.id.color_value); + mColorValueTextView = findViewById(R.id.color_value); mColorValueTextView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { diff --git a/app/src/main/java/org/cyanogenmod/designertools/widget/VerticalSeekBar.java b/app/src/main/java/org/cyanogenmod/designertools/widget/VerticalSeekBar.java index b0ff2fa..a450020 100644 --- a/app/src/main/java/org/cyanogenmod/designertools/widget/VerticalSeekBar.java +++ b/app/src/main/java/org/cyanogenmod/designertools/widget/VerticalSeekBar.java @@ -3,26 +3,31 @@ */ package org.cyanogenmod.designertools.widget; +import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Canvas; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.os.Build; import android.util.AttributeSet; import android.view.MotionEvent; import android.widget.SeekBar; +@SuppressLint("AppCompatCustomView") public class VerticalSeekBar extends SeekBar { public VerticalSeekBar(Context context) { super(context); } - public VerticalSeekBar(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } - public VerticalSeekBar(Context context, AttributeSet attrs) { super(context, attrs); } + public VerticalSeekBar(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(h, w, oldh, oldw); } @@ -34,10 +39,26 @@ protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpe } protected void onDraw(Canvas c) { - c.rotate(-90); + c.rotate(270); c.translate(-getHeight(), 0); - super.onDraw(c); + + // Work around for known bug with Marshmallow where the enabled thumb is not drawn + if (isEnabled() && Build.VERSION.SDK_INT == Build.VERSION_CODES.M) { + drawThumb(c); + } + } + + void drawThumb(Canvas canvas) { + Drawable thumb = getThumb(); + if (thumb != null) { + Rect thumbBounds = thumb.getBounds(); + canvas.save(); + canvas.rotate(270, thumbBounds.exactCenterX(), thumbBounds.exactCenterY()); + canvas.translate(0, thumbBounds.height() / 3f); + thumb.draw(canvas); + canvas.restore(); + } } @Override diff --git a/app/src/main/res/drawable-hdpi/ic_header_glyph.png b/app/src/main/res/drawable-hdpi/ic_header_glyph.png new file mode 100644 index 0000000..8d32af8 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_header_glyph.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_launcher.png b/app/src/main/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 0000000..36d6ba1 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_launcher.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_header_glyph.png b/app/src/main/res/drawable-mdpi/ic_header_glyph.png new file mode 100644 index 0000000..1b09e3d Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_header_glyph.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_launcher.png b/app/src/main/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 0000000..e9b0cfb Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_launcher.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_header_glyph.png b/app/src/main/res/drawable-xhdpi/ic_header_glyph.png new file mode 100644 index 0000000..58d6726 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_header_glyph.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_launcher.png b/app/src/main/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 0000000..8875ec2 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_launcher.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_header_glyph.png b/app/src/main/res/drawable-xxhdpi/ic_header_glyph.png new file mode 100644 index 0000000..562c92e Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_header_glyph.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_launcher.png b/app/src/main/res/drawable-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..24c96e7 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_launcher.png b/app/src/main/res/drawable-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..d23a493 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/drawable/card_background.xml b/app/src/main/res/drawable/card_background.xml index 1619458..aee130c 100644 --- a/app/src/main/res/drawable/card_background.xml +++ b/app/src/main/res/drawable/card_background.xml @@ -18,6 +18,6 @@ android:shape="rectangle"> + android:radius="16dp"/> \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_header_glyph.xml b/app/src/main/res/drawable/ic_header_glyph.xml index 1808f82..2692b9c 100644 --- a/app/src/main/res/drawable/ic_header_glyph.xml +++ b/app/src/main/res/drawable/ic_header_glyph.xml @@ -1,51 +1,10 @@ - - - - - - \ No newline at end of file + + + diff --git a/app/src/main/res/drawable/ic_shortcut_colorpicker.xml b/app/src/main/res/drawable/ic_shortcut_colorpicker.xml new file mode 100644 index 0000000..b421f2f --- /dev/null +++ b/app/src/main/res/drawable/ic_shortcut_colorpicker.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_shortcut_grid.xml b/app/src/main/res/drawable/ic_shortcut_grid.xml new file mode 100644 index 0000000..917b744 --- /dev/null +++ b/app/src/main/res/drawable/ic_shortcut_grid.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_shortcut_mock.xml b/app/src/main/res/drawable/ic_shortcut_mock.xml new file mode 100644 index 0000000..081d99f --- /dev/null +++ b/app/src/main/res/drawable/ic_shortcut_mock.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout-land/activity_designer_tools.xml b/app/src/main/res/layout-land/activity_designer_tools.xml index 432a7c1..e68571d 100644 --- a/app/src/main/res/layout-land/activity_designer_tools.xml +++ b/app/src/main/res/layout-land/activity_designer_tools.xml @@ -33,7 +33,7 @@ android:layout_marginStart="16dp" android:layout_marginBottom="8dp" android:textSize="16sp" - android:text="@string/qs_section_text"/> + android:text="@string/overlays_section_text"/> + android:text="@string/overlays_section_text"/> + android:text="@string/overlays_section_text"/> + android:outlineProvider="background"> diff --git a/app/src/main/res/layout/dialog_color_picker.xml b/app/src/main/res/layout/dialog_color_picker.xml index 6819753..3433c52 100644 --- a/app/src/main/res/layout/dialog_color_picker.xml +++ b/app/src/main/res/layout/dialog_color_picker.xml @@ -19,7 +19,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content"> - diff --git a/app/src/main/res/layout/mockup_overlay_content.xml b/app/src/main/res/layout/mockup_overlay_content.xml index ede8d83..2c1662b 100644 --- a/app/src/main/res/layout/mockup_overlay_content.xml +++ b/app/src/main/res/layout/mockup_overlay_content.xml @@ -108,6 +108,6 @@ android:id="@+id/opacity" android:layout_width="match_parent" android:layout_height="wrap_content" - android:max="8"/> + android:max="9"/> \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..be31618 --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png index ba6f34b..dcf42ea 100644 Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher.png and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_background.png b/app/src/main/res/mipmap-hdpi/ic_launcher_background.png new file mode 100644 index 0000000..a3b1027 Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_background.png differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..3be952c Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png index 4691808..c1a0c51 100644 Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher.png and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_background.png b/app/src/main/res/mipmap-mdpi/ic_launcher_background.png new file mode 100644 index 0000000..1c43307 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_background.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..2191a08 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png index db7029e..a3d7896 100644 Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png new file mode 100644 index 0000000..cf77a13 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..33b3581 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png index 17d58e6..4b7bc88 100644 Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png new file mode 100644 index 0000000..6eb0a75 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..20fb617 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png index b286b4b..2d32e53 100644 Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png new file mode 100644 index 0000000..09db962 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..8ff152c Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 848757a..2c47915 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -43,4 +43,10 @@ #f9f9f9 #263238 + #50ffffff + #80ffffff + #80000000 + #00000000 + #ff000000 + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e95a3cc..31fd77c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,79 +1,92 @@ - - - Designer Tools - - Grid overlay - On-screen grids help you check your layouts for misaligned elements and inconsistent spacing across your app. Cycle between 8dp, 4dp text baseline, and a custom size of your choice. - - Mockup overlay - Overlaying a mockup gives you a live preview of the screen layout as you’re working. - - Color picker - Check on-screen colors at the pixel level by dragging the loupe dot around. - - Screenshot details - Append device information to every screenshot you take. Record device name, build details, screen specs, and more. - - Quick settings tiles - Overlays - Functions - - Line colors - Include keylines - Include custom grid size - - Current mockup: - Portait - Landscape - Reset mockups - %d %% Opacity - - - Grid - Mock overlay - Screenshot - Color picker - - Accept - Cancel - Grid and keyline colors - - Grid - Keyline - - - Screenshot Info - Device - Code Name - Build - Screen Size - Screen Density - - Press to hide color picker - Press to show color picker - - Press to hide grid - Press to show grid - - Press to hide mockup - Press to show mockup - - Screenshot info enabled - - Color value copied to clipboard - - + + + Designer Tools + + Grid overlay + On-screen grids help you check your layouts for misaligned elements and inconsistent spacing across your app. Use the default 8dp grid or a custom size of your choice. + + Mockup overlay + Overlaying a mockup gives you a live preview of the screen layout as you’re working. + + Color picker + Check on-screen colors at the pixel level by dragging the loupe dot around. + + Screenshot details + Append device information to every screenshot you take. Record device name, build details, screen specs, and more. + + Quick settings tiles + Overlays + Functions + + Line colors + Include keylines + Include custom grid size + + Current mockup: + Portait + Landscape + Reset mockups + %d %% Opacity + + + Grid + Mock overlay + Screenshot + Color picker + + Accept + Cancel + Grid and keyline colors + + Grid + Keyline + + + Screenshot Info + Device + Code Name + Build + Screen Size + Screen Density + + Press to hide color picker + Press to show color picker + + Press to hide grid + Press to show grid + + Press to hide mockup + Press to show mockup + + Screenshot info enabled + + Color value copied to clipboard + + File Access Required + + This feature requires \'All files access\' in order to write screenshot info.\n\nWould you like to enable this now? + + Let\'s go! + No thanks + + Display over other apps + + This feature requires permission to display over other apps.\n\nWould you like to enable this now? + + Let\'s go! + No thanks + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index d80229d..74e2200 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -17,15 +17,14 @@ - - - diff --git a/app/src/main/res/xml/app_shortcuts.xml b/app/src/main/res/xml/app_shortcuts.xml new file mode 100644 index 0000000..a7cbb8e --- /dev/null +++ b/app/src/main/res/xml/app_shortcuts.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/build.gradle b/build.gradle index cfce2ca..2ca7ceb 100644 --- a/build.gradle +++ b/build.gradle @@ -2,10 +2,11 @@ buildscript { repositories { + google() jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.2.3' + classpath 'com.android.tools.build:gradle:7.3.1' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files @@ -15,6 +16,7 @@ buildscript { allprojects { repositories { jcenter() + google() } } diff --git a/gradle.properties b/gradle.properties index 9b6ae2a..bdda067 100644 --- a/gradle.properties +++ b/gradle.properties @@ -15,4 +15,6 @@ # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true \ No newline at end of file +# org.gradle.parallel=true +android.enableJetifier=true +android.useAndroidX=true \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ec67e15..0f00a26 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Fri Aug 19 15:01:13 PDT 2016 -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip +#Sun Dec 29 12:58:57 PST 2019 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip diff --git a/gradlew b/gradlew old mode 100644 new mode 100755