Commit fd9ee901 authored by Amit Kumar's avatar Amit Kumar
Browse files

Merge branch 'notification-feature' after adding notification badge

parents 4dc01d3c 8f67f67b
*.iml
.gradle
/.i
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
.externalNativeBuild
.idea/
*iml
gradle.properties
bin/
gen/
out/
build/
.classpath
.project
lint.xml
/dist
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<resourceExtensions />
<wildcardResourcePatterns>
<entry name="!?*.java" />
<entry name="!?*.form" />
<entry name="!?*.class" />
<entry name="!?*.groovy" />
<entry name="!?*.scala" />
<entry name="!?*.flex" />
<entry name="!?*.kt" />
<entry name="!?*.clj" />
<entry name="!?*.aj" />
</wildcardResourcePatterns>
<annotationProcessing>
<profile default="true" name="Default" enabled="false">
<processorPath useClasspath="true" />
</profile>
</annotationProcessing>
</component>
</project>
\ No newline at end of file
<component name="CopyrightManager">
<settings default="" />
</component>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
<option name="resolveModulePerSourceSet" value="false" />
</GradleProjectSettings>
</option>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="NullableNotNullManager">
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
<option name="myNullables">
<value>
<list size="4">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
</list>
</value>
</option>
<option name="myNotNulls">
<value>
<list size="4">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
</list>
</value>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/BlissLauncherO.iml" filepath="$PROJECT_DIR$/BlissLauncherO.iml" />
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
</modules>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
</set>
</option>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
\ No newline at end of file
......@@ -2,12 +2,12 @@ apply plugin: 'com.android.application'
apply plugin: 'io.fabric'
android {
compileSdkVersion 26
buildToolsVersion "26.0.2"
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
defaultConfig {
applicationId "org.indin.blisslauncher"
minSdkVersion 22
targetSdkVersion 26
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
......@@ -18,25 +18,63 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
// Always show the result of every unit test, even if it passes.
testOptions.unitTests.all {
testLogging {
events 'passed', 'skipped', 'failed', 'standardOut', 'standardError'
}
}
compileOptions {
targetCompatibility 1.8
sourceCompatibility 1.8
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
// Support Libs
implementation "com.android.support:appcompat-v7:${rootProject.ext.supportLibraryVersion}"
implementation "com.android.support:recyclerview-v7:${rootProject.ext.supportLibraryVersion}"
// Dagger
implementation "com.google.dagger:dagger:${rootProject.ext.daggerVersion}"
implementation "com.google.dagger:dagger-android:${rootProject.ext.daggerVersion}"
annotationProcessor "com.google.dagger:dagger-compiler:${rootProject.ext.daggerVersion}"
annotationProcessor "com.google.dagger:dagger-android-processor:${rootProject.ext.daggerVersion}"
// Rx Java and Android
implementation "io.reactivex.rxjava2:rxandroid:${rootProject.ext.rxAndroidVersion}"
implementation "io.reactivex.rxjava2:rxjava:${rootProject.ext.rxJavaVersion}"
// Rx Relay
implementation "com.jakewharton.rxrelay2:rxrelay:${rootProject.ext.rxRelayVersion}"
// Unit test dependencies
testImplementation "junit:junit:${rootProject.ext.junitVersion}"
testImplementation "org.robolectric:robolectric:${rootProject.ext.robolectricVersion}"
testImplementation "org.mockito:mockito-core:${rootProject.ext.mockitoVersion}"
testImplementation "org.hamcrest:hamcrest-core:${rootProject.ext.hamcrestVersion}"
testImplementation "org.hamcrest:hamcrest-library:${rootProject.ext.hamcrestVersion}"
testImplementation "org.hamcrest:hamcrest-integration:${rootProject.ext.hamcrestVersion}"
// Instrumentation tests dependencies
androidTestImplementation "junit:junit:${rootProject.ext.junitVersion}"
androidTestImplementation "org.mockito:mockito-core:${rootProject.ext.mockitoVersion}"
androidTestImplementation "org.mockito:mockito-android:${rootProject.ext.mockitoVersion}"
androidTestImplementation "com.android.support:support-annotations:${rootProject.ext.supportLibraryVersion}"
androidTestImplementation("com.android.support.test.espresso:espresso-contrib:${rootProject.ext.espressoVersion}", {
exclude group: 'com.android.support', module: 'appcompat-v7'
exclude group: 'com.android.support', module: 'support-v4'
exclude group: 'com.android.support', module: 'recyclerview-v7'
exclude group: 'com.android.support', module: 'design'
})
compile 'me.relex:circleindicator:1.2.2@aar'
compile 'com.android.support:appcompat-v7:26.1.0'
compile 'com.android.support:gridlayout-v7:26.1.0'
androidTestImplementation "com.android.support.test.espresso:espresso-core:${rootProject.ext.espressoVersion}"
androidTestImplementation "com.android.support.test:runner:${rootProject.ext.runnerRulesVersion}"
androidTestImplementation "com.android.support.test:rules:${rootProject.ext.runnerRulesVersion}"
// Crashlytics
compile('com.crashlytics.sdk.android:crashlytics:2.7.1@aar') {
transitive = true
}
compile files('libs/bruce-utils.jar')
testCompile 'junit:junit:4.12'
compile 'org.lucasr.dspec:dspec:0.1.1'
}
apply plugin: 'com.jakewharton.hugo'
......@@ -5,6 +5,25 @@
<uses-permission android:name="android.permission.SET_WALLPAPER" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="com.android.email.permission.ACCESS_PROVIDER" />
<uses-permission android:name="com.google.android.gm.permission.READ_CONTENT_PROVIDER" />
<uses-permission android:name="com.sec.android.provider.badge.permission.READ" />
<uses-permission android:name="com.fsck.k9.permission.READ_MESSAGES" />
<uses-permission android:name="com.kaitenmail.permission.READ_MESSAGES" />
<uses-permission android:name="com.kaitenmail.adsupported.permission.READ_MESSAGES" />
<uses-permission android:name="android.intent.action.BADGE_COUNT_UPDATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.email.permission.READ_ATTACHMENT" />
<uses-permission android:name="android.email.permission.ACCESS_PROVIDER" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<application
android:name=".BlissLauncher"
android:allowBackup="true"
......@@ -14,7 +33,7 @@
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".ui.DesktopActivity"
android:name=".ui.LauncherActivity"
android:clearTaskOnLaunch="true"
android:launchMode="singleTask"
android:screenOrientation="nosensor"
......@@ -28,9 +47,20 @@
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<service
android:name=".notification.NotificationService"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
<meta-data
android:name="io.fabric.ApiKey"
android:value="8fcf342f1b8ac74d6980872082b7216ef4682a29" />
</application>
</manifest>
package org.indin.blisslaunchero.db;
package org.indin.blisslaunchero.data.db;
import android.content.Context;
import android.content.SharedPreferences;
......@@ -7,7 +7,7 @@ import android.util.Log;
import android.view.ViewGroup;
import android.widget.GridLayout;
import org.indin.blisslaunchero.model.AppItem;
import org.indin.blisslaunchero.data.model.AppItem;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
......
package org.indin.blisslaunchero.model;
package org.indin.blisslaunchero.data.model;
import android.content.Intent;
import android.graphics.drawable.Drawable;
......@@ -8,133 +8,134 @@ import java.util.List;
public class AppItem {
private CharSequence label;
private String packageName;
private Drawable icon;
private Intent intent;
private String componentName;
private boolean iconFromIconPack;
private boolean isSystemApp;
private boolean isClock;
private boolean isCalendar;
private CharSequence mLabel;
private String mPackageName;
private Drawable mIcon;
private Intent mIntent;
private String mComponentName;
private boolean mIconFromIconPack;
private boolean mIsSystemApp;
private boolean mIsClock;
private boolean mIsCalendar;
private boolean isPinnedApp;
// Folder specific
private boolean belongsToFolder;
private boolean isFolder;
private String folderID;
private List<AppItem> subApps;
private boolean mBelongsToFolder;
private boolean mIsFolder;
private String mFolderID;
private List<AppItem> mSubApps;
public AppItem(CharSequence label, String packageName, Drawable icon,
Intent intent, String componentName, boolean iconFromIconPack, boolean isSystemApp,
boolean isClock, boolean isCalendar) {
this.label = label;
this.packageName = packageName;
this.icon = icon;
this.intent = intent;
this.componentName = componentName;
this.iconFromIconPack = iconFromIconPack;
this.isSystemApp = isSystemApp;
this.isClock = isClock;
this.isCalendar = isCalendar;
this.mLabel = label;
this.mPackageName = packageName;
this.mIcon = icon;
this.mIntent = intent;
this.mComponentName = componentName;
this.mIconFromIconPack = iconFromIconPack;
this.mIsSystemApp = isSystemApp;
this.mIsClock = isClock;
this.mIsCalendar = isCalendar;
}
public CharSequence getLabel() {
return label;
return mLabel;
}
public void setLabel(CharSequence label) {
this.label = label;
this.mLabel = label;
}
public String getPackageName() {
return packageName;
return mPackageName;
}
public void setPackageName(String packageName) {
this.packageName = packageName;
this.mPackageName = packageName;
}
public Drawable getIcon() {
return icon;
return mIcon;
}
public boolean isSystemApp() {
return isSystemApp;
return mIsSystemApp;
}
public boolean isClock() {
return isClock;
return mIsClock;
}
public boolean isCalendar() {
return isCalendar;
return mIsCalendar;
}
public void setSystemApp(boolean isSystemApp) {
this.isSystemApp = isSystemApp;
this.mIsSystemApp = isSystemApp;
}
public void setIcon(Drawable icon) {
this.icon = icon;
this.mIcon = icon;
}
public Intent getIntent() {
return intent;
return mIntent;
}
public void setIntent(Intent intent) {
this.intent = intent;
this.mIntent = intent;
}
public String getComponentName() {
return componentName;
return mComponentName;
}
public void setComponentName(String componentName) {
this.componentName = componentName;
this.mComponentName = componentName;
}
public boolean isIconFromIconPack() {
return iconFromIconPack;
return mIconFromIconPack;
}
public void setIconFromIconPack(boolean iconFromIconPack) {
this.iconFromIconPack = iconFromIconPack;
this.mIconFromIconPack = iconFromIconPack;
}
public boolean isFolder() {
return isFolder;
return mIsFolder;
}
public void setFolder(boolean folder) {
isFolder = folder;
mIsFolder = folder;
}
public String getFolderID() {
return folderID;
return mFolderID;
}
public void setFolderID(String folderID) {
this.folderID = folderID;
this.mFolderID = folderID;
}
public List<AppItem> getSubApps() {
if (subApps == null) {
subApps = new ArrayList<>();
if (mSubApps == null) {
mSubApps = new ArrayList<>();
}
return subApps;
return mSubApps;
}
public void setSubApps(List<AppItem> subApps) {
this.subApps = subApps;
this.mSubApps = subApps;
}
public boolean isBelongsToFolder() {
return belongsToFolder;
return mBelongsToFolder;
}
public void setBelongsToFolder(boolean belongsToFolder) {
this.belongsToFolder = belongsToFolder;
this.mBelongsToFolder = belongsToFolder;
}
}
package org.indin.blisslaunchero.data.model;
import android.widget.TextView;
/**
* Created by falcon on 17/3/18.
*/
public class CalendarIcon {
public TextView monthTextView;
public TextView dayTextView;
public CalendarIcon(TextView monthTextView, TextView dayTextView) {
this.monthTextView = monthTextView;
this.dayTextView = dayTextView;
}
}
package org.indin.blisslaunchero.data.model;
/**
* Created by falcon on 18/3/18.
*/
public class OtherInfo {
public int count;
public String packageName;
}
package org.indin.blisslaunchero.notification;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.Log;
/**
* Created by falcon on 20/3/18.
*/
public class DotRenderer {
private static final String TAG = "DotRenderer";
private static final float SIZE_PERCENTAGE = 0.25f;
private final int mSize;
private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG |
Paint.FILTER_BITMAP_FLAG);
public DotRenderer(int iconSizePx){
this.mSize = (int) (SIZE_PERCENTAGE *iconSizePx);
}
public void drawDot(Canvas canvas, Rect iconBounds){
Log.d(TAG, "drawDot() called with: canvas = [" + canvas + "], iconBounds = [" + iconBounds
+ "]");
int badgeCenterX = (int) (iconBounds.left + mSize*0.25);
int badgeCenterY = (int) (iconBounds.top + mSize*0.25);
mPaint.setColor(Color.parseColor("#FF0800"));
canvas.drawCircle(badgeCenterX, badgeCenterY, mSize/2, mPaint);
}
}
package org.indin.blisslaunchero.notification;
import android.service.notification.StatusBarNotification;
import android.util.Log;
import com.jakewharton.rxrelay2.BehaviorRelay;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* Created by Amit Kumar
* Email : mr.doc10jl96@gmail.com
*/
public class NotificationRepository {
private BehaviorRelay<Set<String>> notificationRelay;
private static final String TAG = "NotificationRepository";
private static NotificationRepository sInstance;
private NotificationRepository() {
notificationRelay = BehaviorRelay.createDefault(Collections.emptySet());
}
public static NotificationRepository getNotificationRepository() {
if (sInstance == null) {
sInstance = new NotificationRepository();
}
return sInstance;
}
public void updateNotification(List<StatusBarNotification> list) {
Log.d(TAG, "updateNotification() called with: list = [" + list.size() + "]");
Set<String> notificationSet = new HashSet<>();
for (StatusBarNotification statusBarNotification : list) {
notificationSet.add(statusBarNotification.getPackageName());
}
this.notificationRelay.accept(notificationSet);
}