Skip to content
This repository has been archived by the owner on Jun 20, 2018. It is now read-only.

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
Build 10, v0.5-alpha
  • Loading branch information
mudar committed May 17, 2017
1 parent 89d503d commit 364d205
Show file tree
Hide file tree
Showing 46 changed files with 1,369 additions and 0 deletions.
1 change: 1 addition & 0 deletions app/.gitignore
@@ -0,0 +1 @@
/build
51 changes: 51 additions & 0 deletions app/build.gradle
@@ -0,0 +1,51 @@
apply plugin: 'com.android.application'

android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
defaultConfig {
applicationId "ca.mudar.rotationquicksetting"
minSdkVersion 24
targetSdkVersion 25
versionCode 10
versionName "0.5-alpha"

resConfigs "en", "fr"
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

ext.enableCrashlytics = true
}

debug {
applicationIdSuffix ".d"
versionNameSuffix "-build-" + getDate()
minifyEnabled false

ext.enableCrashlytics = false
}

debugCrashlytics.initWith(buildTypes.debug)
debugCrashlytics {
applicationIdSuffix ""

buildConfigField "boolean", "USE_CRASHLYTICS", "true"
ext.enableCrashlytics = true
}
}
}

def static getDate() {
new Date().format('ddMMMyyyy.HHmm')
}

ext.supportLibVersion = '25.3.1'

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile "com.android.support:appcompat-v7:$supportLibVersion"
compile "com.android.support:design:$supportLibVersion"
}
25 changes: 25 additions & 0 deletions app/proguard-rules.pro
@@ -0,0 +1,25 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /home/mudar/android-sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# Add any project specific keep options here:

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
36 changes: 36 additions & 0 deletions app/src/main/AndroidManifest.xml
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="ca.mudar.rotationquicksetting">

<uses-permission android:name="android.permission.WRITE_SETTINGS" />

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:resizeableActivity="true"
android:roundIcon="@mipmap/ic_launcher"
android:theme="@style/AppTheme">

<activity
android:name="ca.mudar.rotationquicksetting.ui.MainActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<service
android:name="ca.mudar.rotationquicksetting.service.QuickSettingsService"
android:icon="@drawable/ic_screen_lock_rotation"
android:label="@string/tile_label"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
<intent-filter>
<action android:name="android.service.quicksettings.action.QS_TILE" />
</intent-filter>
</service>
</application>

</manifest>
21 changes: 21 additions & 0 deletions app/src/main/java/ca/mudar/rotationquicksetting/Const.java
@@ -0,0 +1,21 @@
package ca.mudar.rotationquicksetting;

/**
* Created by mudar on 10/05/17.
*/

public class Const {

/**
* SharedPreferences
*/
public static final String APP_PREFS_NAME = "orientation_tile_prefs";

public interface PrefsNames {
String REVERSE_PORT = "prefs_reverse_port";
String REVERSE_LAND = "prefs_reverse_land";
String AUTO_ROTATE = "prefs_auto_rotate";
String PERMISSION_GRANTED = "prefs_permission_granted";
String ABOUT = "prefs_about";
}
}
@@ -0,0 +1,59 @@
package ca.mudar.rotationquicksetting.data;

import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;

import ca.mudar.rotationquicksetting.Const;
import ca.mudar.rotationquicksetting.Const.PrefsNames;
import ca.mudar.rotationquicksetting.R;

/**
* Created by mudar on 10/05/17.
*/

public class UserPrefs {

private static UserPrefs instance;
private SharedPreferences mPrefs;
private SharedPreferences.Editor mPrefsEditor;

private UserPrefs(Context context) {
mPrefs = context.getSharedPreferences(Const.APP_PREFS_NAME, Context.MODE_PRIVATE);
}

public static UserPrefs getInstance(Context context) {
if (instance == null) {
instance = new UserPrefs(context);
}
return instance;
}

private SharedPreferences.Editor edit() {
if (mPrefsEditor == null) {
mPrefsEditor = mPrefs.edit();
}

return mPrefsEditor;
}

public static void setDefaults(Context context) {
PreferenceManager.setDefaultValues(context,
Const.APP_PREFS_NAME,
Context.MODE_PRIVATE,
R.xml.prefs_defaults,
false);
}

public boolean isReversePortrait() {
return mPrefs.getBoolean(PrefsNames.REVERSE_PORT, false);
}

public boolean isReverseLandscape() {
return mPrefs.getBoolean(PrefsNames.REVERSE_LAND, false);
}

public boolean hasAutoRotate() {
return mPrefs.getBoolean(PrefsNames.AUTO_ROTATE, false);
}
}
@@ -0,0 +1,182 @@
package ca.mudar.rotationquicksetting.service;

import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.provider.Settings;
import android.service.quicksettings.Tile;
import android.service.quicksettings.TileService;
import android.support.v4.app.NotificationCompat;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.view.WindowManager;

import ca.mudar.rotationquicksetting.R;
import ca.mudar.rotationquicksetting.data.UserPrefs;
import ca.mudar.rotationquicksetting.utils.OrientationUtils;

/**
* Created by mudar on 07/05/17.
*/

public class QuickSettingsService extends TileService {
private final static String TAG = "QuickSettingsService";


@Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "onCreate: ");
}

