Repository: nicholasrout/lens-launcher
Branch: master
Commit: dd9bd11905ff
Files: 87
Total size: 226.9 KB
Directory structure:
gitextract_6p3thwce/
├── .gitignore
├── LICENSE.md
├── README.md
├── app/
│ ├── .gitignore
│ ├── build.gradle
│ ├── build.gradle.orig
│ ├── proguard-rules.pro
│ └── src/
│ ├── androidTest/
│ │ └── java/
│ │ └── nickrout/
│ │ └── lenslauncher/
│ │ └── ApplicationTest.java
│ ├── main/
│ │ ├── AndroidManifest.xml
│ │ ├── AndroidManifest.xml.orig
│ │ ├── java/
│ │ │ └── nickrout/
│ │ │ └── lenslauncher/
│ │ │ ├── AppsSingleton.java
│ │ │ ├── LensLauncherApplication.java
│ │ │ ├── adapter/
│ │ │ │ └── AppRecyclerAdapter.java
│ │ │ ├── background/
│ │ │ │ ├── BackgroundChangedObservable.java
│ │ │ │ ├── BroadcastReceivers.java
│ │ │ │ ├── EditedObservable.java
│ │ │ │ ├── LoadedObservable.java
│ │ │ │ ├── NightModeObservable.java
│ │ │ │ ├── SortAppsTask.java
│ │ │ │ ├── UpdateAppsTask.java
│ │ │ │ ├── UpdatedObservable.java
│ │ │ │ └── VisibilityChangedObservable.java
│ │ │ ├── model/
│ │ │ │ ├── App.java
│ │ │ │ ├── AppPersistent.java
│ │ │ │ └── Grid.java
│ │ │ ├── ui/
│ │ │ │ ├── AboutActivity.java
│ │ │ │ ├── AppsFragment.java
│ │ │ │ ├── BaseActivity.java
│ │ │ │ ├── FakeLauncherActivity.java
│ │ │ │ ├── HomeActivity.java
│ │ │ │ ├── LensFragment.java
│ │ │ │ ├── LensView.java
│ │ │ │ ├── SettingsActivity.java
│ │ │ │ └── SettingsFragment.java
│ │ │ └── util/
│ │ │ ├── AppSorter.java
│ │ │ ├── AppUtil.java
│ │ │ ├── BitmapUtil.java
│ │ │ ├── ColorUtil.java
│ │ │ ├── IconPackManager.java
│ │ │ ├── LauncherUtil.java
│ │ │ ├── LensCalculator.java
│ │ │ ├── NightModeUtil.java
│ │ │ └── Settings.java
│ │ └── res/
│ │ ├── anim/
│ │ │ ├── fade_in.xml
│ │ │ ├── fade_out.xml
│ │ │ ├── slide_in_left.xml
│ │ │ ├── slide_in_right.xml
│ │ │ ├── slide_out_left.xml
│ │ │ └── slide_out_right.xml
│ │ ├── animator/
│ │ │ └── raise.xml
│ │ ├── drawable/
│ │ │ ├── ic_launcher_background.xml
│ │ │ └── ic_launcher_foreground.xml
│ │ ├── layout/
│ │ │ ├── activity_about.xml
│ │ │ ├── activity_fake_launcher.xml
│ │ │ ├── activity_home.xml
│ │ │ ├── activity_settings.xml
│ │ │ ├── fragment_apps.xml
│ │ │ ├── fragment_lens.xml
│ │ │ ├── fragment_settings.xml
│ │ │ ├── layout_pro.xml
│ │ │ └── recycler_item_app.xml
│ │ ├── menu/
│ │ │ ├── menu_app.xml
│ │ │ └── menu_settings.xml
│ │ ├── mipmap-anydpi-v26/
│ │ │ └── ic_launcher.xml
│ │ ├── values/
│ │ │ ├── arrays.xml
│ │ │ ├── colors.xml
│ │ │ ├── dimen.xml
│ │ │ ├── integers.xml
│ │ │ ├── strings.xml
│ │ │ └── styles.xml
│ │ ├── values-land/
│ │ │ └── dimen.xml
│ │ ├── values-night/
│ │ │ ├── colors.xml
│ │ │ └── styles.xml
│ │ ├── values-w640dp/
│ │ │ └── integers.xml
│ │ ├── values-w820dp/
│ │ │ └── dimen.xml
│ │ └── xml/
│ │ └── shortcuts.xml
│ └── test/
│ └── java/
│ └── nickrout/
│ └── lenslauncher/
│ └── ExampleUnitTest.java
├── build.gradle
├── docker-compose.yml
├── docker-entrypoint.sh
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── resources/
│ └── art/
│ └── lens_launcher.sketch
└── settings.gradle
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# built application files
*.apk
*.ap_
# files for the dex VM
*.dex
# Java class files
*.class
# generated files
bin/
gen/
out/
# Local configuration file (sdk path, etc)
local.properties
# Eclipse project files
.classpath
.project
# Android Studio
.idea/
.gradle
build/
/*/local.properties
local.properties
/*/out
/*/*/build
/*/*/production
*.iml
*.iws
*.ipr
*~
*.swp
proguard/
*.log
.navigation/
captures/
# Keystore files
*.jks
# Android SDK
/android-sdk.zip
/android-studio
================================================
FILE: LICENSE.md
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2017 Nicholas Rout
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.
================================================
FILE: README.md
================================================
# Lens Launcher
Lens Launcher is a unique, efficient way to browse and launch your apps.

