Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
saiho committed Jan 14, 2018
0 parents commit d548e54
Show file tree
Hide file tree
Showing 249 changed files with 2,699 additions and 0 deletions.
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
*.iml
.externalNativeBuild
.gradle
.idea
.DS_Store
/build
/captures
/gradle
/gradlew
/gradlew.bat
/local.properties
21 changes: 21 additions & 0 deletions LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2018 Luis Bonilla Puchades

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Toggle Lineage Profiles

This open source app allows to quickly toggle any of the system profiles defined in LineageOS/Cyanogenmod using a widget from the home screen.

It only works if you have LineageOS/Cyanogenmod 13 or higher installed in your phone.

The functionalities are:

* Having the widget in the home screen you know easily which profile is active at any moment.
* Customize the icon and colors of the profiles to be shown in the widget.
* Get a notification when some profile is activated. For example, if you have a profile that disables the lock screen and it is automatically activated in some circumstances, you may want to get a notification when it is activated.
* Two ways of switching from one profile to another:
* Using a popup window that shows the list of existing profiles and lets you select the one to activate.
* Quick toggle from one profile to the next every time you click in the widget.

This app is totally free, with no ads and no in-app purchases, but provided with no warranty. Feel free to vote 0 starts if you want :)


## Install from play store

https://play.google.com/store/apps/details?id=com.saiho.togglelineageprofiles


## Thanks to