@Override
public void onStartListening() {
super.onStartListening();
Log.i(TAG, "onStartListening: ");

try {
updateQuickSettingsTile(getCurrentOrientation(UserPrefs.getInstance(getApplicationContext()).hasAutoRotate()),
Settings.System.canWrite(getApplicationContext()));
} catch (Settings.SettingNotFoundException e) {
e.printStackTrace();
}
}

@Override
public void onStopListening() {
super.onStopListening();
Log.i(TAG, "onStopListening: ");
}

@Override
public void onClick() {
Log.i(TAG, "onClick: ");

if (Settings.System.canWrite(getApplicationContext())) {
try {
final int newOrientation = toggleOrientation();
updateQuickSettingsTile(newOrientation, true);
} catch (Settings.SettingNotFoundException e) {
e.printStackTrace();
}
} else {
showPermissionNotification();
}
}

private void updateQuickSettingsTile(int orientation, boolean canWriteSettings) throws Settings.SettingNotFoundException {
Log.d(TAG, "updateQuickSettingsTile() called with: orientation = [" + orientation + "]");
final Tile tile = getQsTile();
tile.setState(canWriteSettings ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE);

if (OrientationUtils.isLandscape(orientation)) {
tile.setIcon(Icon.createWithResource(getApplicationContext(), R.drawable.ic_screen_landscape));
tile.setLabel(getString(R.string.tile_label_land));
} else if (OrientationUtils.isPortrait(orientation)) {
tile.setIcon(Icon.createWithResource(getApplicationContext(), R.drawable.ic_screen_portrait));
tile.setLabel(getString(R.string.tile_label_port));
} else {
tile.setIcon(Icon.createWithResource(getApplicationContext(), R.drawable.ic_screen_rotation));
tile.setLabel(getString(R.string.tile_label_auto_rotate));
}

tile.updateTile();
}

/**
* Toggles current location, and returns the new value.
* Requires a prior check of Settings.System.canWrite()
*
* @return new rotation
*/
private int toggleOrientation() throws Settings.SettingNotFoundException {
Log.i(TAG, "toggleOrientation: ");
final ContentResolver contentResolver = getContentResolver();
final UserPrefs userPrefs = UserPrefs.getInstance(getApplicationContext());

if (userPrefs.hasAutoRotate() &&
Settings.System.getInt(contentResolver, Settings.System.ACCELEROMETER_ROTATION) == 0) {
// Enable auto-rotation
Log.e(TAG, "Enable auto-rotation");
Settings.System.putInt(contentResolver, Settings.System.ACCELEROMETER_ROTATION, 1);
return OrientationUtils.ROTATION_AUTO;
}

final int oldOrientation = getCurrentOrientation(false);
final int newOrientation = OrientationUtils.getOppositeOrientation(oldOrientation, userPrefs);

Settings.System.putInt(contentResolver, Settings.System.ACCELEROMETER_ROTATION, 0);
Settings.System.putInt(contentResolver, Settings.System.USER_ROTATION, newOrientation);

return newOrientation;
}

private int getCurrentOrientation(boolean includeAutoRotate) throws Settings.SettingNotFoundException {
Log.i(TAG, "getCurrentOrientation: ");
final ContentResolver contentResolver = getContentResolver();
final boolean hasAccelerometer = (Settings.System
.getInt(contentResolver, Settings.System.ACCELEROMETER_ROTATION) == 1);

if (hasAccelerometer && includeAutoRotate) {
return OrientationUtils.ROTATION_AUTO;
}

return hasAccelerometer ? getAccelerometerOrientation() : getUserOrientation();
}

private int getUserOrientation() throws Settings.SettingNotFoundException {
Log.i(TAG, "getUserOrientation: ");
return Settings.System.getInt(getContentResolver(), Settings.System.USER_ROTATION);
}

private int getAccelerometerOrientation() throws Settings.SettingNotFoundException {
Log.i(TAG, "getAccelerometerOrientation: ");
final WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
return windowManager.getDefaultDisplay().getRotation();
}

/**
* Create and show a simple notification containing the received GCM message.
*/
private void showPermissionNotification() {
final Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS,
Uri.parse("package:" + getPackageName()));

final PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(),
0,
intent,
PendingIntent.FLAG_ONE_SHOT);

final Resources res = getApplicationContext().getResources();
final String contentTitle = res.getString(R.string.notify_permissions_title);
final String contentText = res.getString(R.string.notify_permissions_text);

final Drawable drawable = ContextCompat.getDrawable(getApplicationContext(), R.mipmap.ic_launcher);
final Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();

final NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext())
.setSmallIcon(R.drawable.ic_screen_lock_rotation)
.setLargeIcon(bitmap)
.setColor(getColor(R.color.app_notification))
.setContentTitle(contentTitle)
.setContentText(contentText)
.setOngoing(true)
.setShowWhen(false)
.setAutoCancel(true)
.setPriority(NotificationCompat.PRIORITY_MAX)
.setCategory(NotificationCompat.CATEGORY_MESSAGE)
.setContentIntent(pendingIntent);

((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE))
.notify(0, builder.build());
}

}

0 comments on commit 364d205

Please sign in to comment.