Instead of scrolling long lists or swiping through multiple pages, Lens Launcher implements two unique features:
• An Equispaced Grid that displays all of your apps, regardless of screen size or app count.
• A Graphical Fisheye Lens to quickly zoom, pan and launch apps using touch gestures.
Lens Launcher also includes a full Settings menu to tweak all aspects of the Lens; Distortion, Scaling, Icon Size, Haptic Feedback, etc.
The Graphical Fisheye Lens algorithm is derived from methods proposed by Manojit Sarkar and Marc H. Brown. Their original 1993 paper, titled Graphical Fisheye Views, can be found here:
https://drive.google.com/open?id=0B6Nqy9y098RLa2pqNVFUcUhIZXM
Major contributions to Lens Launcher have been made by Rish Bhardwaj (@CreaRo)
You can download Lens Launcher on Google Play:
https://play.google.com/store/apps/details?id=nickrout.lenslauncher
## Build from Source
If you'd like to build from source, you may do so easily with [Docker][1], but
if you are wanting to contribute it may be better to install the build tools on
your machine.
### Easy Way
Building the APK is extremely easy using [`docker-compose`][2], all that is
needed is to run the following inside the repo's directory:
```bash
docker-compose run --rm gradle
```
Then download the APK inside
`lens-launcher/app/build/outputs/apk/app-release.apk` to your phone to install.
### For Development
1. Install the latest Android SDK from [Android Studio][3] and accept the
licenses.
2. Install Java JDK 8 from [Oracle][4].
3. Run `keytool` and create a keystore following the command prompts.
4. Generate an APK with `gradlew` like below:
```bash
gradlew assembleRelease \
-Pandroid.injected.signing.key.alias=$KEY_ALIAS \
-Pandroid.injected.signing.store.file=$KEY_STORE_PATH \
-Pandroid.injected.signing.store.password=$KEY_STORE_PASSWORD \
-Pandroid.injected.signing.key.password=$KEY_PASSWORD;
```
[1]: https://docs.docker.com/
[2]: https://docs.docker.com/compose/install/
[3]: https://developer.android.com/studio/index.html
[4]: http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
================================================
FILE: app/.gitignore
================================================
/build
================================================
FILE: app/build.gradle
================================================
apply plugin: 'com.android.application'
android {
namespace "nickrout.lenslauncher"
compileSdk 34
defaultConfig {
applicationId "nickrout.lenslauncher"
minSdkVersion 15
targetSdkVersion 34
versionCode 46
versionName "3.0.1"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
testImplementation 'junit:junit:4.13.2'
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.android.support:design:26.1.0'
implementation 'com.android.support:recyclerview-v7:26.1.0'
implementation 'com.android.support:cardview-v7:26.1.0'
implementation 'com.android.support:palette-v7:26.1.0'
implementation 'com.github.satyan:sugar:1.5'
implementation 'com.afollestad.material-dialogs:core:0.9.5.0'
implementation 'com.afollestad.material-dialogs:commons:0.9.5.0'
implementation 'com.jakewharton:butterknife:8.8.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
}
tasks.withType(JavaCompile).configureEach{
options.fork = true
options.forkOptions.jvmArgs +=[
'--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED',
'--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED',
'--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED']
}
================================================
FILE: app/build.gradle.orig
================================================
apply plugin: 'com.android.application'
android {
compileSdkVersion 23
buildToolsVersion "23.0.3"
defaultConfig {
applicationId "nickrout.lenslauncher"
minSdkVersion 16
targetSdkVersion 23
versionCode 16
versionName "1.3.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.4.0'
<<<<<<< HEAD
compile 'com.android.support:design:23.1.1'
compile 'com.android.support:recyclerview-v7:23.3.0'
compile 'com.android.support:cardview-v7:23.3.0'
=======
compile 'com.android.support:palette-v7:23.4.0'
>>>>>>> 85209e8a5dc31e126a1f49a543f70d299720c052
compile 'com.github.satyan:sugar:1.5'
compile 'com.afollestad.material-dialogs:core:0.8.5.8'
compile 'com.afollestad.material-dialogs:commons:0.8.5.8'
compile 'com.makeramen:dragsortadapter:1.3.0'
compile 'com.jakewharton:butterknife:7.0.1'
}
================================================
FILE: app/proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /Users/nicholasrout/Library/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 *;
#}
================================================
FILE: app/src/androidTest/java/nickrout/lenslauncher/ApplicationTest.java
================================================
package nickrout.lenslauncher;
import android.app.Application;
import android.test.ApplicationTestCase;
/**
* Testing Fundamentals
*/
public class ApplicationTest extends ApplicationTestCase {
public ApplicationTest() {
super(Application.class);
}
}
================================================
FILE: app/src/main/AndroidManifest.xml
================================================
================================================
FILE: app/src/main/AndroidManifest.xml.orig
================================================
=======
android:value="3" />
>>>>>>> 0c9969d213bbd5efac04492932bd13b6d97bacc0
================================================
FILE: app/src/main/java/nickrout/lenslauncher/AppsSingleton.java
================================================
package nickrout.lenslauncher;
import android.graphics.Bitmap;
import java.util.ArrayList;
import nickrout.lenslauncher.model.App;
/**
* Created by nicholasrout on 2016/05/30.
*/
public class AppsSingleton {
private static AppsSingleton mAppsSingleton;
private ArrayList mApps;
private ArrayList mAppIcons;
private AppsSingleton() {}
public static AppsSingleton getInstance() {
if (mAppsSingleton == null) {
mAppsSingleton = new AppsSingleton();
}
return mAppsSingleton;
}
public ArrayList getApps() {
ArrayList apps = new ArrayList<>();
if (mApps == null) {
return apps;
}
apps.addAll(mApps);
return apps;
}
public void setApps(ArrayList apps) {
mApps = apps;
}
public ArrayList getAppIcons() {
ArrayList appIcons = new ArrayList<>();
if (mAppIcons == null) {
return appIcons;
}
appIcons.addAll(mAppIcons);
return appIcons;
}
public void setAppIcons(ArrayList appIcons) {
mAppIcons = appIcons;
}
}
================================================
FILE: app/src/main/java/nickrout/lenslauncher/LensLauncherApplication.java
================================================
package nickrout.lenslauncher;
import com.orm.SugarApp;
import java.util.Observable;
import java.util.Observer;
import nickrout.lenslauncher.background.SortAppsTask;
import nickrout.lenslauncher.background.EditedObservable;
import nickrout.lenslauncher.background.UpdatedObservable;
import nickrout.lenslauncher.background.UpdateAppsTask;
/**
* Created by nicholasrout on 2016/06/12.
*/
public class LensLauncherApplication extends SugarApp implements Observer {
@Override
public void onCreate() {
super.onCreate();
UpdatedObservable.getInstance().addObserver(this);
EditedObservable.getInstance().addObserver(this);
updateApps();
}
@Override
public void update(Observable observable, Object data) {
if (observable instanceof UpdatedObservable) {
updateApps();
} else if (observable instanceof EditedObservable) {
editApps();
}
}
private void updateApps() {
new UpdateAppsTask(
getPackageManager(),
getApplicationContext(),
this)
.execute();
}
private void editApps() {
new SortAppsTask(
getApplicationContext(),
this)
.execute();
}
}
================================================
FILE: app/src/main/java/nickrout/lenslauncher/adapter/AppRecyclerAdapter.java
================================================
package nickrout.lenslauncher.adapter;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.graphics.Rect;
import android.net.Uri;
import android.provider.Settings;
import android.support.design.widget.Snackbar;
import android.support.v7.widget.CardView;
import android.support.v7.widget.PopupMenu;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import nickrout.lenslauncher.R;
import nickrout.lenslauncher.background.BroadcastReceivers;
import nickrout.lenslauncher.model.App;
import nickrout.lenslauncher.model.AppPersistent;
import nickrout.lenslauncher.ui.SettingsActivity;
import nickrout.lenslauncher.util.AppUtil;
public class AppRecyclerAdapter extends RecyclerView.Adapter {
public static final String TAG = "AppRecyclerAdapter";
private Context mContext;
private final List mApps;
public AppRecyclerAdapter(Context mContext, List mApps) {
this.mContext = mContext;
this.mApps = mApps;
}
public App getItemForPosition(int position) {
return mApps.get(position);
}
@Override
public int getItemCount() {
return mApps.size();
}
@Override
public long getItemId(int position) {
return mApps.get(position).getId();
}
@Override
public AppViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View view = inflater.inflate(R.layout.recycler_item_app, parent, false);
final AppViewHolder holder = new AppViewHolder(view, mContext);
holder.setOnClickListeners();
return holder;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
App app = getItemForPosition(position);
if (app == null) {
return;
}
AppViewHolder appViewHolder = (AppViewHolder) holder;
appViewHolder.setAppElement(app);
}
public static class AppViewHolder extends RecyclerView.ViewHolder implements PopupMenu.OnMenuItemClickListener {
@BindView(R.id.element_app_container)
CardView mContainer;
@BindView(R.id.element_app_label)
TextView mLabel;
@BindView(R.id.element_app_icon)
ImageView mIcon;
@BindView(R.id.element_app_hide)
ImageView mToggleAppVisibility;
@BindView(R.id.element_app_menu)
ImageView mMenu;
private App mApp;
private Context mContext;
public AppViewHolder(View itemView, Context context) {
super(itemView);
ButterKnife.bind(this, itemView);
this.mContext = context;
}
public void setAppElement(App app) {
this.mApp = app;
mLabel.setText(mApp.getLabel());
mIcon.setImageBitmap(mApp.getIcon());
boolean isAppVisible =
AppPersistent.getAppVisibility(mApp.getPackageName().toString(), mApp.getName().toString());
if (isAppVisible) {
mToggleAppVisibility.setImageResource(R.drawable.ic_visibility_grey_24dp);
} else {
mToggleAppVisibility.setImageResource(R.drawable.ic_visibility_off_grey_24dp);
}
if (mApp.getPackageName().toString().equals("nickrout.lenslauncher")) {
mToggleAppVisibility.setVisibility(View.INVISIBLE);
} else {
mToggleAppVisibility.setVisibility(View.VISIBLE);
}
}
public void toggleAppVisibility(App app) {
this.mApp = app;
boolean isAppVisible =
AppPersistent.getAppVisibility(mApp.getPackageName().toString(), mApp.getName().toString());
AppPersistent.setAppVisibility(
mApp.getPackageName().toString(),
mApp.getName().toString(),
!isAppVisible);
if (isAppVisible) {
Snackbar.make(mContainer, mApp.getLabel() + " is now hidden", Snackbar.LENGTH_LONG).show();
mToggleAppVisibility.setImageResource(R.drawable.ic_visibility_off_grey_24dp);
} else {
Snackbar.make(mContainer, mApp.getLabel() + " is now visible", Snackbar.LENGTH_LONG).show();
mToggleAppVisibility.setImageResource(R.drawable.ic_visibility_grey_24dp);
}
}
private void sendChangeAppsVisibilityBroadcast() {
if (mContext == null) {
return;
}
if (!(mContext instanceof SettingsActivity)) {
return;
}
SettingsActivity settingsActivity = (SettingsActivity) mContext;
Intent changeAppsVisibilityIntent = new Intent(settingsActivity, BroadcastReceivers.AppsVisibilityChangedReceiver.class);
settingsActivity.sendBroadcast(changeAppsVisibilityIntent);
}
public void setOnClickListeners() {
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
AppUtil.launchComponent(
mContext,
mApp.getPackageName().toString(), mApp.getName().toString(),
itemView, new Rect(0, 0, itemView.getMeasuredWidth(), itemView.getMeasuredHeight()));
}
});
mToggleAppVisibility.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mApp != null) {
sendChangeAppsVisibilityBroadcast();
toggleAppVisibility(mApp);
} else {
Snackbar.make(mContainer, mContext.getString(R.string.error_app_not_found), Snackbar.LENGTH_LONG).show();
}
}
});
mMenu.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
PopupMenu popupMenu = new PopupMenu(mContext, view);
popupMenu.setOnMenuItemClickListener(AppViewHolder.this);
popupMenu.inflate(R.menu.menu_app);
popupMenu.show();
}
});
}
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_item_element_app_info:
try {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.parse("package:" + mApp.getPackageName()));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(intent);
} catch (ActivityNotFoundException e) {
Toast.makeText(mContext, R.string.error_app_not_found, Toast.LENGTH_SHORT).show();
}
return true;
case R.id.menu_item_element_uninstall:
try {
Intent intent = new Intent(Intent.ACTION_DELETE);
intent.setData(Uri.parse("package:" + mApp.getPackageName()));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(intent);
} catch (ActivityNotFoundException e) {
Toast.makeText(mContext, R.string.error_app_not_found, Toast.LENGTH_SHORT).show();
}
return true;
}
return false;
}
}
}
================================================
FILE: app/src/main/java/nickrout/lenslauncher/background/BackgroundChangedObservable.java
================================================
package nickrout.lenslauncher.background;
import java.util.Observable;
public class BackgroundChangedObservable extends Observable {
private static BackgroundChangedObservable instance = new BackgroundChangedObservable();
public static BackgroundChangedObservable getInstance() {
return instance;
}
private BackgroundChangedObservable() {
}
public void updateValue(Object data) {
synchronized (this) {
setChanged();
notifyObservers(data);
}
}
public void update() {
updateValue(null);
}
}
================================================
FILE: app/src/main/java/nickrout/lenslauncher/background/BroadcastReceivers.java
================================================
package nickrout.lenslauncher.background;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
/**
* Created by nicholasrout on 2016/06/12.
*/
public class BroadcastReceivers {
public static class AppsUpdatedReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
UpdatedObservable.getInstance().update();
}
}
public static class AppsEditedReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
EditedObservable.getInstance().update();
}
}
public static class AppsVisibilityChangedReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
VisibilityChangedObservable.getInstance().update();
}
}
public static class AppsLoadedReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
LoadedObservable.getInstance().update();
}
}
public static class BackgroundChangedReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
BackgroundChangedObservable.getInstance().update();
}
}
public static class NightModeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
NightModeObservable.getInstance().update();
}
}
}
================================================
FILE: app/src/main/java/nickrout/lenslauncher/background/EditedObservable.java
================================================
package nickrout.lenslauncher.background;
import java.util.Observable;
/**
* Created by nicholasrout on 2016/06/23.
*/
public class EditedObservable extends Observable {
private static EditedObservable instance = new EditedObservable();
public static EditedObservable getInstance() {
return instance;
}
private EditedObservable() {
}
public void updateValue(Object data) {
synchronized (this) {
setChanged();
notifyObservers(data);
}
}
public void update() {
updateValue(null);
}
}
================================================
FILE: app/src/main/java/nickrout/lenslauncher/background/LoadedObservable.java
================================================
package nickrout.lenslauncher.background;
import java.util.Observable;
/**
* Created by nicholasrout on 2016/06/12.
*/
public class LoadedObservable extends Observable {
private static LoadedObservable instance = new LoadedObservable();
public static LoadedObservable getInstance() {
return instance;
}
private LoadedObservable() {
}
public void updateValue(Object data) {
synchronized (this) {
setChanged();
notifyObservers(data);
}
}
public void update() {
updateValue(null);
}
}
================================================
FILE: app/src/main/java/nickrout/lenslauncher/background/NightModeObservable.java
================================================
package nickrout.lenslauncher.background;
import java.util.Observable;
/**
* Created by nicholasrout on 2017/01/15.
*/
public class NightModeObservable extends Observable {
private static NightModeObservable instance = new NightModeObservable();
public static NightModeObservable getInstance() {
return instance;
}
private NightModeObservable() {
}
public void updateValue(Object data) {
synchronized (this) {
setChanged();
notifyObservers(data);
}
}
public void update() {
updateValue(null);
}
}
================================================
FILE: app/src/main/java/nickrout/lenslauncher/background/SortAppsTask.java
================================================
package nickrout.lenslauncher.background;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import java.util.ArrayList;
import nickrout.lenslauncher.model.App;
import nickrout.lenslauncher.util.AppSorter;
import nickrout.lenslauncher.AppsSingleton;
import nickrout.lenslauncher.util.Settings;
/**
* Created by nicholasrout on 2016/06/23.
*/
public class SortAppsTask extends AsyncTask {
private Context mContext;
private Application mApplication;
private Settings mSettings;
private ArrayList mApps;
private ArrayList mAppIcons;
public SortAppsTask(Context context,
Application application) {
mContext = context;
mApplication = application;
mSettings = new Settings(mContext);
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected Void doInBackground(Void... params) {
ArrayList apps = AppsSingleton.getInstance().getApps();
AppSorter.sort(apps, mSettings.getSortType());
mApps = new ArrayList<>();
mAppIcons = new ArrayList<>();
for (int i = 0; i < apps.size(); i++) {
App app = apps.get(i);
Bitmap appIcon = app.getIcon();
if (appIcon != null) {
mApps.add(app);
mAppIcons.add(appIcon);
}
}
return null;
}
@Override
protected void onPostExecute(Void result) {
AppsSingleton.getInstance().setApps(mApps);
AppsSingleton.getInstance().setAppIcons(mAppIcons);
Intent appsLoadedIntent = new Intent(mApplication, BroadcastReceivers.AppsLoadedReceiver.class);
mApplication.sendBroadcast(appsLoadedIntent);
super.onPostExecute(result);
}
}
================================================
FILE: app/src/main/java/nickrout/lenslauncher/background/UpdateAppsTask.java
================================================
package nickrout.lenslauncher.background;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import java.util.ArrayList;
import nickrout.lenslauncher.model.App;
import nickrout.lenslauncher.util.AppUtil;
import nickrout.lenslauncher.AppsSingleton;
import nickrout.lenslauncher.util.Settings;
/**
* Created by rish on 26/5/16.
*/
public class UpdateAppsTask extends AsyncTask {
private PackageManager mPackageManager;
private Context mContext;
private Application mApplication;
private Settings mSettings;
private ArrayList mApps;
private ArrayList mAppIcons;
public UpdateAppsTask(PackageManager packageManager,
Context context,
Application application) {
this.mPackageManager = packageManager;
this.mContext = context;
this.mApplication = application;
this.mSettings = new Settings(context);
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected Void doInBackground(Void... params) {
ArrayList apps = AppUtil.getApps(
mPackageManager,
mContext,
mApplication,
mSettings.getString(Settings.KEY_ICON_PACK_LABEL_NAME),
mSettings.getSortType());
mApps = new ArrayList<>();
mAppIcons = new ArrayList<>();
for (int i = 0; i < apps.size(); i++) {
App app = apps.get(i);
Bitmap appIcon = app.getIcon();
if (appIcon != null) {
mApps.add(app);
mAppIcons.add(appIcon);
}
}
return null;
}
@Override
protected void onPostExecute(Void result) {
AppsSingleton.getInstance().setApps(mApps);
AppsSingleton.getInstance().setAppIcons(mAppIcons);
Intent appsLoadedIntent = new Intent(mApplication, BroadcastReceivers.AppsLoadedReceiver.class);
mApplication.sendBroadcast(appsLoadedIntent);
super.onPostExecute(result);
}
}
================================================
FILE: app/src/main/java/nickrout/lenslauncher/background/UpdatedObservable.java
================================================
package nickrout.lenslauncher.background;
import java.util.Observable;
/**
* Created by nickrout on 2016/04/08.
*/
public class UpdatedObservable extends Observable {
private static UpdatedObservable instance = new UpdatedObservable();
public static UpdatedObservable getInstance() {
return instance;
}
private UpdatedObservable() {
}
public void updateValue(Object data) {
synchronized (this) {
setChanged();
notifyObservers(data);
}
}
public void update() {
updateValue(null);
}
}
================================================
FILE: app/src/main/java/nickrout/lenslauncher/background/VisibilityChangedObservable.java
================================================
package nickrout.lenslauncher.background;
import java.util.Observable;
public class VisibilityChangedObservable extends Observable {
private static VisibilityChangedObservable instance = new VisibilityChangedObservable();
public static VisibilityChangedObservable getInstance() {
return instance;
}
private VisibilityChangedObservable() {
}
public void updateValue(Object data) {
synchronized (this) {
setChanged();
notifyObservers(data);
}
}
public void update() {
updateValue(null);
}
}
================================================
FILE: app/src/main/java/nickrout/lenslauncher/model/App.java
================================================
package nickrout.lenslauncher.model;
import android.graphics.Bitmap;
import android.support.annotation.ColorInt;
/**
* Created by nickrout on 2016/04/02.
*/
public class App {
private int mId;
private CharSequence mLabel;
private CharSequence mPackageName;
private CharSequence mName;
private int mIconResId;
private Bitmap mIcon;
private long mInstallDate;
private @ColorInt int mPaletteColor;
public App() {
}
public int getId() {
return mId;
}
public void setId(int mId) {
this.mId = mId;
}
public CharSequence getLabel() {
return mLabel;
}
public void setLabel(CharSequence label) {
mLabel = label;
}
public CharSequence getPackageName() {
return mPackageName;
}
public void setPackageName(CharSequence packageName) {
mPackageName = packageName;
}
public CharSequence getName() {
return mName;
}
public void setName(CharSequence name) {
mName = name;
}
public int getIconResId() {
return mIconResId;
}
public void setIconResId(int iconResId) {
mIconResId = iconResId;
}
public Bitmap getIcon() {
return mIcon;
}
public void setIcon(Bitmap icon) {
mIcon = icon;
}
public long getInstallDate() {
return mInstallDate;
}
public void setInstallDate(long mInstallDate) {
this.mInstallDate = mInstallDate;
}
public int getPaletteColor() {
return mPaletteColor;
}
public void setPaletteColor(int paletteColor) {
mPaletteColor = paletteColor;
}
@Override
public String toString() {
return "App{" +
"mId=" + mId +
", mLabel=" + mLabel +
", mPackageName=" + mPackageName +
", mName=" + mName +
", mIconResId=" + mIconResId +
", mIcon=" + mIcon +
", mInstallDate=" + mInstallDate +
", mPaletteColor=" + mPaletteColor +
'}';
}
}
================================================
FILE: app/src/main/java/nickrout/lenslauncher/model/AppPersistent.java
================================================
package nickrout.lenslauncher.model;
import com.orm.SugarRecord;
import com.orm.query.Condition;
import com.orm.query.Select;
import com.orm.util.NamingHelper;
/**
* Created by rish on 20/5/16.
*/
public class AppPersistent extends SugarRecord {
private static final String TAG = "AppPersistent";
/* Required Default Constructor */
public AppPersistent() {
}
private String mPackageName;
private String mName;
private String mIdentifier;
private long mOpenCount;
private int mOrderNumber;
private boolean mAppVisible;
private static boolean DEFAULT_APP_VISIBILITY = true;
private static int DEFAULT_ORDER_NUMBER = -1;
private static long DEFAULT_OPEN_COUNT = 1;
public AppPersistent(String packageName, String name, long openCount, int orderNumber, boolean appVisible) {
this.mPackageName = packageName;
this.mName = name;
this.mIdentifier = AppPersistent.generateIdentifier(packageName, name);
this.mOpenCount = openCount;
this.mOrderNumber = orderNumber;
this.mAppVisible = appVisible;
}
public String getPackageName() {
return mPackageName;
}
public void setPackageName(String packageName) {
this.mPackageName = packageName;
this.mIdentifier =
AppPersistent.generateIdentifier(this.mPackageName, this.mName);
}
public String getName() {
return mName;
}
public void setName(String name) {
mName = name;
this.mIdentifier =
AppPersistent.generateIdentifier(this.mPackageName, this.mName);
}
public String getIdentifier() {
return mIdentifier;
}
public long getOpenCount() {
return mOpenCount;
}
public void setOpenCount(long openCount) {
this.mOpenCount = openCount;
}
public int getOrderNumber() {
return mOrderNumber;
}
public void setOrderNumber(int orderNumber) {
this.mOrderNumber = orderNumber;
}
public boolean isAppVisible() {
return mAppVisible;
}
public void setAppVisible(boolean appVisible) {
this.mAppVisible = appVisible;
}
@Override
public String toString() {
return "AppPersistent{" +
"mPackageName='" + mPackageName + '\'' +
", mName='" + mName + '\'' +
", mIdentifier='" + mIdentifier + '\'' +
", mOpenCount=" + mOpenCount +
", mOrderNumber=" + mOrderNumber +
", mAppVisible=" + mAppVisible +
'}';
}
public static String generateIdentifier(String packageName, String name) {
return packageName + "-" + name;
}
public static void incrementAppCount(String packageName, String name) {
String identifier = AppPersistent.generateIdentifier(packageName, name);
AppPersistent appPersistent = Select.from(AppPersistent.class).where(Condition.prop(NamingHelper.toSQLNameDefault("mIdentifier")).eq(identifier)).first();
if (appPersistent != null) {
appPersistent.setOpenCount(appPersistent.getOpenCount() + 1);
appPersistent.save();
} else {
AppPersistent newAppPersistent = new AppPersistent(packageName, name, DEFAULT_OPEN_COUNT, DEFAULT_ORDER_NUMBER, DEFAULT_APP_VISIBILITY);
newAppPersistent.save();
}
}
public static void setAppOrderNumber(String packageName, String name, int orderNumber) {
String identifier = AppPersistent.generateIdentifier(packageName, name);
AppPersistent appPersistent = Select.from(AppPersistent.class).where(Condition.prop(NamingHelper.toSQLNameDefault("mIdentifier")).eq(identifier)).first();
if (appPersistent != null) {
appPersistent.setOrderNumber(orderNumber);
appPersistent.save();
} else {
AppPersistent newAppPersistent = new AppPersistent(packageName, name, DEFAULT_OPEN_COUNT, DEFAULT_ORDER_NUMBER, DEFAULT_APP_VISIBILITY);
newAppPersistent.save();
}
}
public static boolean getAppVisibility(String packageName, String name) {
String identifier = AppPersistent.generateIdentifier(packageName, name);
AppPersistent appPersistent = Select.from(AppPersistent.class).where(Condition.prop(NamingHelper.toSQLNameDefault("mIdentifier")).eq(identifier)).first();
if (appPersistent != null) {
return appPersistent.isAppVisible();
} else {
return true;
}
}
public static void setAppVisibility(String packageName, String name, boolean mHideApp) {
String identifier = AppPersistent.generateIdentifier(packageName, name);
AppPersistent appPersistent = Select.from(AppPersistent.class).where(Condition.prop(NamingHelper.toSQLNameDefault("mIdentifier")).eq(identifier)).first();
if (appPersistent != null) {
appPersistent.setAppVisible(mHideApp);
appPersistent.save();
} else {
AppPersistent newAppPersistent = new AppPersistent(packageName, name, DEFAULT_OPEN_COUNT, DEFAULT_ORDER_NUMBER, mHideApp);
newAppPersistent.save();
}
}
public static long getAppOpenCount(String packageName, String name) {
String identifier = AppPersistent.generateIdentifier(packageName, name);
AppPersistent appPersistent = Select.from(AppPersistent.class).where(Condition.prop(NamingHelper.toSQLNameDefault("mIdentifier")).eq(identifier)).first();
if (appPersistent != null) {
return appPersistent.getOpenCount();
} else {
return 0;
}
}
}
================================================
FILE: app/src/main/java/nickrout/lenslauncher/model/Grid.java
================================================
package nickrout.lenslauncher.model;
/**
* Created by nickrout on 2016/04/02.
*/
public class Grid {
private int mItemCount;
private int mItemCountHorizontal;
private int mItemCountVertical;
private float mItemSize;
private float mSpacingHorizontal;
private float mSpacingVertical;
public Grid() {}
public int getItemCount() {
return mItemCount;
}
public void setItemCount(int itemCount) {
mItemCount = itemCount;
}
public int getItemCountHorizontal() {
return mItemCountHorizontal;
}
public void setItemCountHorizontal(int itemCountHorizontal) {
mItemCountHorizontal = itemCountHorizontal;
}
public int getItemCountVertical() {
return mItemCountVertical;
}
public void setItemCountVertical(int itemCountVertical) {
mItemCountVertical = itemCountVertical;
}
public float getItemSize() {
return mItemSize;
}
public void setItemSize(float itemSize) {
mItemSize = itemSize;
}
public float getSpacingHorizontal() {
return mSpacingHorizontal;
}
public void setSpacingHorizontal(float spacingHorizontal) {
mSpacingHorizontal = spacingHorizontal;
}
public float getSpacingVertical() {
return mSpacingVertical;
}
public void setSpacingVertical(float spacingVertical) {
mSpacingVertical = spacingVertical;
}
@Override
public String toString() {
return "Grid{" +
"mItemCount=" + mItemCount +
", mItemCountHorizontal=" + mItemCountHorizontal +
", mItemCountVertical=" + mItemCountVertical +
", mItemSize=" + mItemSize +
", mSpacingHorizontal=" + mSpacingHorizontal +
", mSpacingVertical=" + mSpacingVertical +
'}';
}
}
================================================
FILE: app/src/main/java/nickrout/lenslauncher/ui/AboutActivity.java
================================================
package nickrout.lenslauncher.ui;
import android.animation.Animator;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.CollapsingToolbarLayout;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.Toolbar;
import android.text.Html;
import android.text.method.LinkMovementMethod;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewAnimationUtils;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.Observable;
import java.util.Observer;
import butterknife.BindView;
import butterknife.ButterKnife;
import nickrout.lenslauncher.R;
import nickrout.lenslauncher.background.NightModeObservable;
/**
* Created by nickrout on 2016/04/06.
*/
public class AboutActivity extends BaseActivity implements Observer {
private static final String TAG = "AboutActivity";
@BindView(R.id.text_view_about)
TextView mTextViewAbout;
@BindView(R.id.backdrop)
ImageView mImageAbout;
@BindView(R.id.collapsing_toolbar)
CollapsingToolbarLayout mCollapsingToolbar;
@BindView(R.id.toolbar)
Toolbar mToolbar;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_about);
ButterKnife.bind(this);
setSupportActionBar(mToolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mCollapsingToolbar.setExpandedTitleColor(ContextCompat.getColor(this, R.color.colorTransparent));
setupViews();
mImageAbout.postDelayed(new Runnable() {
@Override
public void run() {
circularRevealAboutImage();
}
}, 150);
NightModeObservable.getInstance().addObserver(this);
}
private void circularRevealAboutImage() {
if (mImageAbout != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
int cx = mImageAbout.getWidth() / 2;
int cy = mImageAbout.getHeight() / 2;
float finalRadius = (float) Math.hypot(cx, cy);
Animator anim =
ViewAnimationUtils.createCircularReveal(mImageAbout, cx, cy, 0, finalRadius);
mImageAbout.setVisibility(View.VISIBLE);
anim.start();
} else {
mImageAbout.setVisibility(View.VISIBLE);
}
}
}
private void setupViews() {
mTextViewAbout.setText(Html.fromHtml(getString(R.string.about)));
mTextViewAbout.setMovementMethod(LinkMovementMethod.getInstance());
}
@Override
public void onBackPressed() {
finish();
}
@Override
public void finish() {
super.finish();
overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void update(Observable observable, Object o) {
if (observable instanceof NightModeObservable) {
updateNightMode();
}
}
}
================================================
FILE: app/src/main/java/nickrout/lenslauncher/ui/AppsFragment.java
================================================
package nickrout.lenslauncher.ui;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import butterknife.BindView;
import butterknife.ButterKnife;
import me.zhanghai.android.materialprogressbar.MaterialProgressBar;
import nickrout.lenslauncher.R;
import nickrout.lenslauncher.adapter.AppRecyclerAdapter;
import nickrout.lenslauncher.model.App;
import nickrout.lenslauncher.util.AppSorter;
import nickrout.lenslauncher.AppsSingleton;
import nickrout.lenslauncher.background.BroadcastReceivers;
import nickrout.lenslauncher.util.Settings;
/**
* Created by nicholasrout on 2016/06/08.
*/
public class AppsFragment extends Fragment implements SettingsActivity.AppsInterface {
private static final String TAG = "AppsFragment";
@BindView(R.id.recycler_apps)
RecyclerView mRecycler;
@BindView(R.id.progress_apps)
MaterialProgressBar mProgress;
private Settings mSettings;
private AppRecyclerAdapter mAppRecyclerAdapter;
private int mScrolledItemIndex;
public AppsFragment() {
}
public static AppsFragment newInstance() {
AppsFragment appsFragment = new AppsFragment();
// Include potential bundle extras here
return appsFragment;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_apps, container, false);
ButterKnife.bind(this, view);
mSettings = new Settings(getActivity());
setupRecycler(AppsSingleton.getInstance().getApps());
return view;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (getActivity() != null && getActivity() instanceof SettingsActivity) {
((SettingsActivity) getActivity()).setAppsInterface(this);
}
}
private void sendEditAppsBroadcast() {
if (getActivity() == null) {
return;
}
Intent editAppsIntent = new Intent(getActivity(), BroadcastReceivers.AppsEditedReceiver.class);
getActivity().sendBroadcast(editAppsIntent);
}
private void setupRecycler(ArrayList apps) {
if (getActivity() == null || apps.size() == 0) {
return;
}
if (mRecycler.getLayoutManager() != null) {
mScrolledItemIndex = ((LinearLayoutManager) mRecycler.getLayoutManager()).findFirstCompletelyVisibleItemPosition();
}
mProgress.setVisibility(View.INVISIBLE);
mRecycler.setVisibility(View.VISIBLE);
mAppRecyclerAdapter = new AppRecyclerAdapter(getActivity(), apps);
mRecycler.setAdapter(mAppRecyclerAdapter);
mRecycler.setLayoutManager(new GridLayoutManager(getActivity(), getResources().getInteger(R.integer.columns_apps)));
mRecycler.setItemAnimator(new DefaultItemAnimator());
mRecycler.scrollToPosition(mScrolledItemIndex);
mScrolledItemIndex = 0;
}
@Override
public void onDefaultsReset() {
if (mSettings.getSortType() != AppSorter.SortType.values()[Settings.DEFAULT_SORT_TYPE]) {
mSettings.save(Settings.KEY_SORT_TYPE, Settings.DEFAULT_SORT_TYPE);
sendEditAppsBroadcast();
}
}
@Override
public void onAppsUpdated(ArrayList apps) {
setupRecycler(apps);
}
}
================================================
FILE: app/src/main/java/nickrout/lenslauncher/ui/BaseActivity.java
================================================
package nickrout.lenslauncher.ui;
import android.app.ActivityManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.LayoutRes;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import nickrout.lenslauncher.R;
import nickrout.lenslauncher.util.Settings;
/**
* Created by nickrout on 2016/04/05.
*/
public class BaseActivity extends AppCompatActivity {
protected Settings mSettings;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
mSettings = new Settings(this);
if (savedInstanceState == null) {
updateNightMode();
}
super.onCreate(savedInstanceState);
}
@Override
public void setContentView(@LayoutRes int layoutResID) {
super.setContentView(layoutResID);
setTaskDescription();
}
private void setTaskDescription() {
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Bitmap appIconBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
ActivityManager.TaskDescription taskDescription = new ActivityManager.TaskDescription(
getString(R.string.app_name),
appIconBitmap,
ContextCompat.getColor(getBaseContext(), R.color.colorPrimaryDark));
setTaskDescription(taskDescription);
}
}
protected void updateNightMode() {
if (mSettings == null) {
mSettings = new Settings(this);
}
getDelegate().setLocalNightMode(mSettings.getNightMode());
}
}
================================================
FILE: app/src/main/java/nickrout/lenslauncher/ui/FakeLauncherActivity.java
================================================
package nickrout.lenslauncher.ui;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import nickrout.lenslauncher.R;
public class FakeLauncherActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fake_launcher);
}
}
================================================
FILE: app/src/main/java/nickrout/lenslauncher/ui/HomeActivity.java
================================================
package nickrout.lenslauncher.ui;
import android.annotation.TargetApi;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import java.util.ArrayList;
import java.util.Observable;
import java.util.Observer;
import butterknife.BindView;
import butterknife.ButterKnife;
import me.zhanghai.android.materialprogressbar.MaterialProgressBar;
import nickrout.lenslauncher.R;
import nickrout.lenslauncher.background.BackgroundChangedObservable;
import nickrout.lenslauncher.background.NightModeObservable;
import nickrout.lenslauncher.background.VisibilityChangedObservable;
import nickrout.lenslauncher.model.App;
import nickrout.lenslauncher.model.AppPersistent;
import nickrout.lenslauncher.AppsSingleton;
import nickrout.lenslauncher.background.LoadedObservable;
/**
* Created by nickrout on 2016/04/02.
*/
public class HomeActivity extends BaseActivity implements Observer {
private final static String TAG = "HomeActivity";
@BindView(R.id.lens_view_apps)
LensView mLensView;
@BindView(R.id.progress_home)
MaterialProgressBar mProgress;
private PackageManager mPackageManager;
private ArrayList mApps;
private ArrayList mAppIcons;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
ButterKnife.bind(this);
mPackageManager = getPackageManager();
mLensView.setPackageManager(mPackageManager);
mLensView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
assignApps(AppsSingleton.getInstance().getApps(), AppsSingleton.getInstance().getAppIcons());
LoadedObservable.getInstance().addObserver(this);
VisibilityChangedObservable.getInstance().addObserver(this);
BackgroundChangedObservable.getInstance().addObserver(this);
NightModeObservable.getInstance().addObserver(this);
}
@Override
protected void onResume() {
super.onResume();
setupTransparentSystemBarsForLollipop();
}
/**
* Sets up transparent navigation and status bars in Lollipop.
* This method is a no-op for other platform versions.
*/
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void setupTransparentSystemBarsForLollipop() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = getWindow();
window.getAttributes().systemUiVisibility |=
(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
| WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Color.TRANSPARENT);
window.setNavigationBarColor(Color.TRANSPARENT);
}
}
private void setBackground() {
mLensView.invalidate();
}
private void assignApps(ArrayList apps, ArrayList appIcons) {
if (apps.size() == 0 || appIcons.size() == 0) {
return;
}
mProgress.setVisibility(View.INVISIBLE);
mLensView.setVisibility(View.VISIBLE);
mApps = apps;
mAppIcons = appIcons;
removeHiddenApps();
mLensView.setApps(mApps, mAppIcons);
}
private void removeHiddenApps() {
for (int i = 0; i < mApps.size(); i++) {
if (!AppPersistent.getAppVisibility(
mApps.get(i).getPackageName().toString(), mApps.get(i).getName().toString())) {
mApps.remove(i);
mAppIcons.remove(i);
i--;
}
}
}
@Override
public void onBackPressed() {
// Do Nothing
}
@Override
protected void onDestroy() {
LoadedObservable.getInstance().deleteObserver(this);
super.onDestroy();
}
@Override
public void update(Observable observable, Object data) {
if (observable instanceof LoadedObservable || observable instanceof VisibilityChangedObservable) {
assignApps(AppsSingleton.getInstance().getApps(), AppsSingleton.getInstance().getAppIcons());
} else if (observable instanceof BackgroundChangedObservable) {
setBackground();
} else if (observable instanceof NightModeObservable) {
updateNightMode();
}
}
}
================================================
FILE: app/src/main/java/nickrout/lenslauncher/ui/LensFragment.java
================================================
package nickrout.lenslauncher.ui;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.AppCompatSeekBar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.SeekBar;
import android.widget.TextView;
import butterknife.BindView;
import butterknife.ButterKnife;
import nickrout.lenslauncher.R;
import nickrout.lenslauncher.util.Settings;
/**
* Created by nicholasrout on 2016/06/08.
*/
public class LensFragment extends Fragment implements SettingsActivity.LensInterface {
private static final String TAG = "LensFragment";
@BindView(R.id.lens_view_settings)
LensView mLensView;
@BindView(R.id.seek_bar_min_icon_size)
AppCompatSeekBar mMinIconSize;
@BindView(R.id.value_min_icon_size)
TextView mValueMinIconSize;
@BindView(R.id.seek_bar_distortion_factor)
AppCompatSeekBar mDistortionFactor;
@BindView(R.id.value_distortion_factor)
TextView mValueDistortionFactor;
@BindView(R.id.seek_bar_scale_factor)
AppCompatSeekBar mScaleFactor;
@BindView(R.id.value_scale_factor)
TextView mValueScaleFactor;
@BindView(R.id.seek_bar_animation_time)
AppCompatSeekBar mAnimationTime;
@BindView(R.id.value_animation_time)
TextView mValueAnimationTime;
private Settings mSettings;
public LensFragment() {
}
public static LensFragment newInstance() {
LensFragment lensFragment = new LensFragment();
// Include potential bundle extras here
return lensFragment;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_lens, container, false);
ButterKnife.bind(this, view);
mSettings = new Settings(getActivity());
setupViews();
assignValues();
return view;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (getActivity() != null && getActivity() instanceof SettingsActivity) {
((SettingsActivity) getActivity()).setLensInterface(this);
}
}
private void setupViews() {
mLensView.setDrawType(LensView.DrawType.CIRCLES);
mMinIconSize.setMax(Settings.MAX_ICON_SIZE);
mMinIconSize.setOnSeekBarChangeListener(new AppCompatSeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
int appropriateProgress = progress + (int) Settings.MIN_ICON_SIZE;
String minIconSize = appropriateProgress + "dp";
mValueMinIconSize.setText(minIconSize);
mSettings.save(Settings.KEY_ICON_SIZE, (float) appropriateProgress);
mLensView.invalidate();
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
mDistortionFactor.setMax(Settings.MAX_DISTORTION_FACTOR);
mDistortionFactor.setOnSeekBarChangeListener(new AppCompatSeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
float appropriateProgress = (float) progress / 2.0f + Settings.MIN_DISTORTION_FACTOR;
String distortionFactor = appropriateProgress + "";
mValueDistortionFactor.setText(distortionFactor);
mSettings.save(Settings.KEY_DISTORTION_FACTOR, appropriateProgress);
mLensView.invalidate();
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
mScaleFactor.setMax(Settings.MAX_SCALE_FACTOR);
mScaleFactor.setOnSeekBarChangeListener(new AppCompatSeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
float appropriateProgress = (float) progress / 5.0f + Settings.MIN_SCALE_FACTOR;
String scaleFactor = appropriateProgress + "";
mValueScaleFactor.setText(scaleFactor);
mSettings.save(Settings.KEY_SCALE_FACTOR, appropriateProgress);
mLensView.invalidate();
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
mAnimationTime.setMax(Settings.MAX_ANIMATION_TIME);
mAnimationTime.setOnSeekBarChangeListener(new AppCompatSeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
long appropriateProgress = (long) progress / 2 + Settings.MIN_ANIMATION_TIME;
String animationTime = appropriateProgress + "ms";
mValueAnimationTime.setText(animationTime);
mSettings.save(Settings.KEY_ANIMATION_TIME, appropriateProgress);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
private void assignValues() {
mMinIconSize.setProgress((int) mSettings.getFloat(Settings.KEY_ICON_SIZE) - (int) Settings.MIN_ICON_SIZE);
String minIconSize = (int) mSettings.getFloat(Settings.KEY_ICON_SIZE) + "dp";
mValueMinIconSize.setText(minIconSize);
mDistortionFactor.setProgress((int) (2.0f * (mSettings.getFloat(Settings.KEY_DISTORTION_FACTOR) - Settings.MIN_DISTORTION_FACTOR)));
String distortionFactor = mSettings.getFloat(Settings.KEY_DISTORTION_FACTOR) + "";
mValueDistortionFactor.setText(distortionFactor);
mScaleFactor.setProgress((int) (5.0f * (mSettings.getFloat(Settings.KEY_SCALE_FACTOR) - Settings.MIN_SCALE_FACTOR)));
String scaleFactor = mSettings.getFloat(Settings.KEY_SCALE_FACTOR) + "";
mValueScaleFactor.setText(scaleFactor);
mAnimationTime.setProgress((int) (2 * (mSettings.getLong(Settings.KEY_ANIMATION_TIME) - Settings.MIN_ANIMATION_TIME)));
String animationTime = mSettings.getLong(Settings.KEY_ANIMATION_TIME) + "ms";
mValueAnimationTime.setText(animationTime);
}
@Override
public void onDefaultsReset() {
resetToDefault();
assignValues();
}
private void resetToDefault() {
mSettings.save(Settings.KEY_ICON_SIZE, Settings.DEFAULT_ICON_SIZE);
mSettings.save(Settings.KEY_DISTORTION_FACTOR, Settings.DEFAULT_DISTORTION_FACTOR);
mSettings.save(Settings.KEY_SCALE_FACTOR, Settings.DEFAULT_SCALE_FACTOR);
mSettings.save(Settings.KEY_ANIMATION_TIME, Settings.DEFAULT_ANIMATION_TIME);
}
}
================================================
FILE: app/src/main/java/nickrout/lenslauncher/ui/LensView.java
================================================
package nickrout.lenslauncher.ui;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.graphics.drawable.NinePatchDrawable;
import android.os.Build;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.Transformation;
import java.util.ArrayList;
import nickrout.lenslauncher.R;
import nickrout.lenslauncher.model.App;
import nickrout.lenslauncher.model.AppPersistent;
import nickrout.lenslauncher.model.Grid;
import nickrout.lenslauncher.util.AppUtil;
import nickrout.lenslauncher.util.LensCalculator;
import nickrout.lenslauncher.util.Settings;
/**
* Created by nickrout on 2016/04/02.
*/
public class LensView extends View {
private static final String TAG = "LensView";
private Paint mPaintIcons;
private Paint mPaintCircles;
private Paint mPaintTouchSelection;
private Paint mPaintText;
private Paint mPaintNewAppTag;
private float mTouchX = -Float.MAX_VALUE;
private float mTouchY = -Float.MAX_VALUE;
private boolean mInsideRect = false;
private RectF mRectToSelect = new RectF(0, 0, 0, 0);
private boolean mMustVibrate = true;
private int mSelectIndex;
private ArrayList mApps;
private ArrayList mAppIcons;
private PackageManager mPackageManager;
private float mAnimationMultiplier = 0.0f;
private boolean mAnimationHiding = false;
private int mNumberOfCircles;
private float mTouchSlop;
private boolean mMoving;
private Settings mSettings;
private NinePatchDrawable mWorkspaceBackgroundDrawable;
private Rect mInsets = new Rect(0, 0, 0, 0);
public enum DrawType {
APPS,
CIRCLES
}
private DrawType mDrawType;
public void setDrawType(DrawType drawType) {
mDrawType = drawType;
invalidate();
}
public LensView(Context context) {
super(context);
init();
}
public LensView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public LensView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public void setApps(ArrayList apps, ArrayList appIcons) {
mApps = apps;
mAppIcons = appIcons;
invalidate();
}
public void setPackageManager(PackageManager packageManager) {
mPackageManager = packageManager;
}
private void init() {
mApps = new ArrayList<>();
mAppIcons = new ArrayList<>();
mDrawType = DrawType.APPS;
setBackgroundColor(ContextCompat.getColor(getContext(), R.color.colorTransparent));
mSettings = new Settings(getContext());
setupPaints();
mWorkspaceBackgroundDrawable = (NinePatchDrawable) ContextCompat.getDrawable(getContext(), R.drawable.workspace_bg);
mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
}
@Override
protected boolean fitSystemWindows(Rect insets) {
mInsets = insets;
return true;
}
private void setupPaints() {
mPaintIcons = new Paint();
mPaintIcons.setAntiAlias(true);
mPaintIcons.setStyle(Paint.Style.FILL);
mPaintIcons.setFilterBitmap(true);
mPaintIcons.setDither(true);
mPaintCircles = new Paint();
mPaintCircles.setAntiAlias(true);
mPaintCircles.setStyle(Paint.Style.FILL);
mPaintCircles.setColor(ContextCompat.getColor(getContext(), R.color.colorCircles));
mPaintTouchSelection = new Paint();
mPaintTouchSelection.setAntiAlias(true);
mPaintTouchSelection.setStyle(Paint.Style.STROKE);
mPaintTouchSelection.setColor(Color.parseColor(mSettings.getString(Settings.KEY_HIGHLIGHT_COLOR)));
mPaintTouchSelection.setStrokeWidth(getResources().getDimension(R.dimen.stroke_width_touch_selection));
mPaintText = new Paint();
mPaintText.setAntiAlias(true);
mPaintText.setStyle(Paint.Style.FILL);
mPaintText.setColor(ContextCompat.getColor(getContext(), R.color.colorWhite));
mPaintText.setTextSize(getResources().getDimension(R.dimen.text_size_lens));
mPaintText.setTextAlign(Paint.Align.CENTER);
mPaintText.setTypeface(Typeface.createFromAsset(getContext().getAssets(),"fonts/RobotoCondensed-Regular.ttf"));
mPaintNewAppTag = new Paint();
mPaintNewAppTag.setAntiAlias(true);
mPaintNewAppTag.setStyle(Paint.Style.FILL);
mPaintNewAppTag.setColor(Color.parseColor(mSettings.getString(Settings.KEY_HIGHLIGHT_COLOR)));
mPaintNewAppTag.setDither(true);
mPaintNewAppTag.setShadowLayer(getResources().getDimension(R.dimen.shadow_text),
getResources().getDimension(R.dimen.shadow_text),
getResources().getDimension(R.dimen.shadow_text),
ContextCompat.getColor(getContext(), R.color.colorShadow));
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mDrawType == DrawType.APPS) {
if (mSettings.getString(Settings.KEY_BACKGROUND).equals("Color")) {
canvas.drawColor(Color.parseColor(mSettings.getString(Settings.KEY_BACKGROUND_COLOR)));
}
mPaintNewAppTag.setColor(Color.parseColor(mSettings.getString(Settings.KEY_HIGHLIGHT_COLOR)));
drawWorkspaceBackground(canvas);
if (mApps != null) {
drawGrid(canvas, mApps.size());
}
if (mSettings.getBoolean(Settings.KEY_SHOW_TOUCH_SELECTION)) {
drawTouchSelection(canvas);
}
} else if (mDrawType == DrawType.CIRCLES) {
mNumberOfCircles = 100;
mTouchX = getWidth() / 2;
mTouchY = getHeight() / 2;
drawGrid(canvas, mNumberOfCircles);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (mDrawType == DrawType.APPS) {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN: {
if (event.getX() < 0.0f) {
mTouchX = 0.0f;
} else {
mTouchX = event.getX();
}
if (event.getY() < 0.0f) {
mTouchY = 0.0f;
} else {
mTouchY = event.getY();
}
mSelectIndex = -1;
mMoving = false;
invalidate();
return true;
}
case MotionEvent.ACTION_MOVE: {
if (!mMoving && Math.sqrt(Math.pow(event.getX() - mTouchX, 2) + Math.pow(event.getY() - mTouchY, 2)) > mTouchSlop) {
mMoving = true;
LensAnimation lensShowAnimation = new LensAnimation(true);
startAnimation(lensShowAnimation);
}
if (!mMoving) {
return true;
}
if (event.getX() < 0.0f) {
mTouchX = 0.0f;
} else {
mTouchX = event.getX();
}
if (event.getY() < 0.0f) {
mTouchY = 0.0f;
} else {
mTouchY = event.getY();
}
invalidate();
return true;
}
case MotionEvent.ACTION_UP: {
performLaunchVibration();
if (mMoving) {
LensAnimation lensHideAnimation = new LensAnimation(false);
startAnimation(lensHideAnimation);
mMoving = false;
} else {
launchApp();
}
return true;
}
default: {
return super.onTouchEvent(event);
}
}
}
return super.onTouchEvent(event);
}
private void drawWorkspaceBackground(Canvas canvas) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Rect rect = new Rect(0, 0, getWidth(), getHeight());
mWorkspaceBackgroundDrawable.setBounds(rect);
mWorkspaceBackgroundDrawable.draw(canvas);
}
}
private void drawTouchSelection(Canvas canvas) {
canvas.drawCircle(mTouchX, mTouchY, getResources().getDimension(R.dimen.radius_touch_selection), mPaintTouchSelection);
}
private void drawGrid(Canvas canvas, int itemCount) {
Grid grid = LensCalculator.calculateGrid(
getContext(),
getWidth() - (mInsets.left + mInsets.right),
getHeight() - (mInsets.top + mInsets.bottom),
itemCount);
mInsideRect = false;
int selectIndex = -1;
mRectToSelect = null;
for (float y = 0.0f; y < (float) grid.getItemCountVertical(); y += 1.0f) {
for (float x = 0.0f; x < (float) grid.getItemCountHorizontal(); x += 1.0f) {
int currentItem = (int) (y * ((float) grid.getItemCountHorizontal()) + (x + 1.0f));
int currentIndex = currentItem - 1;
if (currentItem <= grid.getItemCount() || mDrawType == DrawType.CIRCLES) {
RectF rect = new RectF();
rect.left = mInsets.left + (x + 1.0f) * grid.getSpacingHorizontal() + x * grid.getItemSize();
rect.top = mInsets.top + (y + 1.0f) * grid.getSpacingVertical() + y * grid.getItemSize();
rect.right = rect.left + grid.getItemSize();
rect.bottom = rect.top + grid.getItemSize();
float animationMultiplier;
if (mDrawType == DrawType.APPS) {
animationMultiplier = mAnimationMultiplier;
} else {
animationMultiplier = 1.0f;
}
if (mTouchX >= 0 && mTouchY >= 0) {
float shiftedCenterX = LensCalculator.shiftPoint(getContext(), mTouchX, rect.centerX(), getWidth(), animationMultiplier);
float shiftedCenterY = LensCalculator.shiftPoint(getContext(), mTouchY, rect.centerY(), getHeight(), animationMultiplier);
float scaledCenterX = LensCalculator.scalePoint(getContext(), mTouchX, rect.centerX(), rect.width(), getWidth(), animationMultiplier);
float scaledCenterY = LensCalculator.scalePoint(getContext(), mTouchY, rect.centerY(), rect.height(), getHeight(), animationMultiplier);
float newSize = LensCalculator.calculateSquareScaledSize(scaledCenterX, shiftedCenterX, scaledCenterY, shiftedCenterY);
if (mSettings.getFloat(Settings.KEY_DISTORTION_FACTOR) > 0.0f && mSettings.getFloat(Settings.KEY_SCALE_FACTOR) > 0.0f) {
rect = LensCalculator.calculateRect(shiftedCenterX, shiftedCenterY, newSize);
} else if (mSettings.getFloat(Settings.KEY_DISTORTION_FACTOR) > 0.0f && mSettings.getFloat(Settings.KEY_SCALE_FACTOR) == 0.0f) {
rect = LensCalculator.calculateRect(shiftedCenterX, shiftedCenterY, rect.width());
}
if (LensCalculator.isInsideRect(mTouchX, mTouchY, rect)) {
mInsideRect = true;
selectIndex = currentIndex;
mRectToSelect = rect;
}
}
if (mDrawType == DrawType.APPS) {
drawAppIcon(canvas, rect, currentIndex);
} else if (mDrawType == DrawType.CIRCLES) {
drawCircle(canvas, rect);
}
}
}
}
if (selectIndex >= 0) {
if (selectIndex != mSelectIndex) {
mMustVibrate = true;
} else {
mMustVibrate = false;
}
} else {
mMustVibrate = false;
}
if (!mAnimationHiding) {
mSelectIndex = selectIndex;
}
if (mDrawType == DrawType.APPS) {
performHoverVibration();
}
if (mRectToSelect != null && mDrawType == DrawType.APPS && mApps != null && mSelectIndex >= 0) {
drawAppName(canvas, mRectToSelect);
}
}
private void drawAppIcon(Canvas canvas, RectF rect, int index) {
if (index < mAppIcons.size()) {
Bitmap appIcon = mAppIcons.get(index);
Rect src = new Rect(0, 0, appIcon.getWidth(), appIcon.getHeight());
canvas.drawBitmap(appIcon, src, rect, mPaintIcons);
/**
* Check if the app was installed Settings.SHOW_NEW_APP_TAG_DURATION ago, and if it has been opened since.
* If not, drawNewAppTag()
*/
if ((mApps.get(index).getInstallDate() >= (System.currentTimeMillis() - Settings.SHOW_NEW_APP_TAG_DURATION)
&& (AppPersistent.getAppOpenCount(
mApps.get(index).getPackageName().toString(), mApps.get(index).getName().toString()) == 0))) {
drawNewAppTag(canvas, rect);
}
}
}
private void drawCircle(Canvas canvas, RectF rect) {
canvas.drawCircle(rect.centerX(), rect.centerY(), rect.width() / 2.0f, mPaintCircles);
}
private void drawAppName(Canvas canvas, RectF rect) {
if (mSettings.getBoolean(Settings.KEY_SHOW_NAME_APP_HOVER) && mMoving) {
canvas.drawText((String) mApps.get(mSelectIndex).getLabel(),
rect.centerX(),
rect.top - getResources().getDimension(R.dimen.margin_lens_text),
mPaintText);
}
}
private void drawNewAppTag(Canvas canvas, RectF rect) {
if (mSettings.getBoolean(Settings.KEY_SHOW_NEW_APP_TAG)) {
canvas.drawCircle(rect.centerX(),
rect.bottom + getResources().getDimension(R.dimen.margin_new_app_tag),
getResources().getDimension(R.dimen.radius_new_app_tag),
mPaintNewAppTag);
}
}
private void performHoverVibration() {
if (mInsideRect) {
if (mMustVibrate) {
if (mSettings.getBoolean(Settings.KEY_VIBRATE_APP_HOVER) && !mAnimationHiding) {
performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
}
mMustVibrate = false;
}
} else {
mMustVibrate = true;
}
}
private void performLaunchVibration() {
if (mInsideRect) {
if (mSettings.getBoolean(Settings.KEY_VIBRATE_APP_LAUNCH)) {
performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
}
}
}
private void launchApp() {
if (mPackageManager != null && mApps != null && mSelectIndex >= 0) {
AppUtil.launchComponent(
getContext(),
(String) mApps.get(mSelectIndex).getPackageName(),
(String) mApps.get(mSelectIndex).getName(),
this,
mRectToSelect == null ? null :
new Rect((int) mRectToSelect.left, (int) mRectToSelect.top,
(int) mRectToSelect.right, (int) mRectToSelect.bottom));
}
}
private class LensAnimation extends Animation {
private boolean mShow;
public LensAnimation(boolean show) {
mShow = show;
setInterpolator(new AccelerateDecelerateInterpolator());
setDuration(mSettings.getLong(Settings.KEY_ANIMATION_TIME));
setAnimationListener(new AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
if (!mShow) {
mAnimationHiding = true;
mPaintText.clearShadowLayer();
} else {
mAnimationHiding = false;
}
}
@Override
public void onAnimationEnd(Animation animation) {
if (!mShow) {
launchApp();
mTouchX = -Float.MAX_VALUE;
mTouchY = -Float.MAX_VALUE;
mAnimationHiding = false;
} else {
mPaintText.setShadowLayer(
getResources().getDimension(R.dimen.shadow_text),
getResources().getDimension(R.dimen.shadow_text),
getResources().getDimension(R.dimen.shadow_text),
ContextCompat.getColor(getContext(), R.color.colorShadow));
}
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
super.applyTransformation(interpolatedTime, t);
if (mShow) {
mAnimationMultiplier = interpolatedTime;
mPaintTouchSelection.setColor(Color.parseColor(mSettings.getString(Settings.KEY_HIGHLIGHT_COLOR)));
mPaintTouchSelection.setAlpha((int) (255.0f * interpolatedTime));
mPaintText.setAlpha((int) (255.0f * interpolatedTime));
} else {
mAnimationMultiplier = 1.0f - interpolatedTime;
mPaintTouchSelection.setColor(Color.parseColor(mSettings.getString(Settings.KEY_HIGHLIGHT_COLOR)));
mPaintTouchSelection.setAlpha((int) (255.0f * (1.0f - interpolatedTime)));
mPaintText.setAlpha((int) (255.0f * (1.0f - interpolatedTime)));
}
postInvalidate();
}
}
}
================================================
FILE: app/src/main/java/nickrout/lenslauncher/ui/SettingsActivity.java
================================================
package nickrout.lenslauncher.ui;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import com.afollestad.materialdialogs.MaterialDialog;
import com.afollestad.materialdialogs.color.ColorChooserDialog;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import nickrout.lenslauncher.R;
import nickrout.lenslauncher.background.NightModeObservable;
import nickrout.lenslauncher.model.App;
import nickrout.lenslauncher.util.AppSorter;
import nickrout.lenslauncher.AppsSingleton;
import nickrout.lenslauncher.background.BroadcastReceivers;
import nickrout.lenslauncher.util.IconPackManager;
import nickrout.lenslauncher.util.LauncherUtil;
import nickrout.lenslauncher.background.LoadedObservable;
import nickrout.lenslauncher.util.NightModeUtil;
import nickrout.lenslauncher.util.Settings;
/**
* Created by nicholasrout on 2016/06/07.
*/
public class SettingsActivity extends BaseActivity
implements Observer, ColorChooserDialog.ColorCallback {
private static final String TAG = "SettingsActivity";
private static final String COLOR_TAG_BACKGROUND = "BackgroundColor";
private static final String COLOR_TAG_HIGHLIGHT = "HighlightColor";
@BindView(R.id.toolbar)
Toolbar mToolbar;
@BindView(R.id.tabs)
TabLayout mTabLayout;
@BindView(R.id.viewpager)
ViewPager mViewPager;
@BindView(R.id.fab_sort)
FloatingActionButton mSortFab;
@OnClick(R.id.fab_sort)
public void onSortClicked() {
showSortTypeDialog();
}
private FragmentPagerAdapter mPagerAdapter;
private ArrayList mApps;
private MaterialDialog mSortTypeDialog;
private MaterialDialog mIconPackDialog;
private MaterialDialog mNightModeDialog;
private MaterialDialog mBackgroundDialog;
private ColorChooserDialog mBackgroundColorDialog;
private ColorChooserDialog mHighlightColorDialog;
public interface LensInterface {
void onDefaultsReset();
}
private LensInterface mLensInterface;
public void setLensInterface(LensInterface lensInterface) {
mLensInterface = lensInterface;
}
public interface AppsInterface {
void onDefaultsReset();
void onAppsUpdated(ArrayList apps);
}
private AppsInterface mAppsInterface;
public void setAppsInterface(AppsInterface appsInterface) {
mAppsInterface = appsInterface;
}
public interface SettingsInterface {
void onDefaultsReset();
void onValuesUpdated();
}
private SettingsInterface mSettingsInterface;
public void setSettingsInterface(SettingsInterface settingsInterface) {
mSettingsInterface = settingsInterface;
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
ButterKnife.bind(this);
mSortFab.hide();
setSupportActionBar(mToolbar);
mPagerAdapter = new FragmentPagerAdapter(getSupportFragmentManager(), SettingsActivity.this);
mViewPager.setAdapter(mPagerAdapter);
mTabLayout.setupWithViewPager(mViewPager);
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
switch (position) {
case 1:
mSortFab.show();
break;
default:
mSortFab.hide();
break;
}
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
mApps = AppsSingleton.getInstance().getApps();
LoadedObservable.getInstance().addObserver(this);
NightModeObservable.getInstance().addObserver(this);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_settings, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_item_show_apps:
if (LauncherUtil.isLauncherDefault(getApplication())) {
Intent homeIntent = new Intent(Intent.ACTION_MAIN);
homeIntent.addCategory(Intent.CATEGORY_HOME);
startActivity(homeIntent);
} else {
Intent homeIntent = new Intent(SettingsActivity.this, HomeActivity.class);
startActivity(homeIntent);
}
overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
return true;
case R.id.menu_item_about:
Intent aboutIntent = new Intent(SettingsActivity.this, AboutActivity.class);
startActivity(aboutIntent);
overridePendingTransition(R.anim.slide_in_left, R.anim.slide_out_right);
return true;
case R.id.menu_item_reset_default_settings:
switch (mViewPager.getCurrentItem()) {
case 0:
if (mLensInterface != null) {
mLensInterface.onDefaultsReset();
}
break;
case 1:
if (mAppsInterface != null) {
mAppsInterface.onDefaultsReset();
}
break;
case 2:
if (mSettingsInterface != null) {
mSettingsInterface.onDefaultsReset();
}
break;
}
Snackbar.make(mToolbar, getString(R.string.snackbar_reset_successful), Snackbar.LENGTH_LONG).show();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
public void update(Observable observable, Object data) {
if (observable instanceof LoadedObservable) {
mApps = AppsSingleton.getInstance().getApps();
if (mAppsInterface != null) {
mAppsInterface.onAppsUpdated(mApps);
}
} else if (observable instanceof NightModeObservable) {
updateNightMode();
}
}
private void sendUpdateAppsBroadcast() {
Intent refreshAppsIntent = new Intent(SettingsActivity.this, BroadcastReceivers.AppsUpdatedReceiver.class);
sendBroadcast(refreshAppsIntent);
}
private void sendEditAppsBroadcast() {
Intent editAppsIntent = new Intent(SettingsActivity.this, BroadcastReceivers.AppsEditedReceiver.class);
sendBroadcast(editAppsIntent);
}
private void sendBackgroundChangedBroadcast() {
Intent changeBackgroundIntent = new Intent(SettingsActivity.this, BroadcastReceivers.BackgroundChangedReceiver.class);
sendBroadcast(changeBackgroundIntent);
}
public void sendNightModeBroadcast() {
Intent nightModeIntent = new Intent(SettingsActivity.this, BroadcastReceivers.NightModeReceiver.class);
sendBroadcast(nightModeIntent);
}
private void showSortTypeDialog() {
final List sortTypes = new ArrayList<>(EnumSet.allOf(AppSorter.SortType.class));
final List sortTypeStrings = new ArrayList<>();
for (int i = 0; i < sortTypes.size(); i++) {
sortTypeStrings.add(getApplicationContext().getString(sortTypes.get(i).getDisplayNameResId()));
}
AppSorter.SortType selectedSortType = mSettings.getSortType();
int selectedIndex = sortTypes.indexOf(selectedSortType);
mSortTypeDialog = new MaterialDialog.Builder(SettingsActivity.this)
.title(R.string.setting_sort_apps)
.items(sortTypeStrings)
.alwaysCallSingleChoiceCallback()
.itemsCallbackSingleChoice(selectedIndex, new MaterialDialog.ListCallbackSingleChoice() {
@Override
public boolean onSelection(MaterialDialog dialog, View view, int which, CharSequence text) {
mSettings.save(sortTypes.get(which));
sendEditAppsBroadcast();
return true;
}
})
.show();
}
public void showIconPackDialog() {
final ArrayList availableIconPacks =
new IconPackManager().getAvailableIconPacksWithIcons(true, getApplication());
final ArrayList iconPackNames = new ArrayList<>();
iconPackNames.add(getString(R.string.setting_default_icon_pack));
for (int i = 0; i < availableIconPacks.size(); i++) {
if (iconPackNames.size() > 0 && !iconPackNames.contains(availableIconPacks.get(i).mName)) {
iconPackNames.add(availableIconPacks.get(i).mName);
}
}
String selectedPackageName = mSettings.getString(Settings.KEY_ICON_PACK_LABEL_NAME);
int selectedIndex = iconPackNames.indexOf(selectedPackageName);
mIconPackDialog = new MaterialDialog.Builder(SettingsActivity.this)
.title(R.string.setting_icon_pack)
.items(iconPackNames)
.alwaysCallSingleChoiceCallback()
.itemsCallbackSingleChoice(selectedIndex, new MaterialDialog.ListCallbackSingleChoice() {
@Override
public boolean onSelection(MaterialDialog dialog, View view, int which, CharSequence text) {
mSettings.save(Settings.KEY_ICON_PACK_LABEL_NAME, iconPackNames.get(which));
if (mSettingsInterface != null) {
mSettingsInterface.onValuesUpdated();
}
sendUpdateAppsBroadcast();
return true;
}
})
.show();
}
public void showHomeLauncherChooser() {
LauncherUtil.resetPreferredLauncherAndOpenChooser(getApplicationContext());
}
public void showNightModeChooser() {
String[] availableNightModes = getResources().getStringArray(R.array.night_modes);
final ArrayList nightModes = new ArrayList<>();
for (int i = 0; i < availableNightModes.length; i++) {
nightModes.add(availableNightModes[i]);
}
String selectedNightMode = NightModeUtil.getNightModeDisplayName(mSettings.getNightMode());
int selectedIndex = nightModes.indexOf(selectedNightMode);
mNightModeDialog = new MaterialDialog.Builder(SettingsActivity.this)
.title(R.string.setting_night_mode)
.items(R.array.night_modes)
.alwaysCallSingleChoiceCallback()
.itemsCallbackSingleChoice(selectedIndex, new MaterialDialog.ListCallbackSingleChoice() {
@Override
public boolean onSelection(MaterialDialog dialog, View view, int which, CharSequence text) {
String selection = nightModes.get(which);
mSettings.save(Settings.KEY_NIGHT_MODE, NightModeUtil.getNightModeFromDisplayName(selection));
sendNightModeBroadcast();
if (mSettingsInterface != null) {
mSettingsInterface.onValuesUpdated();
}
dismissBackgroundDialog();
return true;
}
})
.show();
}
public void showBackgroundDialog() {
String[] availableBackgrounds = getResources().getStringArray(R.array.backgrounds);
final ArrayList backgroundNames = new ArrayList<>();
for (int i = 0; i < availableBackgrounds.length; i++) {
backgroundNames.add(availableBackgrounds[i]);
}
String selectedBackground = mSettings.getString(Settings.KEY_BACKGROUND);
int selectedIndex = backgroundNames.indexOf(selectedBackground);
mBackgroundDialog = new MaterialDialog.Builder(SettingsActivity.this)
.title(R.string.setting_background)
.items(R.array.backgrounds)
.alwaysCallSingleChoiceCallback()
.itemsCallbackSingleChoice(selectedIndex, new MaterialDialog.ListCallbackSingleChoice() {
@Override
public boolean onSelection(MaterialDialog dialog, View view, int which, CharSequence text) {
String selection = backgroundNames.get(which);
if (selection.equals("Wallpaper")) {
mSettings.save(Settings.KEY_BACKGROUND, selection);
sendBackgroundChangedBroadcast();
if (mSettingsInterface != null) {
mSettingsInterface.onValuesUpdated();
}
dismissBackgroundDialog();
showWallpaperPicker();
} else if (selection.equals("Color")) {
dismissBackgroundDialog();
showBackgroundColorDialog();
}
return true;
}
})
.show();
}
public void showWallpaperPicker() {
Intent intent = new Intent(Intent.ACTION_SET_WALLPAPER);
startActivity(Intent.createChooser(intent, "Select Wallpaper"));
}
public void showBackgroundColorDialog() {
mBackgroundColorDialog = new ColorChooserDialog.Builder(this, R.string.setting_background_color)
.titleSub(R.string.setting_background_color)
.accentMode(false)
.doneButton(com.afollestad.materialdialogs.commons.R.string.md_done_label)
.cancelButton(com.afollestad.materialdialogs.commons.R.string.md_cancel_label)
.backButton(com.afollestad.materialdialogs.commons.R.string.md_back_label)
.preselect(Color.parseColor(mSettings.getString(Settings.KEY_BACKGROUND_COLOR)))
.dynamicButtonColor(false)
.allowUserColorInputAlpha(false)
.tag(COLOR_TAG_BACKGROUND)
.show(this);
}
public void showHighlightColorDialog() {
mHighlightColorDialog = new ColorChooserDialog.Builder(this, R.string.setting_highlight_color)
.titleSub(R.string.setting_highlight_color)
.accentMode(true)
.doneButton(com.afollestad.materialdialogs.commons.R.string.md_done_label)
.cancelButton(com.afollestad.materialdialogs.commons.R.string.md_cancel_label)
.backButton(com.afollestad.materialdialogs.commons.R.string.md_back_label)
.preselect(Color.parseColor(mSettings.getString(Settings.KEY_HIGHLIGHT_COLOR)))
.dynamicButtonColor(false)
.allowUserColorInputAlpha(false)
.tag(COLOR_TAG_HIGHLIGHT)
.show(this);
}
@Override
public void onColorSelection(@NonNull ColorChooserDialog dialog, @ColorInt int selectedColor) {
String hexColor = String.format("#%06X", selectedColor);
if (dialog.tag().equals(COLOR_TAG_BACKGROUND)) {
mSettings.save(Settings.KEY_BACKGROUND, "Color");
mSettings.save(Settings.KEY_BACKGROUND_COLOR, hexColor);
sendBackgroundChangedBroadcast();
} else if (dialog.tag().equals(COLOR_TAG_HIGHLIGHT)) {
mSettings.save(Settings.KEY_HIGHLIGHT_COLOR, hexColor);
}
if (mSettingsInterface != null) {
mSettingsInterface.onValuesUpdated();
}
}
@Override
public void onColorChooserDismissed(@NonNull ColorChooserDialog dialog) {
}
private void dismissSortTypeDialog() {
if (mSortTypeDialog != null && mSortTypeDialog.isShowing()) {
mSortTypeDialog.dismiss();
}
}
private void dismissIconPackDialog() {
if (mIconPackDialog != null && mIconPackDialog.isShowing()) {
mIconPackDialog.dismiss();
}
}
private void dismissNightModeDialog() {
if (mNightModeDialog != null && mNightModeDialog.isShowing()) {
mNightModeDialog.dismiss();
}
}
private void dismissBackgroundDialog() {
if (mBackgroundDialog != null && mBackgroundDialog.isShowing()) {
mBackgroundDialog.dismiss();
}
}
private void dismissAllDialogs() {
dismissSortTypeDialog();
dismissIconPackDialog();
dismissNightModeDialog();
dismissBackgroundDialog();
// Color dialogs do not need to be dismissed
}
@Override
protected void onDestroy() {
dismissAllDialogs();
LoadedObservable.getInstance().deleteObserver(this);
super.onDestroy();
}
@Override
public void onBackPressed() {
finish();
}
@Override
public void finish() {
super.finish();
overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
}
private class FragmentPagerAdapter extends FragmentStatePagerAdapter {
private static final int NUM_PAGES = 3;
private Context mContext;
public FragmentPagerAdapter(FragmentManager fragmentManager, Context context) {
super(fragmentManager);
mContext = context;
}
@Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return LensFragment.newInstance();
case 1:
return AppsFragment.newInstance();
case 2:
return SettingsFragment.newInstance();
}
return new Fragment();
}
@Override
public int getCount() {
return NUM_PAGES;
}
@Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return mContext.getResources().getString(R.string.tab_lens);
case 1:
return mContext.getResources().getString(R.string.tab_apps);
case 2:
return mContext.getResources().getString(R.string.tab_settings);
}
return super.getPageTitle(position);
}
}
}
================================================
FILE: app/src/main/java/nickrout/lenslauncher/ui/SettingsFragment.java
================================================
package nickrout.lenslauncher.ui;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.SwitchCompat;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.TextView;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import nickrout.lenslauncher.R;
import nickrout.lenslauncher.util.LauncherUtil;
import nickrout.lenslauncher.util.NightModeUtil;
import nickrout.lenslauncher.util.Settings;
/**
* Created by nicholasrout on 2016/06/08.
*/
public class SettingsFragment extends Fragment implements SettingsActivity.SettingsInterface {
private static final String TAG = "SettingsFragment";
@OnClick(R.id.layout_home_launcher)
public void onHomeLauncherClick() {
showHomeLauncherChooser();
}
@BindView(R.id.text_view_selected_home_launcher)
TextView mHomeLauncherTextView;
@OnClick(R.id.layout_icon_pack)
public void onIconPackClick() {
showIconPackDialog();
}
@BindView(R.id.text_view_selected_icon_pack)
TextView mIconPackTextView;
@OnClick(R.id.layout_night_mode)
public void onNightModeClick() {
showNightModeChooser();
}
@BindView(R.id.text_view_selected_night_mode)
TextView mNightModeTextView;
@OnClick(R.id.layout_background)
public void onBackgroundClick() {
showBackgroundDialog();
}
@BindView(R.id.text_view_selected_background)
TextView mBackgroundTextView;
@BindView(R.id.image_view_selected_background_color)
ImageView mBackgroundColorImageView;
@OnClick(R.id.layout_highlight_color)
public void onHighlightColorClick() {
showHighlightColorDialog();
}
@BindView(R.id.text_view_selected_highlight_color)
TextView mHighlightColorTextView;
@BindView(R.id.image_view_selected_highlight_color)
ImageView mHighlightColorImageView;
@BindView(R.id.switch_vibrate_app_hover)
SwitchCompat mVibrateAppHover;
@BindView(R.id.switch_vibrate_app_launch)
SwitchCompat mVibrateAppLaunch;
@BindView(R.id.switch_show_name_app_hover)
SwitchCompat mShowNameAppHover;
@BindView(R.id.switch_show_new_app_tag)
SwitchCompat mShowNewAppTag;
@BindView(R.id.switch_show_touch_selection)
SwitchCompat mShowTouchSelection;
private Settings mSettings;
public SettingsFragment() {
}
public static SettingsFragment newInstance() {
SettingsFragment settingsFragment = new SettingsFragment();
// Include potential bundle extras here
return settingsFragment;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_settings, container, false);
ButterKnife.bind(this, view);
mSettings = new Settings(getActivity());
setupViews();
assignValues();
return view;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (getActivity() != null && getActivity() instanceof SettingsActivity) {
((SettingsActivity) getActivity()).setSettingsInterface(this);
}
}
private void setupViews() {
mVibrateAppHover.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
mSettings.save(Settings.KEY_VIBRATE_APP_HOVER, isChecked);
}
});
mVibrateAppLaunch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
mSettings.save(Settings.KEY_VIBRATE_APP_LAUNCH, isChecked);
}
});
mShowNameAppHover.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
mSettings.save(Settings.KEY_SHOW_NAME_APP_HOVER, isChecked);
}
});
mShowNewAppTag.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
mSettings.save(Settings.KEY_SHOW_NEW_APP_TAG, isChecked);
}
});
mShowTouchSelection.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
mSettings.save(Settings.KEY_SHOW_TOUCH_SELECTION, isChecked);
}
});
}
private void assignValues() {
mIconPackTextView.setText(mSettings.getString(Settings.KEY_ICON_PACK_LABEL_NAME));
String highlightColor = "#" + mSettings.getString(Settings.KEY_HIGHLIGHT_COLOR).substring(3);
String homeLauncher = "";
if (getActivity() != null) {
homeLauncher = LauncherUtil.getHomeLauncherName(getActivity().getApplication());
}
mHomeLauncherTextView.setText(homeLauncher);
mNightModeTextView.setText(NightModeUtil.getNightModeDisplayName(mSettings.getNightMode()));
if (mSettings.getString(Settings.KEY_BACKGROUND).equals("Color")) {
String backgroundColor = "#" + mSettings.getString(Settings.KEY_BACKGROUND_COLOR).substring(3);
mBackgroundTextView.setText(backgroundColor);
mBackgroundColorImageView.setVisibility(View.VISIBLE);
GradientDrawable backgroundColorDrawable = new GradientDrawable();
backgroundColorDrawable.setColor(Color.parseColor(mSettings.getString(Settings.KEY_BACKGROUND_COLOR)));
backgroundColorDrawable.setCornerRadius(getResources().getDimension(R.dimen.radius_highlight_color_switch));
mBackgroundColorImageView.setImageDrawable(backgroundColorDrawable);
} else {
mBackgroundTextView.setText(mSettings.getString(Settings.KEY_BACKGROUND));
mBackgroundColorImageView.setVisibility(View.GONE);
}
mHighlightColorTextView.setText(highlightColor);
GradientDrawable highlightColorDrawable = new GradientDrawable();
highlightColorDrawable.setColor(Color.parseColor(mSettings.getString(Settings.KEY_HIGHLIGHT_COLOR)));
highlightColorDrawable.setCornerRadius(getResources().getDimension(R.dimen.radius_highlight_color_switch));
mHighlightColorImageView.setImageDrawable(highlightColorDrawable);
mVibrateAppHover.setChecked(mSettings.getBoolean(Settings.KEY_VIBRATE_APP_HOVER));
mVibrateAppLaunch.setChecked(mSettings.getBoolean(Settings.KEY_VIBRATE_APP_LAUNCH));
mShowNameAppHover.setChecked(mSettings.getBoolean(Settings.KEY_SHOW_NAME_APP_HOVER));
mShowNewAppTag.setChecked(mSettings.getBoolean(Settings.KEY_SHOW_NEW_APP_TAG));
mShowTouchSelection.setChecked(mSettings.getBoolean(Settings.KEY_SHOW_TOUCH_SELECTION));
}
private void showIconPackDialog() {
if (getActivity() != null && getActivity() instanceof SettingsActivity) {
((SettingsActivity) getActivity()).showIconPackDialog();
}
}
private void showHomeLauncherChooser() {
if (getActivity() != null && getActivity() instanceof SettingsActivity) {
((SettingsActivity) getActivity()).showHomeLauncherChooser();
}
}
private void showNightModeChooser() {
if (getActivity() != null && getActivity() instanceof SettingsActivity) {
((SettingsActivity) getActivity()).showNightModeChooser();
}
}
private void showBackgroundDialog() {
if (getActivity() != null && getActivity() instanceof SettingsActivity) {
((SettingsActivity) getActivity()).showBackgroundDialog();
}
}
private void showHighlightColorDialog() {
if (getActivity() != null && getActivity() instanceof SettingsActivity) {
((SettingsActivity) getActivity()).showHighlightColorDialog();
}
}
@Override
public void onDefaultsReset() {
resetToDefault();
assignValues();
}
@Override
public void onValuesUpdated() {
assignValues();
}
private void resetToDefault() {
mSettings.save(Settings.KEY_VIBRATE_APP_HOVER, Settings.DEFAULT_VIBRATE_APP_HOVER);
mSettings.save(Settings.KEY_VIBRATE_APP_LAUNCH, Settings.DEFAULT_VIBRATE_APP_LAUNCH);
mSettings.save(Settings.KEY_SHOW_NAME_APP_HOVER, Settings.DEFAULT_SHOW_NAME_APP_HOVER);
mSettings.save(Settings.KEY_SHOW_TOUCH_SELECTION, Settings.DEFAULT_SHOW_TOUCH_SELECTION);
mSettings.save(Settings.KEY_SHOW_NEW_APP_TAG, Settings.DEFAULT_SHOW_NEW_APP_TAG);
mSettings.save(Settings.KEY_BACKGROUND, Settings.DEFAULT_BACKGROUND);
mSettings.save(Settings.KEY_BACKGROUND_COLOR, Settings.DEFAULT_BACKGROUND_COLOR);
mSettings.save(Settings.KEY_HIGHLIGHT_COLOR, Settings.DEFAULT_HIGHLIGHT_COLOR);
mSettings.save(Settings.KEY_ICON_PACK_LABEL_NAME, Settings.DEFAULT_ICON_PACK_LABEL_NAME);
mSettings.save(Settings.KEY_NIGHT_MODE, Settings.DEFAULT_NIGHT_MODE);
if (getActivity() != null && getActivity() instanceof SettingsActivity) {
((SettingsActivity) getActivity()).sendNightModeBroadcast();
}
}
}
================================================
FILE: app/src/main/java/nickrout/lenslauncher/util/AppSorter.java
================================================
package nickrout.lenslauncher.util;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import nickrout.lenslauncher.R;
import nickrout.lenslauncher.model.App;
import nickrout.lenslauncher.model.AppPersistent;
/**
* Created by nicholasrout on 2016/05/28.
*/
public class AppSorter {
public enum SortType {
LABEL_ASCENDING(R.string.setting_sort_type_label_ascending),
LABEL_DESCENDING(R.string.setting_sort_type_label_descending),
INSTALL_DATE_ASCENDING(R.string.setting_sort_type_install_date_ascending),
INSTALL_DATE_DESCENDING(R.string.setting_sort_type_install_date_descending),
ICON_COLOR_ASCENDING(R.string.setting_sort_type_icon_color_ascending),
ICON_COLOR_DESCENDING(R.string.setting_sort_type_icon_color_descending),
OPEN_COUNT_ASCENDING(R.string.setting_sort_type_open_count_ascending),
OPEN_COUNT_DESCENDING(R.string.setting_sort_type_open_count_descending);
int mDisplayNameResId;
SortType(int displayNameResId) {
mDisplayNameResId = displayNameResId;
}
public int getDisplayNameResId() {
return mDisplayNameResId;
}
}
public static void sort(ArrayList apps, SortType sortType) {
switch (sortType) {
case LABEL_ASCENDING:
sortByLabelAscending(apps);
break;
case LABEL_DESCENDING:
sortByLabelDescending(apps);
break;
case INSTALL_DATE_ASCENDING:
sortByInstallDateAscending(apps);
break;
case INSTALL_DATE_DESCENDING:
sortByInstallDateDescending(apps);
break;
case OPEN_COUNT_ASCENDING:
sortByOpenCountAscending(apps);
break;
case OPEN_COUNT_DESCENDING:
sortByOpenCountDescending(apps);
break;
case ICON_COLOR_ASCENDING:
sortByIconColorAscending(apps);
break;
case ICON_COLOR_DESCENDING:
sortByIconColorDescending(apps);
break;
default:
sortByLabelAscending(apps);
break;
}
}
private static void sortByLabelAscending(ArrayList apps) {
Collections.sort(apps, new Comparator() {
@Override
public int compare(App a1, App a2) {
return (a1.getLabel().toString()).compareToIgnoreCase(a2.getLabel().toString());
}
});
}
private static void sortByLabelDescending(ArrayList apps) {
sortByLabelAscending(apps);
Collections.reverse(apps);
}
private static void sortByInstallDateAscending(ArrayList apps) {
Collections.sort(apps, new Comparator() {
@Override
public int compare(App a1, App a2) {
if (a1.getInstallDate() > a2.getInstallDate()) {
return -1;
} else if (a1.getInstallDate() < a2.getInstallDate()) {
return +1;
}
return 0;
}
});
}
private static void sortByInstallDateDescending(ArrayList apps) {
sortByInstallDateAscending(apps);
Collections.reverse(apps);
}
private static void sortByOpenCountAscending(ArrayList apps) {
Collections.sort(apps, new Comparator() {
@Override
public int compare(App a1, App a2) {
long a1OpenCount =
AppPersistent.getAppOpenCount(a1.getPackageName().toString(), a1.getName().toString());
long a2OpenCount =
AppPersistent.getAppOpenCount(a2.getPackageName().toString(), a2.getName().toString());
if (a1OpenCount > a2OpenCount) {
return -1;
} else if (a1OpenCount < a2OpenCount) {
return +1;
}
return 0;
}
});
}
private static void sortByOpenCountDescending(ArrayList apps) {
sortByOpenCountAscending(apps);
Collections.reverse(apps);
}
private static void sortByIconColorAscending(ArrayList apps) {
Collections.sort(apps, new Comparator() {
@Override
public int compare(App a1, App a2) {
float a1HSVColor = ColorUtil.getHueColorFromApp(a1);
float a2HSVColor = ColorUtil.getHueColorFromApp(a2);
if (a1HSVColor > a2HSVColor) {
return -1;
} else if (a1HSVColor < a2HSVColor) {
return +1;
}
return 0;
}
});
}
private static void sortByIconColorDescending(ArrayList apps) {
sortByIconColorAscending(apps);
Collections.reverse(apps);
}
}
================================================
FILE: app/src/main/java/nickrout/lenslauncher/util/AppUtil.java
================================================
package nickrout.lenslauncher.util;
import android.app.Application;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.ActivityOptionsCompat;
import android.support.v4.content.ContextCompat;
import android.view.View;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
import nickrout.lenslauncher.R;
import nickrout.lenslauncher.background.BroadcastReceivers;
import nickrout.lenslauncher.model.App;
import nickrout.lenslauncher.model.AppPersistent;
/**
* Created by nickrout on 2016/04/02.
*/
public class AppUtil {
private static final String TAG = AppUtil.class.getSimpleName();
// Get all available apps for launcher
public static ArrayList getApps(
PackageManager packageManager, Context context, Application application,
String iconPackLabelName, AppSorter.SortType sortType) {
ArrayList apps = new ArrayList<>();
Intent intent = new Intent(Intent.ACTION_MAIN, null);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
List availableActivities = null;
try {
availableActivities = packageManager.queryIntentActivities(intent, 0);
} catch (RuntimeException e) {
e.printStackTrace();
Toast.makeText(context, R.string.error_too_many_apps, Toast.LENGTH_SHORT).show();
}
if (availableActivities != null) {
IconPackManager.IconPack selectedIconPack = null;
ArrayList iconPacks = new IconPackManager().getAvailableIconPacksWithIcons(true, application);
for (IconPackManager.IconPack iconPack : iconPacks) {
if (iconPack.mName.equals(iconPackLabelName))
selectedIconPack = iconPack;
}
for (int i = 0; i < availableActivities.size(); i++) {
ResolveInfo resolveInfo = availableActivities.get(i);
App app = new App();
app.setId(i);
try {
app.setInstallDate(packageManager.getPackageInfo(resolveInfo.activityInfo.packageName, 0).firstInstallTime);
} catch (PackageManager.NameNotFoundException e) {
app.setInstallDate(0);
}
app.setLabel(resolveInfo.loadLabel(packageManager));
app.setPackageName(resolveInfo.activityInfo.packageName);
app.setName(resolveInfo.activityInfo.name);
app.setIconResId(resolveInfo.activityInfo.getIconResource());
Bitmap defaultBitmap = BitmapUtil.packageNameToBitmap(
context, packageManager, resolveInfo.activityInfo.packageName, resolveInfo.activityInfo.getIconResource());
if (selectedIconPack != null)
app.setIcon(selectedIconPack.getIconForPackage(app.getPackageName().toString(), defaultBitmap));
else
app.setIcon(defaultBitmap);
app.setPaletteColor(ColorUtil.getPaletteColorFromApp(app));
apps.add(app);
}
}
AppSorter.sort(apps, sortType);
return apps;
}
// Launch apps, for launcher :-P
public static void launchComponent(Context context, String packageName, String name, View view, Rect bounds) {
if (packageName != null && name != null) {
Intent componentIntent = new Intent();
componentIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
componentIntent.setComponent(new ComponentName(packageName, name));
if (!packageName.equals("nickrout.lenslauncher")) {
componentIntent.setAction(Intent.ACTION_MAIN);
}
componentIntent.addCategory(Intent.CATEGORY_LAUNCHER);
try {
// Launch Component
ContextCompat.startActivity(context, componentIntent, getLauncherOptionsBundle(context, view, bounds));
// Increment app open count
AppPersistent.incrementAppCount(packageName, name);
// Resort apps (if open count selected)
Settings settings = new Settings(context);
if (settings.getSortType() == AppSorter.SortType.OPEN_COUNT_ASCENDING ||
settings.getSortType() == AppSorter.SortType.OPEN_COUNT_DESCENDING) {
Intent editAppsIntent = new Intent(context, BroadcastReceivers.AppsEditedReceiver.class);
context.sendBroadcast(editAppsIntent);
}
} catch (ActivityNotFoundException e) {
Toast.makeText(context, R.string.error_app_not_found, Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(context, R.string.error_app_not_found, Toast.LENGTH_SHORT).show();
}
}
private static Bundle getLauncherOptionsBundle(Context context, View source, Rect bounds) {
Bundle optionsBundle = null;
if (source != null) {
ActivityOptionsCompat options;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && bounds != null) {
// Clip reveal animation for Marshmallow and above
options = ActivityOptionsCompat.makeClipRevealAnimation(source, bounds.left, bounds.top, bounds.width(), bounds.height());
} else {
// Fade animation otherwise
options = ActivityOptionsCompat.makeCustomAnimation(context, R.anim.fade_in, R.anim.fade_out);
}
optionsBundle = options.toBundle();
}
return optionsBundle;
}
}
================================================
FILE: app/src/main/java/nickrout/lenslauncher/util/BitmapUtil.java
================================================
package nickrout.lenslauncher.util;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
/**
* Created by nickrout on 2016/04/02.
*/
public class BitmapUtil {
// Old method - does not allow for adding options i.e. lower quality
// Source: http://stackoverflow.com/questions/3035692/how-to-convert-a-drawable-to-a-bitmap
public static Bitmap drawableToBitmap (Drawable drawable) {
Bitmap bitmap = null;
if (drawable instanceof BitmapDrawable) {
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
bitmapDrawable.setAntiAlias(true);
bitmapDrawable.setDither(true);
bitmapDrawable.setTargetDensity(Integer.MAX_VALUE);
if(bitmapDrawable.getBitmap() != null) {
return bitmapDrawable.getBitmap();
}
}
if(drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) {
bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); // Single color bitmap will be created of 1x1 pixel
} else {
bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
}
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
// Get bitmap from resource id, with quality options
public static Bitmap resIdToBitmap(Resources res, int resId) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;
options.inDither = false;
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
options.inPreferQualityOverSpeed = true;
try {
return BitmapFactory.decodeResource(res, resId, options);
} catch (OutOfMemoryError e1) {
e1.printStackTrace();
return null;
}
}
// Get res id from app package name
public static int packageNameToResId(PackageManager packageManager, String packageName) {
try {
ApplicationInfo applicationInfo = packageManager.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
return applicationInfo.icon;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
return -1;
}
}
// Get bitmap from app package name
public static Bitmap packageNameToBitmap(PackageManager packageManager, String packageName) {
try {
ApplicationInfo applicationInfo = packageManager.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
Resources resources = packageManager.getResourcesForApplication(applicationInfo);
int appIconResId = applicationInfo.icon;
return resIdToBitmap(resources, appIconResId);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
return null;
}
}
// Get bitmap from app package name (with res id)
public static Bitmap packageNameToBitmap(Context context, PackageManager packageManager, String packageName, int resId) {
try {
ApplicationInfo applicationInfo = packageManager.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
Resources resources = packageManager.getResourcesForApplication(applicationInfo);
Bitmap bitmap = resIdToBitmap(resources, resId);
if (bitmap == null) {
Drawable drawable = packageManager.getApplicationIcon(packageName);
if (drawable != null) {
bitmap = drawableToBitmap(drawable);
}
}
return bitmap;
} catch (PackageManager.NameNotFoundException | Resources.NotFoundException e) {
e.printStackTrace();
return null;
}
}
}
================================================
FILE: app/src/main/java/nickrout/lenslauncher/util/ColorUtil.java
================================================
package nickrout.lenslauncher.util;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.support.annotation.ColorInt;
import android.support.v7.graphics.Palette;
import nickrout.lenslauncher.model.App;
/**
* Created by nicholasrout on 2016/05/28.
*/
public class ColorUtil {
public static @ColorInt int getPaletteColorFromApp(App app) {
return getPaletteColorFromBitmap(app.getIcon());
}
public static @ColorInt int getPaletteColorFromBitmap(Bitmap bitmap) {
Palette palette;
try {
palette = Palette.from(bitmap).generate();
} catch (IllegalArgumentException e) {
e.printStackTrace();
return Color.BLACK;
}
if (palette.getSwatches().size() > 0) {
int swatchIndex = 0;
for (int i = 1; i < palette.getSwatches().size(); i++) {
if (palette.getSwatches().get(i).getPopulation()
> palette.getSwatches().get(swatchIndex).getPopulation()) {
swatchIndex = i;
}
}
return palette.getSwatches().get(swatchIndex).getRgb();
} else {
return Color.BLACK;
}
}
public static float getHueColorFromApp(App app) {
return getHueColorFromColor(app.getPaletteColor());
}
public static float getHueColorFromColor(@ColorInt int color) {
float[] hsvValues = new float[3];
Color.colorToHSV(color, hsvValues);
return hsvValues[0];
}
}
================================================
FILE: app/src/main/java/nickrout/lenslauncher/util/IconPackManager.java
================================================
package nickrout.lenslauncher.util;
/**
* Created by rish on 22/5/16.
*/
import android.app.Application;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.support.annotation.ColorInt;
import android.util.Log;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import nickrout.lenslauncher.R;
public class IconPackManager {
private static final String TAG = "IconPackManager";
private Application mApplication;
public class IconPack {
public IconPack() {
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setFilterBitmap(true);
mPaint.setDither(true);
}
public String mPackageName;
public String mName;
private boolean mLoaded = false;
private HashMap mPackagesDrawables = new HashMap();
private List mBackImages = new ArrayList();
private Bitmap mMaskImage = null;
private Bitmap mFrontImage = null;
private float mFactor = 1.0f;
private Paint mPaint;
Resources mIconPackRes = null;
public void load() {
// Load appfilter.xml from the icon pack package
PackageManager pm = mApplication.getPackageManager();
try {
XmlPullParser xpp = null;
mIconPackRes = pm.getResourcesForApplication(mPackageName);
int appfilterid = mIconPackRes.getIdentifier("appfilter", "xml", mPackageName);
if (appfilterid > 0) {
xpp = mIconPackRes.getXml(appfilterid);
} else {
// No resource found, try to open it from assets folder
try {
InputStream appfilterstream = mIconPackRes.getAssets().open("appfilter.xml");
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
xpp = factory.newPullParser();
xpp.setInput(appfilterstream, "utf-8");
} catch (IOException e1) {
Log.d(TAG, "No appfilter.xml file");
}
}
if (xpp != null) {
int eventType = xpp.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_TAG) {
if (xpp.getName().equals("iconback")) {
for (int i = 0; i < xpp.getAttributeCount(); i++) {
if (xpp.getAttributeName(i).startsWith("img")) {
String drawableName = xpp.getAttributeValue(i);
Bitmap iconback = loadBitmap(drawableName);
if (iconback != null)
mBackImages.add(iconback);
}
}
} else if (xpp.getName().equals("iconmask")) {
if (xpp.getAttributeCount() > 0 && xpp.getAttributeName(0).equals("img1")) {
String drawableName = xpp.getAttributeValue(0);
mMaskImage = loadBitmap(drawableName);
}
} else if (xpp.getName().equals("iconupon")) {
if (xpp.getAttributeCount() > 0 && xpp.getAttributeName(0).equals("img1")) {
String drawableName = xpp.getAttributeValue(0);
mFrontImage = loadBitmap(drawableName);
}
} else if (xpp.getName().equals("scale")) {
if (xpp.getAttributeCount() > 0 && xpp.getAttributeName(0).equals("factor")) {
try {
mFactor = Float.valueOf(xpp.getAttributeValue(0));
} catch (NumberFormatException e) {
mFactor = 1.0f;
e.printStackTrace();
}
}
} else if (xpp.getName().equals("item")) {
String componentName = null;
String drawableName = null;
for (int i = 0; i < xpp.getAttributeCount(); i++) {
if (xpp.getAttributeName(i).equals("component")) {
componentName = xpp.getAttributeValue(i);
} else if (xpp.getAttributeName(i).equals("drawable")) {
drawableName = xpp.getAttributeValue(i);
}
}
if (!mPackagesDrawables.containsKey(componentName))
mPackagesDrawables.put(componentName, drawableName);
}
}
eventType = xpp.next();
}
}
mLoaded = true;
} catch (PackageManager.NameNotFoundException e) {
Log.d(TAG, "Cannot load icon pack");
} catch (XmlPullParserException e) {
Log.d(TAG, "Cannot parse icon pack appfilter.xml");
} catch (IOException e) {
e.printStackTrace();
}
}
private Bitmap loadBitmap(String drawableName) {
int id = mIconPackRes.getIdentifier(drawableName, "drawable", mPackageName);
if (id > 0) {
Drawable bitmap = mIconPackRes.getDrawable(id);
if (bitmap instanceof BitmapDrawable)
return ((BitmapDrawable) bitmap).getBitmap();
}
return null;
}
public Bitmap getIconForPackage(String appPackageName, Bitmap defaultBitmap) {
if (!mLoaded) {
load();
}
PackageManager pm = mApplication.getPackageManager();
Intent launchIntent = pm.getLaunchIntentForPackage(appPackageName);
String componentName = null;
if (launchIntent != null)
componentName = pm.getLaunchIntentForPackage(appPackageName).getComponent().toString();
String drawable = mPackagesDrawables.get(componentName);
if (drawable != null) {
Bitmap bitmap = loadBitmap(drawable);
if (bitmap == null) {
return generateBitmap(defaultBitmap);
}
return bitmap;
} else {
// Try to get a resource with the component filename
if (componentName != null) {
int start = componentName.indexOf("{") + 1;
int end = componentName.indexOf("}", start);
if (end > start) {
drawable = componentName.substring(start, end).toLowerCase(Locale.getDefault()).replace(".", "_").replace("/", "_");
if (mIconPackRes.getIdentifier(drawable, "drawable", mPackageName) > 0)
return loadBitmap(drawable);
}
}
}
return generateBitmap(defaultBitmap);
}
private Bitmap generateBitmap(Bitmap defaultBitmap) {
// No need to go through below process id defaultBitmap is null
if (defaultBitmap == null) {
return null;
}
// If no back images, return default app icon
if (mBackImages.size() == 0) {
return defaultBitmap;
}
// Get a random back image
Bitmap backImage = getMostAppropriateBackImage(defaultBitmap);
int backImageWidth = backImage.getWidth();
int backImageHeight = backImage.getHeight();
// Create a bitmap for the result
Bitmap result;
try {
result = Bitmap.createBitmap(backImageWidth, backImageHeight, Bitmap.Config.ARGB_8888);
} catch (OutOfMemoryError e) {
e.printStackTrace();
return null;
}
// Instantiate a canvas to combine the icon / background
Canvas canvas = new Canvas(result);
// Draw the background first
canvas.drawBitmap(backImage, 0, 0, null);
// Create rects for scaling the default bitmap
Rect srcRect = new Rect(
0,
0,
defaultBitmap.getWidth(),
defaultBitmap.getHeight()
);
float scaledWidth = mFactor * ((float) backImageWidth);
float scaledHeight = mFactor * ((float) backImageHeight);
RectF destRect = new RectF(
((float) backImageWidth) / 2.0f - scaledWidth / 2.0f,
((float) backImageHeight) / 2.0f - scaledHeight / 2.0f,
((float) backImageWidth) / 2.0f + scaledWidth / 2.0f,
((float) backImageHeight) / 2.0f + scaledHeight / 2.0f
);
// Handle mask image
if (mMaskImage != null) {
// First get mask bitmap
Bitmap mask;
try {
mask = Bitmap.createBitmap(backImageWidth, backImageHeight, Bitmap.Config.ARGB_8888);
} catch (OutOfMemoryError e) {
e.printStackTrace();
return null;
}
// Make a temp mask canvas
Canvas maskCanvas = new Canvas(mask);
// Draw the bitmap with mask into the result
maskCanvas.drawBitmap(
defaultBitmap, srcRect, destRect, mPaint
);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
maskCanvas.drawBitmap(mMaskImage, 0, 0, mPaint);
mPaint.setXfermode(null);
canvas.drawBitmap(mask, 0, 0, mPaint);
} else {
// Draw the scaled bitmap without mask
canvas.drawBitmap(
defaultBitmap, srcRect, destRect, mPaint
);
}
// Draw the front image
if (mFrontImage != null) {
canvas.drawBitmap(mFrontImage, 0, 0, mPaint);
}
// Return result
return result;
}
private Bitmap getMostAppropriateBackImage(Bitmap defaultBitmap) {
if (mBackImages.size() == 1) {
return mBackImages.get(0);
}
@ColorInt int defaultPaletteColor = ColorUtil.getPaletteColorFromBitmap(defaultBitmap);
float defaultHueColor = ColorUtil.getHueColorFromColor(defaultPaletteColor);
float difference = Float.MAX_VALUE;
int index = 0;
for (int i = 0; i < mBackImages.size(); i++) {
@ColorInt int backPaletteColor = ColorUtil.getPaletteColorFromBitmap(mBackImages.get(i));
float backHueColor = ColorUtil.getHueColorFromColor(backPaletteColor);
if (Math.abs(defaultHueColor - backHueColor) < difference) {
difference = Math.abs(defaultHueColor - backHueColor);
index = i;
}
}
return mBackImages.get(index);
}
}
private ArrayList mIconPacks = null;
public ArrayList getAvailableIconPacksWithIcons(boolean forceReload, Application application) {
mApplication = application;
if (mIconPacks == null || forceReload) {
mIconPacks = new ArrayList<>();
PackageManager pm = mApplication.getPackageManager();
/**
* Currently Lens Launcher supports all icon packs supported by GoLauncher / EX
* Create a set by filter the list to contain unique icon packs only
*/
List rinfo = new ArrayList<>();
for (String launcher : mApplication.getResources().getStringArray(R.array.icon_pack_launchers)) {
rinfo.addAll(pm.queryIntentActivities(new Intent(launcher), PackageManager.GET_META_DATA));
}
for (ResolveInfo ri : rinfo) {
IconPack ip = new IconPack();
ip.mPackageName = ri.activityInfo.packageName;
ApplicationInfo ai = null;
try {
ai = pm.getApplicationInfo(ip.mPackageName, PackageManager.GET_META_DATA);
ip.mName = mApplication.getPackageManager().getApplicationLabel(ai).toString();
mIconPacks.add(ip);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
}
}
return mIconPacks;
}
}
================================================
FILE: app/src/main/java/nickrout/lenslauncher/util/LauncherUtil.java
================================================
package nickrout.lenslauncher.util;
import android.app.Application;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
/**
* Created by rish on 5/6/16.
*/
public class LauncherUtil {
public static boolean isLauncherDefault(Application application) {
final Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
final ResolveInfo res = application.getPackageManager().resolveActivity(intent, 0);
if (res.activityInfo == null) {
return false;
} else if ("android".equals(res.activityInfo.packageName)) {
return false;
} else {
if (res.activityInfo.packageName.equals(application.getPackageName())) return true;
else
return false;
}
}
public static String getHomeLauncherName(Application application) {
final Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
final ResolveInfo res = application.getPackageManager().resolveActivity(intent, 0);
if (res.activityInfo == null) {
return "";
}
return res.activityInfo.loadLabel(application.getPackageManager()).toString();
}
public static void resetPreferredLauncherAndOpenChooser(Context context) {
PackageManager packageManager = context.getPackageManager();
ComponentName componentName = new ComponentName(context, nickrout.lenslauncher.ui.FakeLauncherActivity.class);
packageManager.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
Intent selector = new Intent(Intent.ACTION_MAIN);
selector.addCategory(Intent.CATEGORY_HOME);
selector.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(selector);
packageManager.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, PackageManager.DONT_KILL_APP);
}
}
================================================
FILE: app/src/main/java/nickrout/lenslauncher/util/LensCalculator.java
================================================
package nickrout.lenslauncher.util;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.RectF;
import android.util.DisplayMetrics;
import nickrout.lenslauncher.model.Grid;
/**
* Created by nickrout on 2016/04/02.
*/
public class LensCalculator {
// Algorithm for calculating equispaced grid
public static Grid calculateGrid(Context context, int screenWidth, int screenHeight, int itemCount) {
Grid grid = new Grid();
grid.setItemCount(itemCount);
int itemCountHorizontal, itemCountVertical;
if (itemCount == 0 || itemCount == 1) {
itemCountHorizontal = itemCount;
itemCountVertical = itemCount;
} else {
double optimalSquareSize = calculateOptimalSquareSize(screenWidth, screenHeight, itemCount);
itemCountHorizontal = (int) Math.ceil(screenWidth / optimalSquareSize);
itemCountVertical = (int) Math.ceil((double) itemCount / (double) itemCountHorizontal);
}
grid.setItemCountHorizontal(itemCountHorizontal);
grid.setItemCountVertical(itemCountVertical);
Settings settings = new Settings(context);
float itemSize = LensCalculator.convertDpToPixel(settings.getFloat(Settings.KEY_ICON_SIZE), context);
grid.setItemSize(itemSize);
float spacingHorizontal = (((float) screenWidth) - ((float) itemCountHorizontal * itemSize)) / ((float) (itemCountHorizontal + 1));
grid.setSpacingHorizontal(spacingHorizontal);
float spacingVertical = (((float) screenHeight) - ((float) itemCountVertical * itemSize)) / ((float) (itemCountVertical + 1));
grid.setSpacingVertical(spacingVertical);
return grid;
}
// Algorithm for calculating optimal square side length given width, height and number of items
public static double calculateOptimalSquareSize(int screenWidth, int screenHeight, int itemCount) {
// Source: http://math.stackexchange.com/questions/466198/algorithm-to-get-the-maximum-size-of-n-squares-that-fit-into-a-rectangle-with-a
double x = (double) screenWidth, y = (double) screenHeight, n = (double) itemCount;
double px = Math.ceil(Math.sqrt(n * x / y));
double sx, sy;
if(Math.floor(px * y / x) * px < n) {
sx = y / Math.ceil(px * y / x);
} else {
sx = x / px;
}
double py = Math.ceil(Math.sqrt(n * y / x));
if(Math.floor(py * x / y) * py < n) {
sy = x / Math.ceil(x * py / y);
} else {
sy = y / py;
}
return Math.max(sx, sy);
}
// Algorithm for circular distance
public static double calculateDistance(float x1, float x2, float y1, float y2) {
return Math.sqrt(Math.pow((double) (x2 - x1), 2) + Math.pow((double) (y2 - y1), 2));
}
// Algorithm for determining whether a rect is within a given lens (centered at touchX, touchY)
public static boolean isRectWithinLens(RectF rect, float touchX, float touchY, float lensDiameter) {
if (rect.left >= touchX - lensDiameter / 2.0f &&
rect.right <= touchX + lensDiameter / 2.0f &&
rect.top >= touchY - lensDiameter / 2.0f &&
rect.bottom <= touchY + lensDiameter / 2.0f) {
return true;
} else {
return false;
}
}
// Graphical Fisheye Lens algorithm for shifting
public static float shiftPoint(Context context, float lensPosition, float itemPosition, float boundary, float multiplier) {
if (lensPosition < 0) {
return itemPosition;
}
Settings settings = new Settings(context);
float shiftedPosition;
float a = Math.abs(lensPosition - itemPosition);
float b = Math.max(lensPosition, boundary - lensPosition);
float x = a / b;
float d = multiplier * settings.getFloat(Settings.KEY_DISTORTION_FACTOR);
float y = ((1.0f + d) * x) / (1.0f + (d * x));
float newDistanceFromCenter = b * y;
if (lensPosition >= itemPosition) {
shiftedPosition = lensPosition - newDistanceFromCenter;
} else {
shiftedPosition = lensPosition + newDistanceFromCenter;
}
return shiftedPosition;
}
// Graphical Fisheye Lens algorithm for scaling
public static float scalePoint(Context context, float lensPosition, float itemPosition, float itemSize, float boundary, float multiplier) {
if (lensPosition < 0) {
return itemSize;
}
Settings settings = new Settings(context);
float scaleDifference = settings.getFloat(Settings.KEY_SCALE_FACTOR) - Settings.MIN_SCALE_FACTOR;
float d = Settings.MIN_SCALE_FACTOR + scaleDifference * multiplier;
if (lensPosition >= itemPosition) {
itemPosition = itemPosition - d * (itemSize / 2.0f);
} else {
itemPosition = itemPosition + d * (itemSize / 2.0f);
}
return LensCalculator.shiftPoint(context, lensPosition, itemPosition, boundary, multiplier);
}
// Graphical Fisheye Lens algorithm for determining final scaled size
public static float calculateSquareScaledSize(float scaledPositionX, float shiftedPositionX, float scaledPositionY, float shiftedPositionY) {
return 2.0f * Math.min(Math.abs(scaledPositionX - shiftedPositionX), Math.abs(scaledPositionY - shiftedPositionY));
}
// Algorithm for calculating new rect
public static RectF calculateRect(float newCenterX, float newCenterY, float newSize) {
RectF newRect = new RectF(
newCenterX - newSize / 2.0f,
newCenterY - newSize / 2.0f,
newCenterX + newSize / 2.0f,
newCenterY + newSize / 2.0f);
return newRect;
}
// Algorithm for determining if touch point is within rect
public static boolean isInsideRect(float x, float y, RectF rect) {
if (x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom) {
return true;
} else {
return false;
}
}
// Algorithm for converting dp measurements to pixels
public static float convertDpToPixel(float dp, Context context) {
Resources resources = context.getResources();
DisplayMetrics metrics = resources.getDisplayMetrics();
float px = dp * ((float) metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT);
return px;
}
// Algorithm for converting pixels to dp measurements
public static float convertPixelsToDp(float px, Context context) {
Resources resources = context.getResources();
DisplayMetrics metrics = resources.getDisplayMetrics();
float dp = px / ((float) metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT);
return dp;
}
}
================================================
FILE: app/src/main/java/nickrout/lenslauncher/util/NightModeUtil.java
================================================
package nickrout.lenslauncher.util;
import android.support.v7.app.AppCompatDelegate;
/**
* Created by nicholasrout on 2017/01/15.
*/
public class NightModeUtil {
public static String getNightModeDisplayName(@AppCompatDelegate.NightMode int nightMode) {
switch (nightMode) {
case AppCompatDelegate.MODE_NIGHT_NO:
return "Light";
case AppCompatDelegate.MODE_NIGHT_YES:
return "Dark";
case AppCompatDelegate.MODE_NIGHT_AUTO:
return "Auto";
default:
return "Follow System";
}
}
public static @AppCompatDelegate.NightMode int getNightModeFromDisplayName(String displayName) {
switch (displayName) {
case "Light":
return AppCompatDelegate.MODE_NIGHT_NO;
case "Dark":
return AppCompatDelegate.MODE_NIGHT_YES;
case "Auto":
return AppCompatDelegate.MODE_NIGHT_AUTO;
default:
return AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM;
}
}
}
================================================
FILE: app/src/main/java/nickrout/lenslauncher/util/Settings.java
================================================
package nickrout.lenslauncher.util;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.v7.app.AppCompatDelegate;
/**
* Created by nicholasrout on 2016/04/02.
*/
public class Settings {
public static final float DEFAULT_ICON_SIZE = 18.0f;
public static final float DEFAULT_DISTORTION_FACTOR = 2.5f;
public static final float DEFAULT_SCALE_FACTOR = 1.0f;
public static final long DEFAULT_ANIMATION_TIME = 200;
public static final boolean DEFAULT_VIBRATE_APP_HOVER = false;
public static final boolean DEFAULT_VIBRATE_APP_LAUNCH = true;
public static final boolean DEFAULT_SHOW_NAME_APP_HOVER = true;
public static final boolean DEFAULT_SHOW_TOUCH_SELECTION = false;
public static final boolean DEFAULT_SHOW_NEW_APP_TAG = true;
public static final String DEFAULT_BACKGROUND = "Wallpaper";
public static final String DEFAULT_BACKGROUND_COLOR = "#FFF8BBD0";
public static final String DEFAULT_HIGHLIGHT_COLOR = "#FFF50057";
public static final String DEFAULT_ICON_PACK_LABEL_NAME = "Default Icon Pack";
public static final int DEFAULT_SORT_TYPE = 0;
public static final int DEFAULT_NIGHT_MODE = AppCompatDelegate.MODE_NIGHT_NO;
// These values are for the progress bars, their real values = (MAX_VALUE / INTERVAL (eg. 2)) + MIN_VALUE
public static final int MAX_ICON_SIZE = 45;
public static final int MAX_DISTORTION_FACTOR = 9;
public static final int MAX_SCALE_FACTOR = 5;
public static final int MAX_ANIMATION_TIME = 600;
public static final int SHOW_NEW_APP_TAG_DURATION = 12 * 60 * 60 * 1000; /* An app has the new tag for twelve hours. If openCount >= 1, the new tag is not drawn. */
public static final float MIN_ICON_SIZE = 10.0f;
public static final float MIN_DISTORTION_FACTOR = 0.5f;
public static final float MIN_SCALE_FACTOR = 1.0f;
public static final long MIN_ANIMATION_TIME = 100;
public static final float DEFAULT_FLOAT = Float.MIN_VALUE;
public static final long DEFAULT_LONG = Long.MIN_VALUE;
public static final boolean DEFAULT_BOOLEAN = false;
public static final String DEFAULT_STRING = "";
public static final String KEY_ICON_SIZE = "min_icon_size";
public static final String KEY_DISTORTION_FACTOR = "distortion_factor";
public static final String KEY_SCALE_FACTOR = "scale_factor";
public static final String KEY_ANIMATION_TIME = "animation_time";
public static final String KEY_VIBRATE_APP_HOVER = "vibrate_app_hover";
public static final String KEY_VIBRATE_APP_LAUNCH = "vibrate_app_launch";
public static final String KEY_SHOW_NAME_APP_HOVER = "show_name_app_hover";
public static final String KEY_SHOW_TOUCH_SELECTION = "show_touch_selection";
public static final String KEY_SHOW_NEW_APP_TAG = "show_new_tag_app";
public static final String KEY_BACKGROUND = "background";
public static final String KEY_BACKGROUND_COLOR = "background_color";
public static final String KEY_HIGHLIGHT_COLOR = "show_touch_selection_color";
public static final String KEY_ICON_PACK_LABEL_NAME = "icon_pack_label_name";
public static final String KEY_SORT_TYPE = "sort_type";
public static final String KEY_NIGHT_MODE = "night_mode";
private Context mContext;
private SharedPreferences mPrefs;
public Settings(Context context) {
mContext = context;
}
private SharedPreferences sharedPreferences() {
if (mPrefs == null) {
mPrefs = PreferenceManager.getDefaultSharedPreferences(mContext);
}
return mPrefs;
}
public void save(String name, int value) {
sharedPreferences().edit().putInt(name, value).commit();
}
public @AppCompatDelegate.NightMode int getNightMode() {
switch (sharedPreferences().getInt(KEY_NIGHT_MODE, DEFAULT_NIGHT_MODE)) {
case AppCompatDelegate.MODE_NIGHT_AUTO:
return AppCompatDelegate.MODE_NIGHT_AUTO;
case AppCompatDelegate.MODE_NIGHT_NO:
return AppCompatDelegate.MODE_NIGHT_NO;
case AppCompatDelegate.MODE_NIGHT_YES:
return AppCompatDelegate.MODE_NIGHT_YES;
default:
return AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM;
}
}
public void save(String name, float value) {
sharedPreferences().edit().putFloat(name, value).commit();
}
public float getFloat(String name) {
if (name.equals(KEY_ICON_SIZE)) {
if (sharedPreferences().getFloat(name, DEFAULT_ICON_SIZE) < MIN_ICON_SIZE) {
save(name, MIN_ICON_SIZE);
} else if (sharedPreferences().getFloat(name, DEFAULT_ICON_SIZE) > getMaxFloatValue(name)) {
save(name, getMaxFloatValue(name));
}
return sharedPreferences().getFloat(name, DEFAULT_ICON_SIZE);
} else if (name.equals(KEY_DISTORTION_FACTOR)) {
if (sharedPreferences().getFloat(name, DEFAULT_DISTORTION_FACTOR) < MIN_DISTORTION_FACTOR) {
save(name, MIN_DISTORTION_FACTOR);
} else if (sharedPreferences().getFloat(name, DEFAULT_DISTORTION_FACTOR) > getMaxFloatValue(name)) {
save(name, getMaxFloatValue(name));
}
return sharedPreferences().getFloat(name, DEFAULT_DISTORTION_FACTOR);
} else if (name.equals(KEY_SCALE_FACTOR)) {
if (sharedPreferences().getFloat(name, DEFAULT_SCALE_FACTOR) < MIN_SCALE_FACTOR) {
save(name, MIN_SCALE_FACTOR);
} else if (sharedPreferences().getFloat(name, DEFAULT_SCALE_FACTOR) > getMaxFloatValue(name)) {
save(name, getMaxFloatValue(name));
}
return sharedPreferences().getFloat(name, DEFAULT_SCALE_FACTOR);
} else {
return sharedPreferences().getFloat(name, DEFAULT_FLOAT);
}
}
public void save(String name, long value) {
sharedPreferences().edit().putLong(name, value).commit();
}
public long getLong(String name) {
if (name.equals(KEY_ANIMATION_TIME)) {
if (sharedPreferences().getLong(name, DEFAULT_ANIMATION_TIME) < MIN_ANIMATION_TIME) {
save(name, MIN_ANIMATION_TIME);
} else if (sharedPreferences().getLong(name, DEFAULT_ANIMATION_TIME) > getMaxLongValue(name)) {
save(name, getMaxLongValue(name));
}
return sharedPreferences().getLong(name, DEFAULT_ANIMATION_TIME);
} else {
return sharedPreferences().getLong(name, DEFAULT_LONG);
}
}
public void save(String name, String value) {
sharedPreferences().edit().putString(name, value).commit();
}
public String getString(String name) {
if (name.equals(KEY_BACKGROUND)) {
return sharedPreferences().getString(name, DEFAULT_BACKGROUND);
} else if (name.equals(KEY_BACKGROUND_COLOR)) {
return sharedPreferences().getString(name, DEFAULT_BACKGROUND_COLOR);
} else if (name.equals(KEY_HIGHLIGHT_COLOR)) {
return sharedPreferences().getString(name, DEFAULT_HIGHLIGHT_COLOR);
} else if (name.equals(KEY_ICON_PACK_LABEL_NAME)) {
return sharedPreferences().getString(name, DEFAULT_ICON_PACK_LABEL_NAME);
} else {
return sharedPreferences().getString(name, DEFAULT_STRING);
}
}
public void save(String name, boolean value) {
sharedPreferences().edit().putBoolean(name, value).commit();
}
public boolean getBoolean(String name) {
if (name.equals(KEY_VIBRATE_APP_HOVER)) {
return sharedPreferences().getBoolean(name, DEFAULT_VIBRATE_APP_HOVER);
} else if (name.equals(KEY_VIBRATE_APP_LAUNCH)) {
return sharedPreferences().getBoolean(name, DEFAULT_VIBRATE_APP_LAUNCH);
} else if (name.equals(KEY_SHOW_NAME_APP_HOVER)) {
return sharedPreferences().getBoolean(name, DEFAULT_SHOW_NAME_APP_HOVER);
} else if (name.equals(KEY_SHOW_TOUCH_SELECTION)) {
return sharedPreferences().getBoolean(name, DEFAULT_SHOW_TOUCH_SELECTION);
} else if (name.equals(KEY_SHOW_NEW_APP_TAG)) {
return sharedPreferences().getBoolean(name, DEFAULT_SHOW_NEW_APP_TAG);
} else {
return sharedPreferences().getBoolean(name, DEFAULT_BOOLEAN);
}
}
public void save(AppSorter.SortType value) {
save(KEY_SORT_TYPE, value.ordinal());
}
public AppSorter.SortType getSortType() {
int ordinal = sharedPreferences().getInt(KEY_SORT_TYPE, DEFAULT_SORT_TYPE);
return AppSorter.SortType.values()[ordinal];
}
public float getMaxFloatValue(String name) {
if (name.equals(KEY_ICON_SIZE)) {
return (float) MAX_ICON_SIZE + MIN_ICON_SIZE;
} else if (name.equals(KEY_DISTORTION_FACTOR)) {
return (float) MAX_DISTORTION_FACTOR / 2 + MIN_DISTORTION_FACTOR;
} else if (name.equals(KEY_SCALE_FACTOR)) {
return (float) MAX_SCALE_FACTOR / 2 + MIN_SCALE_FACTOR;
} else {
return DEFAULT_FLOAT;
}
}
public long getMaxLongValue(String name) {
if (name.equals(KEY_ANIMATION_TIME)) {
return (long) MAX_ANIMATION_TIME / 2 + MIN_ANIMATION_TIME;
} else {
return DEFAULT_LONG;
}
}
}
================================================
FILE: app/src/main/res/anim/fade_in.xml
================================================
================================================
FILE: app/src/main/res/anim/fade_out.xml
================================================
================================================
FILE: app/src/main/res/anim/slide_in_left.xml
================================================
================================================
FILE: app/src/main/res/anim/slide_in_right.xml
================================================
================================================
FILE: app/src/main/res/anim/slide_out_left.xml
================================================
================================================
FILE: app/src/main/res/anim/slide_out_right.xml
================================================
================================================
FILE: app/src/main/res/animator/raise.xml
================================================
-
-
================================================
FILE: app/src/main/res/drawable/ic_launcher_background.xml
================================================
================================================
FILE: app/src/main/res/drawable/ic_launcher_foreground.xml
================================================
================================================
FILE: app/src/main/res/layout/activity_about.xml
================================================
================================================
FILE: app/src/main/res/layout/activity_fake_launcher.xml
================================================
================================================
FILE: app/src/main/res/layout/activity_home.xml
================================================
================================================
FILE: app/src/main/res/layout/activity_settings.xml
================================================
================================================
FILE: app/src/main/res/layout/fragment_apps.xml
================================================
================================================
FILE: app/src/main/res/layout/fragment_lens.xml
================================================
================================================
FILE: app/src/main/res/layout/fragment_settings.xml
================================================
================================================
FILE: app/src/main/res/layout/layout_pro.xml
================================================
================================================
FILE: app/src/main/res/layout/recycler_item_app.xml
================================================
================================================
FILE: app/src/main/res/menu/menu_app.xml
================================================
================================================
FILE: app/src/main/res/menu/menu_settings.xml
================================================
================================================
FILE: app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
================================================
================================================
FILE: app/src/main/res/values/arrays.xml
================================================
- com.gau.go.launcherex.theme
- org.adw.launcher.THEMES
- Wallpaper
- Color
- Light
- Dark
- Auto
- Follow System
================================================
FILE: app/src/main/res/values/colors.xml
================================================
#111111
#000000
#F50057
#000000
#FFFFFF
#00FFFFFF
#DDDDDD
@color/colorBlack
#80000000
@color/colorBlack
@color/colorBlack
================================================
FILE: app/src/main/res/values/dimen.xml
================================================
]>
50dp
3dp
14sp
1dp
8dp
1dp
80dp
0dp
3dp
6dp
360dp
32dp
16dp
32sp
32dp
16dp
48dp
64dp
4dp
8dp
16dp
16dp
8dp
16dp
================================================
FILE: app/src/main/res/values/integers.xml
================================================
1
================================================
FILE: app/src/main/res/values/strings.xml
================================================
Lens Launcher
About
Order & Visibility
Settings
Apps
Lens
Apps
Settings
Lens Diameter
Icon Size
Distortion Factor
Scale Factor
Animation Time
Vibrate on App Hover
Vibrate on App Launch
Show Name on App Hover
Show Touch Selection
Show New App Tag
Background Color
Highlight Color
Icon Pack
Home Launcher
Night Mode Theme
Background
Default Icon Pack
@string/setting_sort_type_label_ascending
App Name (Ascending)
App Name (Descending)
Newest First
Oldest First
Most Opened
Least Opened
Icon Color (Light to Dark)
Icon Color (Dark to Light)
@string/activity_title_arranger
App Order
About
Reset Default Settings
Change Home Launcher
Show Apps
Open
App Info
Uninstall
App Not Found
Failed to Load Apps
Loading Apps
Loading Icons
Values Reset To Default
Instead of scrolling long lists or swiping through multiple pages, Lens Launcher implements two unique features:
• An Equispaced Grid that displays all of your apps, regardless of screen size or app count.
• A Graphical Fisheye Lens to quickly zoom, pan and launch apps using touch gestures.
Lens Launcher also includes a full Settings menu to tweak all aspects of the Lens; Distortion, Scaling, Icon Size, Haptic Feedback, etc.
The Graphical Fisheye Lens algorithm is derived from methods proposed by Manojit Sarkar and Marc H. Brown. Their original 1993 paper, titled Graphical Fisheye Views, can be found here.
Lens Launcher is written by Nick Rout
Twitter | Google+
Major contributions have been made by Rish Bhardwaj
Website | LinkedIn
The source code and resources are available on Github
Check out ShortStories by Nick Rout. Interactive stories told through App Shortcuts and Notifications.
Get it on Google Play]]>
MainActivity
PRO
Get Lens Launcher PRO
================================================
FILE: app/src/main/res/values/styles.xml
================================================
================================================
FILE: app/src/main/res/values-land/dimen.xml
================================================
30dp
80dp
240dp
================================================
FILE: app/src/main/res/values-night/colors.xml
================================================
@color/colorWhite
@color/colorWhite
================================================
FILE: app/src/main/res/values-night/styles.xml
================================================
================================================
FILE: app/src/main/res/values-w640dp/integers.xml
================================================
2
================================================
FILE: app/src/main/res/values-w820dp/dimen.xml
================================================
64dp
56dp
================================================
FILE: app/src/main/res/xml/shortcuts.xml
================================================
================================================
FILE: app/src/test/java/nickrout/lenslauncher/ExampleUnitTest.java
================================================
package nickrout.lenslauncher;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* To work on unit tests, switch the Test Artifact in the Build Variants view.
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() throws Exception {
assertEquals(4, 2 + 2);
}
}
================================================
FILE: build.gradle
================================================
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:8.2.2'
}
}
allprojects {
repositories {
google()
mavenCentral()
maven { url "https://jitpack.io" }
}
}
tasks.register('clean', Delete) {
delete rootProject.buildDir
}
================================================
FILE: docker-compose.yml
================================================
version: '2'
services:
gradle:
image: openjdk
working_dir: /app
environment:
- ANDROID_HOME=/app/android-studio
command: bash /app/docker-entrypoint.sh
volumes:
- '.:/app'
- '~/.gradle:/root/.gradle'
================================================
FILE: docker-entrypoint.sh
================================================
#! /bin/bash
set -e;
cd /app;
# Ensure Android SDK is installed
if [ ! -d /app/android-studio ]; then
echo "Android SDK directory not found.";
if [ ! -f /app/android-sdk.zip ]; then
echo "Android SDK zip file not found; beginning download.";
# Download the latest version of Android SDK
curl -L "$( \
curl -sL "https://developer.android.com/studio/index.html" \
| grep -Eoh "https?://.*?android-studio-ide.*?-linux\.zip" \
)" > /app/android-sdk.zip;
fi
# Unzips file to /app/android-studio
unzip /app/android-sdk.zip;
fi
# Sign Android SDK license
if [ ! -d /app/android-studio/licenses/android-sdk-license ]; then
mkdir -p /app/android-studio/licenses;
echo -e "\n8933bad161af4178b1185d1a37fbf41ea5269c55" \
> /app/android-studio/licenses/android-sdk-license;
fi
# Generate self-signed cert
keytool -genkey -noprompt \
-alias selfsigned \
-dname "CN=UNKNOWN, OU=UNKNOWN, O=UNKNOWN, L=UNKNOWN, S=UNKNOWN, C=UNKNOWN" \
-keystore /root/.keystore \
-storepass password \
-keypass password;
# Create Lens Launcher APK
/app/gradlew assembleRelease \
-Pandroid.injected.signing.key.alias=selfsigned \
-Pandroid.injected.signing.store.file=/root/.keystore \
-Pandroid.injected.signing.store.password=password \
-Pandroid.injected.signing.key.password=password;
# Find the generated APK file in lens-launcher/app/build/outputs/apk/app-release.apk
================================================
FILE: gradle/wrapper/gradle-wrapper.properties
================================================
#Wed Jan 31 16:09:16 SAST 2024
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
================================================
FILE: gradle.properties
================================================
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx10248m -XX:MaxPermSize=256m
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
# 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
android.nonFinalResIds=false
================================================
FILE: gradlew
================================================
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
================================================
FILE: gradlew.bat
================================================
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
================================================
FILE: settings.gradle
================================================
include ':app'