Nick Roach, creator of the flat circle icons set (obtained from https://www.elegantthemes.com).

## Licenses

The code of the app is licensed under the terms of the MIT License.

The icon set has been licensed by his author, Nick Roach 2013, under the terms of GNU General Public License, version 2.
2 changes: 2 additions & 0 deletions app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/build
/release
63 changes: 63 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
apply plugin: 'com.android.application'

def sourceProfileIconList = new File(buildDir, "generated/source/lists")

android {
compileSdkVersion 27
buildToolsVersion '27.0.3'
defaultConfig {
applicationId "com.saiho.togglelineageprofiles"
minSdkVersion 23
targetSdkVersion 27
versionCode 12
versionName '1.0.12'
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
sourceSets {
main {
java {
srcDirs += sourceProfileIconList
}
}
}
productFlavors {
}
}

dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:appcompat-v7:27.0.2'
implementation 'org.cyanogenmod:platform.sdk:6.0'
}

task generateProfileIconList {
doLast {
println "Generating ProfileIconList.java"
def content = "package com.saiho.togglelineageprofiles;\n"
content += "public final class ProfileIconList {\n"
content += "public static java.util.HashMap<String, Integer> ids = new java.util.HashMap<>();\n"
content += "static {\n"
file("\\src\\main\\res\\drawable-nodpi").listFiles(new FilenameFilter() {
@Override
boolean accept(File file, String name) {
return name.startsWith("profile_icon_") && name.endsWith(".png")
}
}).each {
def fileName = it.name[0..it.name.length() - 5]
content += "ids.put(\"" + fileName + "\", R.drawable." + fileName + ");\n"
}
content += "};\n"
content += "}"

def dir = new File(sourceProfileIconList, "com\\saiho\\togglelineageprofiles")
dir.mkdirs()
new File(dir, "ProfileIconList.java").text = content
}
}
preBuild.dependsOn generateProfileIconList
21 changes: 21 additions & 0 deletions app/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# 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
59 changes: 59 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.saiho.togglelineageprofiles">

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

<application
android:allowBackup="true"
android:description="@string/app_description"
android:icon="@mipmap/app_icon"
android:label="@string/app_name"
android:supportsRtl="false"
android:theme="@style/Theme.AppCompat.Light.DarkActionBar">

<activity
android:name=".preferences.SettingsActivity"
android:label="@string/app_name"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<receiver
android:name=".widget.ProfileWidget"
android:exported="true"
android:label="@string/app_name">
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/widget_provider" />
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
</receiver>

<receiver
android:name=".ProfileChangeReceiver"
android:enabled="false"
android:exported="true">
<intent-filter>
<action android:name="cyanogenmod.platform.intent.action.PROFILE_SELECTED" />
<action android:name="cyanogenmod.platform.intent.action.PROFILE_UPDATED" />
</intent-filter>
</receiver>

<receiver
android:name=".widget.ProfileWidget$ClickReceiver"
android:enabled="true"
android:exported="false" />

<activity
android:name=".widget.ProfileWidgetPopup"
android:launchMode="singleTask"
android:noHistory="true"
android:theme="@style/Theme.ProfileWidgetPopup" />

</application>

</manifest>
Binary file added app/src/main/app_icon-web.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
80 changes: 80 additions & 0 deletions app/src/main/java/com/saiho/togglelineageprofiles/Common.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package com.saiho.togglelineageprofiles;

import android.annotation.SuppressLint;
import android.content.Context;
import android.util.MutableInt;

import cyanogenmod.app.Profile;
import cyanogenmod.app.ProfileManager;
import cyanogenmod.os.Build;

public final class Common {
public static final String LOG_TAG = "LogToggleLineageProf";

/**
* Check if LineageOS is present, the system profiles are enabled and at least one profile is defined.
*
* @param context
* @param statusMsgRef Returns the resource id of an error message if there is some problem. Otherwise the
* returning value is set to zero.
* @return true if all the checks are correct.
*/
@SuppressLint("ObsoleteSdkInt")
public static boolean checkSystemProfilesStatus(Context context, MutableInt statusMsgRef) {
if (Build.CM_VERSION.SDK_INT <= 0) {
if (statusMsgRef != null) statusMsgRef.value = R.string.msg_no_lineageos;
return false;
} else {
ProfileManager pm = ProfileManager.getInstance(context);
if (pm == null || !pm.isProfilesEnabled()) {
if (statusMsgRef != null) statusMsgRef.value = R.string.msg_disabled_profiles;
return false;
} else {
String[] profileNames = pm.getProfileNames();
if (profileNames == null || profileNames.length == 0) {
if (statusMsgRef != null) statusMsgRef.value = R.string.msg_no_profiles;
return false;
}
}
}
if (statusMsgRef != null) statusMsgRef.value = 0;
return true;
}

@SuppressLint("ObsoleteSdkInt")
private static ProfileManager getProfileManagerIfEnabled(Context context) {
if (Build.CM_VERSION.SDK_INT > 0) {
ProfileManager pm = ProfileManager.getInstance(context);
if (pm.isProfilesEnabled()) return pm;
}
return null;
}

public static String[] getProfileNames(Context context) {
ProfileManager pm = getProfileManagerIfEnabled(context);
if (pm != null) {
return pm.getProfileNames();
}
return new String[0];
}

public static String getCurrentProfile(Context context) {
ProfileManager pm = getProfileManagerIfEnabled(context);
if (pm != null) {
Profile profile = pm.getActiveProfile();
if (profile != null) {
return profile.getName();
}
}
return null;
}

@SuppressWarnings("deprecation")
public static void setCurrentProfile(Context context, String profileName) {
ProfileManager pm = getProfileManagerIfEnabled(context);
if (pm != null) {
ProfileChangeReceiver.dontNotifyChangedProfile = profileName;
pm.setActiveProfile(profileName);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package com.saiho.togglelineageprofiles;

import android.app.Notification;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.util.Log;

import com.saiho.togglelineageprofiles.preferences.Pref;
import com.saiho.togglelineageprofiles.widget.ProfileWidget;

import static com.saiho.togglelineageprofiles.Common.LOG_TAG;
import static com.saiho.togglelineageprofiles.Common.getCurrentProfile;

public class ProfileChangeReceiver extends BroadcastReceiver {

public static final int NOTIFICATION_ID_PROFILE_CHANGED = 1;
public static String dontNotifyChangedProfile = null;

private static Boolean cachedManifestStateEnabled = null;

public static void refreshManifestState(Context context) {
int newState;
if (Pref.profileNotify.size() > 0 || ProfileWidget.isVisible(context)) {
if (cachedManifestStateEnabled != null && cachedManifestStateEnabled) return;
cachedManifestStateEnabled = true;
newState = PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
Log.i(LOG_TAG, "Enable Profile Change Receiver");
} else {
if (cachedManifestStateEnabled != null && !cachedManifestStateEnabled) return;
cachedManifestStateEnabled = false;
newState = PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
Log.i(LOG_TAG, "Disable Profile Change Receiver");
}

PackageManager pm = context.getPackageManager();
ComponentName compName = new ComponentName(context.getApplicationContext(), ProfileChangeReceiver.class);
pm.setComponentEnabledSetting(compName, newState, PackageManager.DONT_KILL_APP);
}

@Override
public void onReceive(Context context, Intent intent) {
Log.v(LOG_TAG, "Profile change event");
Pref.loadContextPreferences(context);
ProfileWidget.doProfileChanged(context);
showNotification(context);
}

private void showNotification(Context context) {
if (Pref.profileNotify.size() == 0) return;

String currentProfile = getCurrentProfile(context);
if (currentProfile == null) return;

NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (nm == null) return;
nm.cancelAll();

if (!currentProfile.equals(dontNotifyChangedProfile)) {
if (Pref.profileNotify.contains(currentProfile)) {
Integer icon = Pref.profileIcons.get(currentProfile);
if (icon == null) icon = Pref.DEFAULT_ICON;

Bitmap iconBitmap = new ProfileIconDrawable(context, icon, false).convertToBitmap(
context.getResources().getDimensionPixelSize(android.R.dimen.notification_large_icon_width),
context.getResources().getDimensionPixelSize(android.R.dimen.notification_large_icon_height));

@SuppressWarnings("deprecation")
Notification notification = new Notification.Builder(context)
.setContentTitle(context.getString(R.string.notification_title, currentProfile))
.setSmallIcon(R.drawable.notification_icon)
.setLargeIcon(iconBitmap)
.setAutoCancel(true)
.build();

nm.notify(NOTIFICATION_ID_PROFILE_CHANGED, notification);
}
}

dontNotifyChangedProfile = null;
}
}
Loading

0 comments on commit d548e54

Please sign in to comment.