├── .gitignore
├── LICENSE
├── README.md
├── app
├── .gitignore
├── build.gradle
├── libs
│ └── lite-orm-1.9.2.jar
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── cn
│ │ └── gavinliu
│ │ └── notificationbox
│ │ ├── NotificationBoxApp.java
│ │ ├── model
│ │ ├── AppInfo.java
│ │ ├── ModelSource.java
│ │ └── NotificationInfo.java
│ │ ├── service
│ │ └── NotificationListenerService.java
│ │ ├── ui
│ │ ├── BasePresenter.java
│ │ ├── BaseView.java
│ │ ├── applist
│ │ │ ├── AppListActivity.java
│ │ │ ├── AppListContract.java
│ │ │ ├── AppListFragment.java
│ │ │ └── AppListPresenter.java
│ │ ├── detail
│ │ │ ├── DetailActivity.java
│ │ │ ├── DetailContract.java
│ │ │ ├── DetailFragment.java
│ │ │ └── DetailPresenter.java
│ │ ├── main
│ │ │ ├── MainActivity.java
│ │ │ ├── MainContract.java
│ │ │ ├── MainFragment.java
│ │ │ └── MainPresenter.java
│ │ ├── setting
│ │ │ ├── SettingActivity.java
│ │ │ └── SettingFragment.java
│ │ └── welcome
│ │ │ └── WelcomeActivity.java
│ │ ├── utils
│ │ ├── CommonUtils.java
│ │ ├── DbUtils.java
│ │ ├── PackageUtils.java
│ │ └── SettingUtils.java
│ │ └── widget
│ │ ├── BaseActivity.java
│ │ ├── BaseFragment.java
│ │ ├── BaseListFragment.java
│ │ └── BaseViewHolder.java
│ └── res
│ ├── drawable-xhdpi
│ └── ic_add_white_24dp.png
│ ├── drawable-xxhdpi
│ ├── ic_add_white_24dp.png
│ └── ic_navigate_next_black_24dp.png
│ ├── drawable-xxxhdpi
│ └── ic_add_white_24dp.png
│ ├── layout
│ ├── activity_applist.xml
│ ├── activity_main.xml
│ ├── activity_setting.xml
│ ├── fragment_main.xml
│ ├── item_applist.xml
│ ├── item_detail.xml
│ ├── item_main.xml
│ ├── nb_base_list_fragment.xml
│ ├── nb_empty_view.xml
│ ├── nb_preference_screen.xml
│ └── nb_progress_view.xml
│ ├── menu
│ └── menu_main.xml
│ ├── mipmap-xhdpi
│ └── ic_launcher.png
│ ├── mipmap-xxhdpi
│ └── ic_launcher.png
│ ├── mipmap-xxxhdpi
│ └── ic_launcher.png
│ ├── values-v21
│ └── styles.xml
│ ├── values-zh-rCN
│ └── strings.xml
│ ├── values-zh-rHK
│ └── strings.xml
│ ├── values
│ ├── colors.xml
│ ├── dimens.xml
│ ├── ids.xml
│ ├── strings.xml
│ └── styles.xml
│ └── xml
│ └── setting.xml
├── build.gradle
├── screenshots.png
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | #Android generated
2 | bin
3 | gen
4 | gen*
5 |
6 | #Eclipse
7 | .project
8 | .classpath
9 | .settings
10 |
11 | #IntelliJ IDEA
12 | .idea
13 | *.iml
14 | *.ipr
15 | *.iws
16 | out
17 |
18 | #Maven
19 | target
20 | release.properties
21 | pom.xml.*
22 |
23 | #Ant
24 | build.xml
25 | local.properties
26 | proguard.cfg
27 |
28 | #Gradle
29 | .gradle
30 | build
31 | gradle.properties
32 | gradle/
33 | gradlew
34 | gradlew.bat
35 |
36 | #OSX
37 | .DS_Store
38 |
39 | #Personal Files
40 | signing.
41 |
42 | # Built application files
43 | *.apk
44 | *.ap_
45 |
46 | # Files for the Dalvik VM
47 | *.dex
48 |
49 | # Java class files
50 | *.class
51 |
52 | # Generated files
53 | bin/
54 | gen/
55 |
56 | # Gradle files
57 | .gradle/
58 | build/
59 |
60 | # Local configuration file (sdk path, etc)
61 | local.properties
62 |
63 | # Proguard folder generated by Eclipse
64 | proguard/
65 |
66 | # Log Files
67 | *.log
68 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 Liu Yunlong
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # NotificationBox
2 |
3 | 
4 |
5 | 
6 |
7 | ## Download
8 |
9 | - [Github Release](https://github.com/gavinliu/NotificationBox/releases)
10 |
11 | ## Features
12 |
13 | * Block notification
14 | * Notification history list
15 | * Support android device 19+
16 |
17 | ## Todo
18 |
19 | * Save ``PendingIntent`` (save notification action)
20 |
21 | ## Acknowledgements
22 |
23 | - [RxAndroid](https://github.com/ReactiveX/RxAndroid)
24 | - [LiteOrm](https://github.com/litesuits/android-lite-orm)
25 | - [android-architecture](https://github.com/googlesamples/android-architecture)
26 |
27 | ## License
28 |
29 | MIT
30 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 24
5 | buildToolsVersion "24.0.2"
6 | defaultConfig {
7 | applicationId "cn.gavinliu.notificationbox"
8 | minSdkVersion 19
9 | targetSdkVersion 24
10 | versionCode 1
11 | versionName "1.0"
12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile fileTree(include: ['*.jar'], dir: 'libs')
24 | compile 'com.android.support:appcompat-v7:24.2.1'
25 | compile 'com.android.support:preference-v7:24.2.1'
26 | compile 'com.android.support:recyclerview-v7:24.2.1'
27 | compile 'com.android.support:design:24.2.1'
28 |
29 | compile 'io.reactivex:rxandroid:1.2.1'
30 | compile 'io.reactivex:rxjava:1.1.6'
31 | }
32 |
--------------------------------------------------------------------------------
/app/libs/lite-orm-1.9.2.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gavinliu/NotificationBox/d2844df1c7a5e3f2e1aabd40c57c9201a2715d79/app/libs/lite-orm-1.9.2.jar
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/Gavin/Develop/android-sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
12 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
29 |
30 |
31 |
32 |
33 |
34 |
37 |
38 |
40 |
41 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/gavinliu/notificationbox/NotificationBoxApp.java:
--------------------------------------------------------------------------------
1 | package cn.gavinliu.notificationbox;
2 |
3 | import android.app.Application;
4 | import android.content.Context;
5 |
6 | import com.litesuits.orm.LiteOrm;
7 |
8 | /**
9 | * Created by Gavin on 2016/10/11.
10 | */
11 |
12 | public class NotificationBoxApp extends Application {
13 |
14 | private static Context sAppContext;
15 |
16 | private volatile static LiteOrm sLiteOrm;
17 |
18 | @Override
19 | protected void attachBaseContext(Context base) {
20 | super.attachBaseContext(base);
21 | sAppContext = base;
22 | }
23 |
24 | @Override
25 | public void onCreate() {
26 | super.onCreate();
27 | }
28 |
29 | public static Context get() {
30 | return sAppContext;
31 | }
32 |
33 | public static LiteOrm getLiteOrm() {
34 | if (sLiteOrm == null) {
35 | synchronized (NotificationBoxApp.class) {
36 | if (sLiteOrm == null) {
37 | sLiteOrm = LiteOrm.newSingleInstance(sAppContext, "box.db");
38 | sLiteOrm.setDebugged(true);
39 | }
40 | }
41 | }
42 | return sLiteOrm;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/gavinliu/notificationbox/model/AppInfo.java:
--------------------------------------------------------------------------------
1 | package cn.gavinliu.notificationbox.model;
2 |
3 | import android.graphics.drawable.Drawable;
4 |
5 | import com.litesuits.orm.db.annotation.Column;
6 | import com.litesuits.orm.db.annotation.Ignore;
7 | import com.litesuits.orm.db.annotation.NotNull;
8 | import com.litesuits.orm.db.annotation.PrimaryKey;
9 | import com.litesuits.orm.db.annotation.Table;
10 | import com.litesuits.orm.db.enums.AssignType;
11 |
12 | /**
13 | * Created by Gavin on 2016/10/11.
14 | */
15 | @Table("apps")
16 | public class AppInfo {
17 |
18 | @PrimaryKey(AssignType.AUTO_INCREMENT)
19 | @Column("_id")
20 | private int id;
21 |
22 | @NotNull
23 | private String packageName;
24 |
25 | @NotNull
26 | private String appName;
27 |
28 | @Ignore
29 | private Drawable icon;
30 |
31 | @Ignore
32 | private boolean isSelect;
33 |
34 | public int getId() {
35 | return id;
36 | }
37 |
38 | public void setId(int id) {
39 | this.id = id;
40 | }
41 |
42 | public String getPackageName() {
43 | return packageName;
44 | }
45 |
46 | public void setPackageName(String packageName) {
47 | this.packageName = packageName;
48 | }
49 |
50 | public String getAppName() {
51 | return appName;
52 | }
53 |
54 | public void setAppName(String appName) {
55 | this.appName = appName;
56 | }
57 |
58 | public Drawable getIcon() {
59 | return icon;
60 | }
61 |
62 | public void setIcon(Drawable icon) {
63 | this.icon = icon;
64 | }
65 |
66 | public boolean isSelect() {
67 | return isSelect;
68 | }
69 |
70 | public void setSelect(boolean select) {
71 | isSelect = select;
72 | }
73 |
74 | @Override
75 | public boolean equals(Object obj) {
76 | if (obj instanceof AppInfo) {
77 | AppInfo o = (AppInfo) obj;
78 | if (o.getPackageName().equals(packageName)) {
79 | return true;
80 | } else {
81 | return false;
82 | }
83 | }
84 |
85 | return super.equals(obj);
86 | }
87 |
88 | @Override
89 | public int hashCode() {
90 | return super.hashCode() + packageName.hashCode();
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/gavinliu/notificationbox/model/ModelSource.java:
--------------------------------------------------------------------------------
1 | package cn.gavinliu.notificationbox.model;
2 |
3 | /**
4 | * Created by Gavin on 2016/10/13.
5 | */
6 |
7 | public class ModelSource {
8 | }
9 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/gavinliu/notificationbox/model/NotificationInfo.java:
--------------------------------------------------------------------------------
1 | package cn.gavinliu.notificationbox.model;
2 |
3 | import android.content.Intent;
4 |
5 | import com.litesuits.orm.db.annotation.Column;
6 | import com.litesuits.orm.db.annotation.Ignore;
7 | import com.litesuits.orm.db.annotation.NotNull;
8 | import com.litesuits.orm.db.annotation.PrimaryKey;
9 | import com.litesuits.orm.db.annotation.Table;
10 | import com.litesuits.orm.db.enums.AssignType;
11 |
12 | /**
13 | * Created by Gavin on 2016/10/11.
14 | */
15 | @Table("notifications")
16 | public class NotificationInfo {
17 |
18 | @PrimaryKey(AssignType.AUTO_INCREMENT)
19 | @Column("_id")
20 | private int id;
21 |
22 | @NotNull
23 | private String packageName;
24 |
25 | private String title;
26 |
27 | private String text;
28 |
29 | private long time;
30 |
31 | @Ignore
32 | private Intent mIntent;
33 |
34 | public NotificationInfo(String packageName, String title, String text, long time) {
35 | this.packageName = packageName;
36 | this.title = title;
37 | this.text = text;
38 | this.time = time;
39 | }
40 |
41 | public int getId() {
42 | return id;
43 | }
44 |
45 | public void setId(int id) {
46 | this.id = id;
47 | }
48 |
49 | public String getPackageName() {
50 | return packageName;
51 | }
52 |
53 | public void setPackageName(String packageName) {
54 | this.packageName = packageName;
55 | }
56 |
57 | public String getTitle() {
58 | return title;
59 | }
60 |
61 | public void setTitle(String title) {
62 | this.title = title;
63 | }
64 |
65 | public String getText() {
66 | return text;
67 | }
68 |
69 | public void setText(String text) {
70 | this.text = text;
71 | }
72 |
73 | public long getTime() {
74 | return time;
75 | }
76 |
77 | public void setTime(long time) {
78 | this.time = time;
79 | }
80 |
81 | public Intent getIntent() {
82 | return mIntent;
83 | }
84 |
85 | public void setIntent(Intent intent) {
86 | mIntent = intent;
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/gavinliu/notificationbox/service/NotificationListenerService.java:
--------------------------------------------------------------------------------
1 | package cn.gavinliu.notificationbox.service;
2 |
3 | import android.app.Notification;
4 | import android.app.NotificationManager;
5 | import android.app.PendingIntent;
6 | import android.content.Intent;
7 | import android.os.Build;
8 | import android.os.IBinder;
9 | import android.service.notification.StatusBarNotification;
10 | import android.util.Log;
11 | import android.widget.Toast;
12 |
13 | import java.util.List;
14 |
15 | import cn.gavinliu.notificationbox.NotificationBoxApp;
16 | import cn.gavinliu.notificationbox.R;
17 | import cn.gavinliu.notificationbox.model.AppInfo;
18 | import cn.gavinliu.notificationbox.model.NotificationInfo;
19 | import cn.gavinliu.notificationbox.ui.detail.DetailActivity;
20 | import cn.gavinliu.notificationbox.utils.DbUtils;
21 | import cn.gavinliu.notificationbox.utils.SettingUtils;
22 |
23 | /**
24 | * Created by Gavin on 2016/10/11.
25 | */
26 |
27 | public class NotificationListenerService extends android.service.notification.NotificationListenerService {
28 |
29 | private static final String TAG = "NLS";
30 |
31 | @Override
32 | public IBinder onBind(Intent intent) {
33 | Log.d(TAG, "onBind");
34 | return super.onBind(intent);
35 | }
36 |
37 | @Override
38 | public boolean onUnbind(Intent intent) {
39 | Log.d(TAG, "onUnbind");
40 | return super.onUnbind(intent);
41 | }
42 |
43 | @Override
44 | public void onCreate() {
45 | super.onCreate();
46 | Log.d(TAG, "onCreate");
47 | }
48 |
49 | @Override
50 | public void onDestroy() {
51 | super.onDestroy();
52 | Log.d(TAG, "onDestroy");
53 | }
54 |
55 | @Override
56 | public int onStartCommand(Intent intent, int flags, int startId) {
57 | Log.d(TAG, "onStartCommand");
58 | return super.onStartCommand(intent, flags, startId);
59 | }
60 |
61 | @Override
62 | public void onNotificationPosted(StatusBarNotification sbn) {
63 | super.onNotificationPosted(sbn);
64 | Log.d(TAG, "onNotificationPosted");
65 |
66 | Notification notification = sbn.getNotification();
67 |
68 | String packageName = sbn.getPackageName();
69 | long time = sbn.getPostTime();
70 | String title = notification.extras.getString(Notification.EXTRA_TITLE);
71 | String text = notification.extras.getString(Notification.EXTRA_TEXT);
72 |
73 | DbUtils.saveNotification(new NotificationInfo(packageName, title, text, time));
74 | List blackList = DbUtils.getApp();
75 |
76 | for (AppInfo app : blackList) {
77 | if (packageName.equals(app.getPackageName())) {
78 | Log.d(TAG, packageName + " 拦截:" + title + ": " + text);
79 |
80 | if (android.os.Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT_WATCH) {
81 | cancelNotification(sbn.getKey());
82 | } else {
83 | cancelNotification(sbn.getPackageName(), sbn.getTag(), sbn.getId());
84 | }
85 |
86 | if (SettingUtils.getInstance().isNotify()) {
87 | createNotification(app.getAppName(), packageName, title, text);
88 | }
89 | }
90 | }
91 | }
92 |
93 | @Override
94 | public void onNotificationRemoved(StatusBarNotification sbn) {
95 | super.onNotificationRemoved(sbn);
96 | }
97 |
98 | private void createNotification(String appName, String packageName, String title, String text) {
99 |
100 | Intent intent = new Intent(this, DetailActivity.class);
101 | intent.putExtra("appName", appName);
102 | intent.putExtra("packageName", packageName);
103 |
104 | PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
105 |
106 | Notification.Builder notifyBuilder = new Notification.Builder(this)
107 | .setSmallIcon(R.mipmap.ic_launcher)
108 | .setWhen(System.currentTimeMillis())
109 | .setContentTitle(getResources().getString(R.string.notify_blocking, appName))
110 | .setContentText(title + ": " + text)
111 | .setContentIntent(contentIntent)
112 | .setDefaults(Notification.DEFAULT_LIGHTS);
113 |
114 | NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
115 |
116 | Notification notification = notifyBuilder.build();
117 | notification.flags |= Notification.FLAG_AUTO_CANCEL;
118 |
119 | nm.notify(R.string.app_name, notification);
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/gavinliu/notificationbox/ui/BasePresenter.java:
--------------------------------------------------------------------------------
1 | package cn.gavinliu.notificationbox.ui;
2 |
3 | /**
4 | * Created by Gavin on 2016/10/11.
5 | */
6 |
7 | public interface BasePresenter {
8 |
9 | void start();
10 |
11 | void subscribe();
12 |
13 | void unsubscribe();
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/gavinliu/notificationbox/ui/BaseView.java:
--------------------------------------------------------------------------------
1 | package cn.gavinliu.notificationbox.ui;
2 |
3 | /**
4 | * Created by Gavin on 2016/10/11.
5 | */
6 |
7 | public interface BaseView {
8 |
9 | void setPresenter(T presenter);
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/gavinliu/notificationbox/ui/applist/AppListActivity.java:
--------------------------------------------------------------------------------
1 | package cn.gavinliu.notificationbox.ui.applist;
2 |
3 | import android.os.Bundle;
4 | import android.support.annotation.Nullable;
5 | import android.support.v7.app.AppCompatActivity;
6 |
7 | import cn.gavinliu.notificationbox.R;
8 |
9 | /**
10 | * Created by Gavin on 16-10-17.
11 | */
12 |
13 | public class AppListActivity extends AppCompatActivity {
14 |
15 | @Override
16 | protected void onCreate(@Nullable Bundle savedInstanceState) {
17 | super.onCreate(savedInstanceState);
18 | setContentView(R.layout.activity_applist);
19 |
20 | AppListFragment appListFragment = (AppListFragment) getSupportFragmentManager()
21 | .findFragmentById(R.id.fragment_applist);
22 |
23 | if (appListFragment == null) {
24 | appListFragment = AppListFragment.newInstance();
25 |
26 | getSupportFragmentManager().beginTransaction()
27 | .add(R.id.content, appListFragment)
28 | .commit();
29 | }
30 |
31 | new AppListPresenter(appListFragment);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/gavinliu/notificationbox/ui/applist/AppListContract.java:
--------------------------------------------------------------------------------
1 | package cn.gavinliu.notificationbox.ui.applist;
2 |
3 | import android.content.pm.PackageManager;
4 |
5 | import java.util.List;
6 |
7 | import cn.gavinliu.notificationbox.model.AppInfo;
8 | import cn.gavinliu.notificationbox.ui.BasePresenter;
9 | import cn.gavinliu.notificationbox.ui.BaseView;
10 |
11 | /**
12 | * Created by Gavin on 16-10-17.
13 | */
14 |
15 | public interface AppListContract {
16 |
17 | interface Presenter extends BasePresenter {
18 |
19 | void startLoad(PackageManager pm);
20 |
21 | void saveApp(AppInfo app);
22 |
23 | void deleteApp(AppInfo app);
24 | }
25 |
26 | interface View extends BaseView {
27 |
28 | void showProgress(boolean isShown);
29 |
30 | void showAppList(List appList);
31 |
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/gavinliu/notificationbox/ui/applist/AppListFragment.java:
--------------------------------------------------------------------------------
1 | package cn.gavinliu.notificationbox.ui.applist;
2 |
3 | import android.content.Context;
4 | import android.os.Bundle;
5 | import android.support.annotation.Nullable;
6 | import android.support.v7.app.ActionBar;
7 | import android.support.v7.widget.RecyclerView;
8 | import android.view.LayoutInflater;
9 | import android.view.View;
10 | import android.view.ViewGroup;
11 | import android.widget.CheckBox;
12 | import android.widget.ImageView;
13 | import android.widget.TextView;
14 |
15 | import java.util.List;
16 |
17 | import cn.gavinliu.notificationbox.R;
18 | import cn.gavinliu.notificationbox.model.AppInfo;
19 | import cn.gavinliu.notificationbox.widget.BaseListFragment;
20 | import cn.gavinliu.notificationbox.widget.BaseViewHolder;
21 |
22 | /**
23 | * Created by Gavin on 16-10-17.
24 | */
25 |
26 | public class AppListFragment extends BaseListFragment implements AppListContract.View {
27 |
28 | public static AppListFragment newInstance() {
29 | AppListFragment fragment = new AppListFragment();
30 | return fragment;
31 | }
32 |
33 | private AppListContract.Presenter mPresenter;
34 |
35 | @Override
36 | public void setPresenter(AppListContract.Presenter presenter) {
37 | mPresenter = presenter;
38 | }
39 |
40 | @Override
41 | public void onActivityCreated(@Nullable Bundle savedInstanceState) {
42 | super.onActivityCreated(savedInstanceState);
43 | if (mPresenter != null) mPresenter.startLoad(getActivity().getPackageManager());
44 | }
45 |
46 | @Override
47 | public void setupActionBar(ActionBar actionBar) {
48 | actionBar.setDisplayHomeAsUpEnabled(true);
49 | }
50 |
51 | @Override
52 | public void onDestroy() {
53 | super.onDestroy();
54 | if (mPresenter != null) mPresenter.unsubscribe();
55 | getActivity().setResult(0);
56 | }
57 |
58 | @Override
59 | public void showProgress(boolean isShown) {
60 | if (isShown) {
61 | showProgressView();
62 | } else {
63 | hideProgressView();
64 | }
65 | }
66 |
67 | @Override
68 | public void showAppList(List appList) {
69 | mRecyclerView.setAdapter(new Adapter(getContext(), appList, mItemListener));
70 | }
71 |
72 | private ItemListener mItemListener = new ItemListener() {
73 | @Override
74 | public void onCheckBoxSelect(boolean isChecked, AppInfo app) {
75 | if (isChecked) {
76 | mPresenter.saveApp(app);
77 | } else {
78 | mPresenter.deleteApp(app);
79 | }
80 | }
81 | };
82 |
83 | private static class Adapter extends RecyclerView.Adapter {
84 |
85 | Context context;
86 | List appList;
87 | private ItemListener itemListener;
88 |
89 | public Adapter(Context context, List appList, ItemListener itemListener) {
90 | this.context = context;
91 | this.appList = appList;
92 | this.itemListener = itemListener;
93 | }
94 |
95 | @Override
96 | public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
97 | return new ViewHolder(LayoutInflater.from(context).inflate(R.layout.item_applist, parent, false));
98 | }
99 |
100 | @Override
101 | public void onBindViewHolder(ViewHolder holder, int position) {
102 | final AppInfo app = appList.get(position);
103 |
104 | holder.mIconView.setImageDrawable(app.getIcon());
105 | holder.mNameView.setText(app.getAppName());
106 | holder.mCheckBox.setChecked(app.isSelect());
107 |
108 | holder.mCheckBox.setOnClickListener(new View.OnClickListener() {
109 | @Override
110 | public void onClick(View v) {
111 | boolean isChecked = ((CheckBox) v).isChecked();
112 | app.setSelect(isChecked);
113 | itemListener.onCheckBoxSelect(isChecked, app);
114 | }
115 | });
116 | }
117 |
118 | @Override
119 | public int getItemCount() {
120 | return appList != null ? appList.size() : 0;
121 | }
122 | }
123 |
124 | private static class ViewHolder extends BaseViewHolder {
125 |
126 | private ImageView mIconView;
127 | private TextView mNameView;
128 | private CheckBox mCheckBox;
129 |
130 |
131 | public ViewHolder(View itemView) {
132 | super(itemView);
133 |
134 | mIconView = (ImageView) itemView.findViewById(R.id.icon);
135 | mNameView = (TextView) itemView.findViewById(R.id.name);
136 | mCheckBox = (CheckBox) itemView.findViewById(R.id.checkbox);
137 | }
138 | }
139 |
140 | private interface ItemListener {
141 | void onCheckBoxSelect(boolean isChecked, AppInfo app);
142 | }
143 |
144 | }
145 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/gavinliu/notificationbox/ui/applist/AppListPresenter.java:
--------------------------------------------------------------------------------
1 | package cn.gavinliu.notificationbox.ui.applist;
2 |
3 | import android.content.Intent;
4 | import android.content.pm.PackageManager;
5 |
6 | import java.util.List;
7 |
8 | import cn.gavinliu.notificationbox.model.AppInfo;
9 | import cn.gavinliu.notificationbox.utils.DbUtils;
10 | import cn.gavinliu.notificationbox.utils.PackageUtils;
11 | import rx.Observable;
12 | import rx.Observer;
13 | import rx.Scheduler;
14 | import rx.Subscriber;
15 | import rx.Subscription;
16 | import rx.android.schedulers.AndroidSchedulers;
17 | import rx.schedulers.Schedulers;
18 | import rx.subscriptions.CompositeSubscription;
19 |
20 | /**
21 | * Created by Gavin on 16-10-17.
22 | */
23 |
24 | public class AppListPresenter implements AppListContract.Presenter {
25 |
26 | private AppListContract.View mView;
27 |
28 | private CompositeSubscription mSubscriptions;
29 |
30 | public AppListPresenter(AppListContract.View view) {
31 | mView = view;
32 |
33 | mSubscriptions = new CompositeSubscription();
34 | mView.setPresenter(this);
35 | }
36 |
37 | @Override
38 | public void start() {
39 |
40 | }
41 |
42 | @Override
43 | public void startLoad(PackageManager pm) {
44 | mView.showProgress(true);
45 | Subscription subscription = PackageUtils.getInstallPackages(pm)
46 | .subscribeOn(Schedulers.io())
47 | .observeOn(AndroidSchedulers.mainThread())
48 | .subscribe(new Observer>() {
49 | @Override
50 | public void onCompleted() {
51 |
52 | }
53 |
54 | @Override
55 | public void onError(Throwable e) {
56 |
57 | }
58 |
59 | @Override
60 | public void onNext(List list) {
61 | mView.showProgress(false);
62 | mView.showAppList(list);
63 | }
64 | });
65 |
66 | mSubscriptions.add(subscription);
67 | }
68 |
69 | @Override
70 | public void subscribe() {
71 |
72 | }
73 |
74 | @Override
75 | public void unsubscribe() {
76 | mSubscriptions.clear();
77 | }
78 |
79 |
80 | @Override
81 | public void saveApp(AppInfo app) {
82 | DbUtils.saveApp(app);
83 | }
84 |
85 | @Override
86 | public void deleteApp(AppInfo app) {
87 | DbUtils.deleteApp(app);
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/gavinliu/notificationbox/ui/detail/DetailActivity.java:
--------------------------------------------------------------------------------
1 | package cn.gavinliu.notificationbox.ui.detail;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.support.annotation.Nullable;
6 | import android.support.v7.app.AppCompatActivity;
7 |
8 | import cn.gavinliu.notificationbox.R;
9 |
10 | /**
11 | * Created by Gavin on 2016/10/11.
12 | */
13 |
14 | public class DetailActivity extends AppCompatActivity {
15 |
16 | @Override
17 | protected void onCreate(@Nullable Bundle savedInstanceState) {
18 | super.onCreate(savedInstanceState);
19 | setContentView(R.layout.activity_applist);
20 |
21 | DetailFragment detailFragment = (DetailFragment) getSupportFragmentManager()
22 | .findFragmentById(R.id.fragment_applist);
23 |
24 | if (detailFragment == null) {
25 | Intent intent = getIntent();
26 | Bundle bundle = intent.getExtras();
27 | detailFragment = DetailFragment.newInstance(bundle.getString("appName"), bundle.getString("packageName"));
28 |
29 | getSupportFragmentManager().beginTransaction()
30 | .add(R.id.content, detailFragment)
31 | .commit();
32 | }
33 |
34 | new DetailPresenter(detailFragment);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/gavinliu/notificationbox/ui/detail/DetailContract.java:
--------------------------------------------------------------------------------
1 | package cn.gavinliu.notificationbox.ui.detail;
2 |
3 | import java.util.List;
4 |
5 | import cn.gavinliu.notificationbox.model.NotificationInfo;
6 | import cn.gavinliu.notificationbox.ui.BasePresenter;
7 | import cn.gavinliu.notificationbox.ui.BaseView;
8 |
9 | /**
10 | * Created by Gavin on 16-10-17.
11 | */
12 |
13 | public interface DetailContract {
14 |
15 | interface Presenter extends BasePresenter {
16 |
17 | void startLoad(String packageName);
18 |
19 | }
20 |
21 | interface View extends BaseView {
22 |
23 | void showProgress(boolean isShown);
24 |
25 | void showEmpty();
26 |
27 | void showNotifications(List notifications);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/gavinliu/notificationbox/ui/detail/DetailFragment.java:
--------------------------------------------------------------------------------
1 | package cn.gavinliu.notificationbox.ui.detail;
2 |
3 | import android.content.Context;
4 | import android.os.Bundle;
5 | import android.support.annotation.Nullable;
6 | import android.support.v7.app.ActionBar;
7 | import android.support.v7.widget.RecyclerView;
8 | import android.util.Log;
9 | import android.view.LayoutInflater;
10 | import android.view.View;
11 | import android.view.ViewGroup;
12 | import android.widget.TextView;
13 |
14 | import java.util.List;
15 |
16 | import cn.gavinliu.notificationbox.R;
17 | import cn.gavinliu.notificationbox.model.NotificationInfo;
18 | import cn.gavinliu.notificationbox.utils.CommonUtils;
19 | import cn.gavinliu.notificationbox.widget.BaseListFragment;
20 | import cn.gavinliu.notificationbox.widget.BaseViewHolder;
21 |
22 | /**
23 | * Created by Gavin on 2016/10/11.
24 | */
25 |
26 | public class DetailFragment extends BaseListFragment implements DetailContract.View {
27 |
28 | DetailContract.Presenter mPresenter;
29 |
30 | private String mAppName;
31 | private String mPackageName;
32 |
33 | public static DetailFragment newInstance(String appName, String packageName) {
34 | if (appName == null || packageName == null) {
35 | throw new IllegalArgumentException("appName and packageName can not is null");
36 | }
37 |
38 | Bundle args = new Bundle();
39 | args.putString("appName", appName);
40 | args.putString("packageName", packageName);
41 |
42 | DetailFragment fragment = new DetailFragment();
43 | fragment.setArguments(args);
44 | return fragment;
45 | }
46 |
47 | @Override
48 | public void onActivityCreated(@Nullable Bundle savedInstanceState) {
49 | super.onActivityCreated(savedInstanceState);
50 | if (mPresenter != null) mPresenter.startLoad(mPackageName);
51 | }
52 |
53 | @Override
54 | public void onDestroy() {
55 | super.onDestroy();
56 | if (mPresenter != null) mPresenter.unsubscribe();
57 | }
58 |
59 | @Override
60 | public void getArguments(Bundle bundle) {
61 | if (bundle != null) {
62 | mAppName = bundle.getString("appName");
63 | mPackageName = bundle.getString("packageName");
64 | }
65 | }
66 |
67 | @Override
68 | public void setupActionBar(ActionBar actionBar) {
69 | actionBar.setTitle(mAppName);
70 | actionBar.setDisplayHomeAsUpEnabled(true);
71 | }
72 |
73 | @Override
74 | public void showProgress(boolean isShown) {
75 | if (isShown) {
76 | showProgressView();
77 | } else {
78 | hideProgressView();
79 | }
80 | }
81 |
82 | @Override
83 | public void showEmpty() {
84 | hideProgressView();
85 | showEmptyView();
86 | setEmptyText(getText(R.string.empty_detail));
87 | }
88 |
89 | @Override
90 | public void showNotifications(List notifications) {
91 | mRecyclerView.setAdapter(new Adapter(getContext(), notifications));
92 | }
93 |
94 | @Override
95 | public void setPresenter(DetailContract.Presenter presenter) {
96 | mPresenter = presenter;
97 | }
98 |
99 |
100 | private static class Adapter extends RecyclerView.Adapter {
101 |
102 | Context context;
103 | List notificationList;
104 |
105 | public Adapter(Context context, List notificationList) {
106 | this.context = context;
107 | this.notificationList = notificationList;
108 | }
109 |
110 | @Override
111 | public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
112 | return new ViewHolder(LayoutInflater.from(context).inflate(R.layout.item_detail, parent, false));
113 | }
114 |
115 | @Override
116 | public void onBindViewHolder(ViewHolder holder, int position) {
117 | NotificationInfo notification = notificationList.get(position);
118 | holder.title.setText(notification.getTitle());
119 | holder.text.setText(notification.getText());
120 | holder.time.setText(CommonUtils.getTimeStr(notification.getTime()));
121 | }
122 |
123 | @Override
124 | public int getItemCount() {
125 | return notificationList != null ? notificationList.size() : 0;
126 | }
127 | }
128 |
129 |
130 | private static class ViewHolder extends BaseViewHolder {
131 |
132 | TextView title;
133 | TextView text;
134 | TextView time;
135 |
136 | public ViewHolder(View itemView) {
137 | super(itemView);
138 | title = (TextView) itemView.findViewById(R.id.title);
139 | text = (TextView) itemView.findViewById(R.id.text);
140 | time = (TextView) itemView.findViewById(R.id.time);
141 | }
142 | }
143 |
144 | }
145 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/gavinliu/notificationbox/ui/detail/DetailPresenter.java:
--------------------------------------------------------------------------------
1 | package cn.gavinliu.notificationbox.ui.detail;
2 |
3 | import java.util.List;
4 |
5 | import cn.gavinliu.notificationbox.model.NotificationInfo;
6 | import cn.gavinliu.notificationbox.utils.DbUtils;
7 | import rx.subscriptions.CompositeSubscription;
8 |
9 | /**
10 | * Created by Gavin on 16-10-17.
11 | */
12 |
13 | public class DetailPresenter implements DetailContract.Presenter {
14 |
15 | DetailContract.View mView;
16 |
17 | private CompositeSubscription mSubscriptions;
18 |
19 | public DetailPresenter(DetailContract.View view) {
20 | mView = view;
21 |
22 | mSubscriptions = new CompositeSubscription();
23 | mView.setPresenter(this);
24 | }
25 |
26 | @Override
27 | public void start() {
28 |
29 | }
30 |
31 | @Override
32 | public void startLoad(String packageName) {
33 | mView.showProgress(false);
34 |
35 | List infos = DbUtils.getNotification(packageName);
36 |
37 | if (infos == null || infos.size() == 0) {
38 | mView.showEmpty();
39 | } else {
40 | mView.showNotifications(infos);
41 | }
42 | }
43 |
44 | @Override
45 | public void subscribe() {
46 |
47 | }
48 |
49 | @Override
50 | public void unsubscribe() {
51 | mSubscriptions.unsubscribe();
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/gavinliu/notificationbox/ui/main/MainActivity.java:
--------------------------------------------------------------------------------
1 | package cn.gavinliu.notificationbox.ui.main;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.support.design.widget.FloatingActionButton;
6 | import android.support.design.widget.Snackbar;
7 | import android.support.v4.app.Fragment;
8 | import android.support.v7.app.AppCompatActivity;
9 | import android.support.v7.widget.Toolbar;
10 | import android.view.Menu;
11 | import android.view.MenuItem;
12 | import android.view.View;
13 |
14 | import cn.gavinliu.notificationbox.R;
15 | import cn.gavinliu.notificationbox.service.NotificationListenerService;
16 | import cn.gavinliu.notificationbox.ui.setting.SettingActivity;
17 | import cn.gavinliu.notificationbox.utils.CommonUtils;
18 |
19 | public class MainActivity extends AppCompatActivity {
20 |
21 | FloatingActionButton mFloatingActionButton;
22 | private MainPresenter mMainPresenter;
23 |
24 | @Override
25 | protected void onCreate(Bundle savedInstanceState) {
26 | super.onCreate(savedInstanceState);
27 | setContentView(R.layout.activity_main);
28 |
29 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
30 | setSupportActionBar(toolbar);
31 |
32 | mFloatingActionButton = (FloatingActionButton) findViewById(R.id.fab);
33 | mFloatingActionButton.setOnClickListener(new View.OnClickListener() {
34 | @Override
35 | public void onClick(View view) {
36 | mMainPresenter.addApp();
37 | }
38 | });
39 |
40 | MainFragment mainFragment = (MainFragment) getSupportFragmentManager()
41 | .findFragmentById(R.id.fragment_main);
42 |
43 | if (mainFragment == null) {
44 | mainFragment = MainFragment.newInstance();
45 |
46 | getSupportFragmentManager().beginTransaction()
47 | .add(R.id.content, mainFragment)
48 | .commit();
49 | }
50 |
51 | mMainPresenter = new MainPresenter(mainFragment);
52 | }
53 |
54 | @Override
55 | protected void onResume() {
56 | super.onResume();
57 | if (!CommonUtils.checkNotificationReadPermission(this)) {
58 | Snackbar.make(mFloatingActionButton, getText(R.string.no_read_notification_promission), Snackbar.LENGTH_INDEFINITE)
59 | .setAction(getText(R.string.action_settings), new View.OnClickListener() {
60 | @Override
61 | public void onClick(View v) {
62 | Intent intent = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
63 | startActivity(intent);
64 | }
65 | })
66 | .show();
67 | }
68 | }
69 |
70 | @Override
71 | public boolean onCreateOptionsMenu(Menu menu) {
72 | getMenuInflater().inflate(R.menu.menu_main, menu);
73 | return true;
74 | }
75 |
76 | @Override
77 | public boolean onOptionsItemSelected(MenuItem item) {
78 | int id = item.getItemId();
79 |
80 | if (id == R.id.action_settings) {
81 | Intent intent = new Intent(this, SettingActivity.class);
82 | startActivity(intent);
83 | return true;
84 | }
85 |
86 | return super.onOptionsItemSelected(item);
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/gavinliu/notificationbox/ui/main/MainContract.java:
--------------------------------------------------------------------------------
1 | package cn.gavinliu.notificationbox.ui.main;
2 |
3 | import android.content.pm.PackageManager;
4 |
5 | import java.util.List;
6 |
7 | import cn.gavinliu.notificationbox.model.AppInfo;
8 | import cn.gavinliu.notificationbox.ui.BasePresenter;
9 | import cn.gavinliu.notificationbox.ui.BaseView;
10 |
11 | /**
12 | * Created by Gavin on 2016/10/11.
13 | */
14 |
15 | public interface MainContract {
16 |
17 | interface Presenter extends BasePresenter {
18 |
19 | void addApp();
20 |
21 | void openDetail(AppInfo app);
22 |
23 | void startLoad(PackageManager pm);
24 | }
25 |
26 | interface View extends BaseView {
27 |
28 | void showProgress(boolean isShown);
29 |
30 | void showEmpty();
31 |
32 | void showApp(List apps);
33 |
34 | void showAppList();
35 |
36 | void showDetail(String appName, String packageName);
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/gavinliu/notificationbox/ui/main/MainFragment.java:
--------------------------------------------------------------------------------
1 | package cn.gavinliu.notificationbox.ui.main;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 | import android.support.annotation.Nullable;
7 | import android.support.v7.widget.RecyclerView;
8 | import android.view.LayoutInflater;
9 | import android.view.View;
10 | import android.view.ViewGroup;
11 | import android.widget.ImageView;
12 | import android.widget.TextView;
13 |
14 | import java.util.List;
15 |
16 | import cn.gavinliu.notificationbox.R;
17 | import cn.gavinliu.notificationbox.model.AppInfo;
18 | import cn.gavinliu.notificationbox.ui.applist.AppListActivity;
19 | import cn.gavinliu.notificationbox.ui.detail.DetailActivity;
20 | import cn.gavinliu.notificationbox.widget.BaseListFragment;
21 | import cn.gavinliu.notificationbox.widget.BaseViewHolder;
22 |
23 | /**
24 | * Created by Gavin on 2016/10/11.
25 | */
26 |
27 | public class MainFragment extends BaseListFragment implements MainContract.View {
28 |
29 | MainContract.Presenter mPresenter;
30 |
31 | public static MainFragment newInstance() {
32 | Bundle args = new Bundle();
33 |
34 | MainFragment fragment = new MainFragment();
35 | fragment.setArguments(args);
36 | return fragment;
37 | }
38 |
39 | @Override
40 | public void onActivityCreated(@Nullable Bundle savedInstanceState) {
41 | super.onActivityCreated(savedInstanceState);
42 | if (mPresenter != null) mPresenter.startLoad(getActivity().getPackageManager());
43 | }
44 |
45 | @Override
46 | public void onActivityResult(int requestCode, int resultCode, Intent data) {
47 | super.onActivityResult(requestCode, resultCode, data);
48 | if (mPresenter != null) mPresenter.startLoad(getActivity().getPackageManager());
49 | }
50 |
51 | @Override
52 | public void onDestroy() {
53 | super.onDestroy();
54 | if (mPresenter != null) mPresenter.unsubscribe();
55 | }
56 |
57 | @Override
58 | public void setPresenter(MainContract.Presenter presenter) {
59 | mPresenter = presenter;
60 | }
61 |
62 | @Override
63 | public void showProgress(boolean isShown) {
64 | if (isShown) {
65 | hideEmptyView();
66 | showProgressView();
67 | } else {
68 | hideProgressView();
69 | }
70 | }
71 |
72 | @Override
73 | public void showEmpty() {
74 | hideProgressView();
75 | showEmptyView();
76 | showApp(null);
77 | setEmptyText(getText(R.string.empty_app));
78 | }
79 |
80 | @Override
81 | public void showApp(List apps) {
82 | mRecyclerView.setAdapter(new Adapter(getContext(), apps, mItemListener));
83 | }
84 |
85 | @Override
86 | public void showAppList() {
87 | Intent intent = new Intent(getContext(), AppListActivity.class);
88 | startActivityForResult(intent, 0);
89 | }
90 |
91 | @Override
92 | public void showDetail(String appName, String packageName) {
93 | Intent intent = new Intent(getContext(), DetailActivity.class);
94 | intent.putExtra("appName", appName);
95 | intent.putExtra("packageName", packageName);
96 | startActivity(intent);
97 | }
98 |
99 | private ItemListener mItemListener = new ItemListener() {
100 | @Override
101 | public void onItemClick(AppInfo app) {
102 | mPresenter.openDetail(app);
103 | }
104 | };
105 |
106 | private static class Adapter extends RecyclerView.Adapter {
107 |
108 | Context context;
109 | List appList;
110 | ItemListener itemListener;
111 |
112 | public Adapter(Context context, List appList, ItemListener itemListener) {
113 | this.context = context;
114 | this.appList = appList;
115 | this.itemListener = itemListener;
116 | }
117 |
118 | @Override
119 | public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
120 | return new ViewHolder(LayoutInflater.from(context).inflate(R.layout.item_main, parent, false));
121 | }
122 |
123 | @Override
124 | public void onBindViewHolder(ViewHolder holder, int position) {
125 | final AppInfo app = appList.get(position);
126 |
127 | holder.mIconView.setImageDrawable(app.getIcon());
128 | holder.mNameView.setText(app.getAppName());
129 |
130 | holder.itemView.setOnClickListener(new View.OnClickListener() {
131 | @Override
132 | public void onClick(View v) {
133 | itemListener.onItemClick(app);
134 | }
135 | });
136 | }
137 |
138 | @Override
139 | public int getItemCount() {
140 | return appList != null ? appList.size() : 0;
141 | }
142 | }
143 |
144 | private static class ViewHolder extends BaseViewHolder {
145 |
146 | private ImageView mIconView;
147 | private TextView mNameView;
148 |
149 |
150 | public ViewHolder(View itemView) {
151 | super(itemView);
152 |
153 | mIconView = (ImageView) itemView.findViewById(R.id.icon);
154 | mNameView = (TextView) itemView.findViewById(R.id.name);
155 | }
156 | }
157 |
158 | private interface ItemListener {
159 | void onItemClick(AppInfo app);
160 | }
161 | }
162 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/gavinliu/notificationbox/ui/main/MainPresenter.java:
--------------------------------------------------------------------------------
1 | package cn.gavinliu.notificationbox.ui.main;
2 |
3 | import android.content.pm.PackageManager;
4 |
5 | import java.util.List;
6 |
7 | import cn.gavinliu.notificationbox.model.AppInfo;
8 | import cn.gavinliu.notificationbox.utils.PackageUtils;
9 | import rx.Observer;
10 | import rx.Subscription;
11 | import rx.android.schedulers.AndroidSchedulers;
12 | import rx.schedulers.Schedulers;
13 | import rx.subscriptions.CompositeSubscription;
14 |
15 | /**
16 | * Created by Gavin on 2016/10/12.
17 | */
18 |
19 | public class MainPresenter implements MainContract.Presenter {
20 |
21 | private MainContract.View mView;
22 |
23 | private CompositeSubscription mSubscriptions;
24 |
25 | public MainPresenter(MainContract.View view) {
26 | mView = view;
27 |
28 | mSubscriptions = new CompositeSubscription();
29 | mView.setPresenter(this);
30 | }
31 |
32 | @Override
33 | public void start() {
34 |
35 | }
36 |
37 | @Override
38 | public void startLoad(PackageManager pm) {
39 | mView.showProgress(true);
40 |
41 | Subscription subscription = PackageUtils.getAppDbList(pm)
42 | .subscribeOn(Schedulers.io())
43 | .observeOn(AndroidSchedulers.mainThread())
44 | .subscribe(new Observer>() {
45 | @Override
46 | public void onCompleted() {
47 |
48 | }
49 |
50 | @Override
51 | public void onError(Throwable e) {
52 |
53 | }
54 |
55 | @Override
56 | public void onNext(List appInfos) {
57 | mView.showProgress(false);
58 | if (appInfos == null || appInfos.size() == 0) {
59 | mView.showEmpty();
60 | } else {
61 | mView.showApp(appInfos);
62 | }
63 |
64 | }
65 | });
66 |
67 | mSubscriptions.add(subscription);
68 | }
69 |
70 | @Override
71 | public void openDetail(AppInfo app) {
72 | mView.showDetail(app.getAppName(), app.getPackageName());
73 | }
74 |
75 | @Override
76 | public void subscribe() {
77 |
78 | }
79 |
80 | @Override
81 | public void unsubscribe() {
82 | mSubscriptions.unsubscribe();
83 | }
84 |
85 | @Override
86 | public void addApp() {
87 | mView.showAppList();
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/gavinliu/notificationbox/ui/setting/SettingActivity.java:
--------------------------------------------------------------------------------
1 | package cn.gavinliu.notificationbox.ui.setting;
2 |
3 | import android.os.Bundle;
4 | import android.support.annotation.Nullable;
5 | import android.view.MenuItem;
6 |
7 | import cn.gavinliu.notificationbox.R;
8 | import cn.gavinliu.notificationbox.widget.BaseActivity;
9 |
10 | /**
11 | * Created by Gavin on 2016/10/12.
12 | */
13 |
14 | public class SettingActivity extends BaseActivity {
15 |
16 | @Override
17 | protected void onCreate(@Nullable Bundle savedInstanceState) {
18 | super.onCreate(savedInstanceState);
19 | setContentView(R.layout.activity_setting);
20 | if (getSupportActionBar() != null) {
21 | getSupportActionBar().setDisplayHomeAsUpEnabled(true);
22 | }
23 | }
24 |
25 | @Override
26 | public boolean onOptionsItemSelected(MenuItem item) {
27 | switch (item.getItemId()) {
28 | case android.R.id.home:
29 | finish();
30 | break;
31 | }
32 | return super.onOptionsItemSelected(item);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/gavinliu/notificationbox/ui/setting/SettingFragment.java:
--------------------------------------------------------------------------------
1 | package cn.gavinliu.notificationbox.ui.setting;
2 |
3 | import android.content.Intent;
4 | import android.net.Uri;
5 | import android.os.Bundle;
6 | import android.support.v7.preference.Preference;
7 | import android.support.v7.preference.PreferenceFragmentCompat;
8 |
9 | import cn.gavinliu.notificationbox.R;
10 |
11 | /**
12 | * Created by Gavin on 2016/10/25.
13 | */
14 |
15 | public class SettingFragment extends PreferenceFragmentCompat {
16 |
17 | @Override
18 | public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
19 | addPreferencesFromResource(R.xml.setting);
20 | }
21 |
22 | @Override
23 | public void onActivityCreated(Bundle savedInstanceState) {
24 | super.onActivityCreated(savedInstanceState);
25 |
26 | findPreference("permission").setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
27 | @Override
28 | public boolean onPreferenceClick(Preference preference) {
29 | Intent intent = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
30 | startActivity(intent);
31 | return true;
32 | }
33 | });
34 |
35 | findPreference("openSource").setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
36 | @Override
37 | public boolean onPreferenceClick(Preference preference) {
38 | Intent intent = new Intent();
39 | intent.setAction("android.intent.action.VIEW");
40 | intent.setData(Uri.parse("https://github.com/gavinliu/NotificationBox"));
41 | startActivity(intent);
42 | return true;
43 | }
44 | });
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/gavinliu/notificationbox/ui/welcome/WelcomeActivity.java:
--------------------------------------------------------------------------------
1 | package cn.gavinliu.notificationbox.ui.welcome;
2 |
3 | /**
4 | * Created by Gavin on 2016/10/11.
5 | */
6 |
7 | public class WelcomeActivity {
8 | }
9 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/gavinliu/notificationbox/utils/CommonUtils.java:
--------------------------------------------------------------------------------
1 | package cn.gavinliu.notificationbox.utils;
2 |
3 | import android.app.Activity;
4 | import android.content.ComponentName;
5 | import android.provider.Settings;
6 | import android.text.TextUtils;
7 |
8 | import java.text.SimpleDateFormat;
9 | import java.util.Date;
10 |
11 | /**
12 | * Created by Gavin on 2016/10/12.
13 | */
14 |
15 | public class CommonUtils {
16 |
17 | public static boolean checkNotificationReadPermission(Activity activity) {
18 | String notiStr = Settings.Secure.getString(activity.getContentResolver(), "enabled_notification_listeners");
19 | if (notiStr != null && !TextUtils.isEmpty(notiStr)) {
20 | final String[] names = notiStr.split(":");
21 | for (String name : names) {
22 | ComponentName cn = ComponentName.unflattenFromString(name);
23 | if (cn != null) {
24 | if (activity.getPackageName().equals(cn.getPackageName())) {
25 | return true;
26 | }
27 | }
28 | }
29 | }
30 | return false;
31 | }
32 |
33 | public static String getTimeStr(long time) {
34 | SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
35 | Date date = new Date(time);
36 | return format.format(date);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/gavinliu/notificationbox/utils/DbUtils.java:
--------------------------------------------------------------------------------
1 | package cn.gavinliu.notificationbox.utils;
2 |
3 | import com.litesuits.orm.db.assit.QueryBuilder;
4 | import com.litesuits.orm.db.assit.WhereBuilder;
5 |
6 | import java.util.List;
7 |
8 | import cn.gavinliu.notificationbox.NotificationBoxApp;
9 | import cn.gavinliu.notificationbox.model.AppInfo;
10 | import cn.gavinliu.notificationbox.model.NotificationInfo;
11 |
12 | /**
13 | * Created by Gavin on 16-10-15.
14 | */
15 |
16 | public class DbUtils {
17 |
18 | public static void saveNotification(NotificationInfo info) {
19 | if (info.getTitle() == null || info.getText() == null) return;
20 | NotificationBoxApp.getLiteOrm().save(info);
21 | }
22 |
23 | public static List getNotification(String packageName) {
24 | return NotificationBoxApp.getLiteOrm().query(new QueryBuilder(NotificationInfo.class)
25 | .where("packageName = ?", packageName).orderBy("time desc"));
26 | }
27 |
28 | public static List getApp() {
29 | return NotificationBoxApp.getLiteOrm().query(AppInfo.class);
30 | }
31 |
32 | public static void saveApp(AppInfo info) {
33 | NotificationBoxApp.getLiteOrm().save(info);
34 | }
35 |
36 | public static void deleteApp(AppInfo info) {
37 | NotificationBoxApp.getLiteOrm().delete(new WhereBuilder(AppInfo.class)
38 | .where("packageName = ?", info.getPackageName()));
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/gavinliu/notificationbox/utils/PackageUtils.java:
--------------------------------------------------------------------------------
1 | package cn.gavinliu.notificationbox.utils;
2 |
3 | import android.content.Intent;
4 | import android.content.pm.ApplicationInfo;
5 | import android.content.pm.PackageInfo;
6 | import android.content.pm.PackageManager;
7 | import android.content.pm.ResolveInfo;
8 | import android.util.Log;
9 |
10 | import java.util.ArrayList;
11 | import java.util.List;
12 |
13 | import cn.gavinliu.notificationbox.model.AppInfo;
14 | import rx.Observable;
15 | import rx.Subscriber;
16 |
17 | /**
18 | * Created by Gavin on 16-10-18.
19 | */
20 |
21 | public class PackageUtils {
22 |
23 | public static Observable> getInstallPackages(final PackageManager pm) {
24 | return Observable.create(new Observable.OnSubscribe>() {
25 | @Override
26 | public void call(Subscriber super List> subscriber) {
27 | List appInfos = new ArrayList<>();
28 |
29 | Intent intent = new Intent();
30 | intent.addCategory(Intent.CATEGORY_LAUNCHER);
31 | intent.setAction(Intent.ACTION_MAIN);
32 | List resolveInfoList = pm.queryIntentActivities(intent, 0);
33 |
34 | for (ResolveInfo info : resolveInfoList) {
35 | AppInfo app = new AppInfo();
36 | app.setIcon(info.loadIcon(pm));
37 | app.setAppName(info.loadLabel(pm).toString());
38 | app.setPackageName(info.activityInfo.packageName);
39 |
40 | appInfos.add(app);
41 | }
42 |
43 | List db = DbUtils.getApp();
44 | List temp = new ArrayList<>();
45 |
46 | for (AppInfo info : appInfos) {
47 | for (AppInfo a : db) {
48 | if (a.getPackageName().equals(info.getPackageName())) {
49 | info.setSelect(true);
50 | temp.add(info);
51 | }
52 | }
53 | }
54 |
55 | appInfos.removeAll(temp);
56 | appInfos.addAll(0, temp);
57 |
58 | subscriber.onNext(appInfos);
59 | }
60 | });
61 | }
62 |
63 | public static Observable> getAppDbList(final PackageManager pm) {
64 | return Observable.create(new Observable.OnSubscribe>() {
65 |
66 | @Override
67 | public void call(Subscriber super List> subscriber) {
68 | List appInfos = new ArrayList<>();
69 |
70 |
71 | List db = DbUtils.getApp();
72 |
73 | Intent intent = new Intent();
74 | intent.addCategory(Intent.CATEGORY_LAUNCHER);
75 | intent.setAction(Intent.ACTION_MAIN);
76 | List resolveInfoList = pm.queryIntentActivities(intent, 0);
77 |
78 | for (ResolveInfo info : resolveInfoList) {
79 | for (AppInfo app : db) {
80 | if (info.activityInfo.packageName.equals(app.getPackageName())) {
81 | app.setIcon(info.loadIcon(pm));
82 |
83 | appInfos.add(app);
84 | }
85 | }
86 | }
87 |
88 | subscriber.onNext(appInfos);
89 | }
90 | });
91 | }
92 |
93 | }
94 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/gavinliu/notificationbox/utils/SettingUtils.java:
--------------------------------------------------------------------------------
1 | package cn.gavinliu.notificationbox.utils;
2 |
3 | import android.content.Context;
4 | import android.content.SharedPreferences;
5 | import android.support.v7.preference.PreferenceManager;
6 |
7 | import cn.gavinliu.notificationbox.NotificationBoxApp;
8 |
9 | /**
10 | * Created by Gavin on 16-10-26.
11 | */
12 |
13 | public class SettingUtils {
14 |
15 | private static SettingUtils util;
16 | private SharedPreferences mPreference;
17 |
18 | private synchronized static void createInstance(Context ctx) {
19 | if (util == null) {
20 | util = new SettingUtils(ctx);
21 | }
22 | }
23 |
24 | public static SettingUtils getInstance() {
25 | if (util == null) {
26 | createInstance(NotificationBoxApp.get());
27 | }
28 | return util;
29 | }
30 |
31 | private SettingUtils(Context ctx) {
32 | mPreference = PreferenceManager.getDefaultSharedPreferences(ctx);
33 | }
34 |
35 | public boolean isNotify() {
36 | return mPreference.getBoolean("isNotify", false);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/gavinliu/notificationbox/widget/BaseActivity.java:
--------------------------------------------------------------------------------
1 | package cn.gavinliu.notificationbox.widget;
2 |
3 | import android.support.v7.app.AppCompatActivity;
4 |
5 | /**
6 | * Created by Gavin on 16-10-17.
7 | */
8 |
9 | public abstract class BaseActivity extends AppCompatActivity {
10 | }
11 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/gavinliu/notificationbox/widget/BaseFragment.java:
--------------------------------------------------------------------------------
1 | package cn.gavinliu.notificationbox.widget;
2 |
3 | import android.os.Bundle;
4 | import android.support.annotation.Nullable;
5 | import android.support.v4.app.Fragment;
6 | import android.support.v7.app.ActionBar;
7 | import android.support.v7.app.AppCompatActivity;
8 | import android.view.MenuItem;
9 |
10 | /**
11 | * Created by Gavin on 16-10-17.
12 | */
13 |
14 | public abstract class BaseFragment extends Fragment {
15 |
16 | @Override
17 | public void onCreate(@Nullable Bundle savedInstanceState) {
18 | super.onCreate(savedInstanceState);
19 | setHasOptionsMenu(true);
20 | }
21 |
22 | @Override
23 | public void onActivityCreated(@Nullable Bundle savedInstanceState) {
24 | super.onActivityCreated(savedInstanceState);
25 | getArguments(getArguments());
26 | setupActionBar(((AppCompatActivity) getActivity()).getSupportActionBar());
27 | }
28 |
29 | public void getArguments(Bundle bundle) {
30 |
31 | }
32 |
33 | public void setupActionBar(ActionBar actionBar) {
34 |
35 | }
36 |
37 | @Override
38 | public boolean onOptionsItemSelected(MenuItem item) {
39 | switch (item.getItemId()) {
40 | case android.R.id.home:
41 | getActivity().finish();
42 | break;
43 | }
44 | return super.onOptionsItemSelected(item);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/gavinliu/notificationbox/widget/BaseListFragment.java:
--------------------------------------------------------------------------------
1 | package cn.gavinliu.notificationbox.widget;
2 |
3 | import android.os.Bundle;
4 | import android.support.v7.widget.LinearLayoutManager;
5 | import android.support.v7.widget.RecyclerView;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 | import android.widget.TextView;
10 |
11 | import cn.gavinliu.notificationbox.R;
12 |
13 | /**
14 | * Created by Gavin on 16-10-22.
15 | */
16 |
17 | public abstract class BaseListFragment extends BaseFragment {
18 |
19 | protected View mView;
20 | protected RecyclerView mRecyclerView;
21 | protected View mEmptyLayout;
22 | protected TextView mEmptyText;
23 | protected View mProgressLayout;
24 |
25 | @Override
26 | public final View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
27 | if (mView == null) {
28 | mView = inflater.inflate(R.layout.nb_base_list_fragment, null, false);
29 | }
30 | return mView;
31 | }
32 |
33 | @Override
34 | public void onViewCreated(View view, Bundle savedInstanceState) {
35 | if (view != null) {
36 | mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
37 | mEmptyLayout = view.findViewById(R.id.empty_layout);
38 | mProgressLayout = view.findViewById(R.id.progress_layout);
39 | mEmptyText = (TextView) view.findViewById(R.id.empty_text);
40 | }
41 |
42 | setupRecyclerView(mRecyclerView);
43 | }
44 |
45 | protected void showEmptyView() {
46 | mEmptyLayout.setVisibility(View.VISIBLE);
47 | }
48 |
49 | protected void hideEmptyView() {
50 | mEmptyLayout.setVisibility(View.GONE);
51 | }
52 |
53 | protected void showProgressView() {
54 | mProgressLayout.setVisibility(View.VISIBLE);
55 | }
56 |
57 | protected void hideProgressView() {
58 | mProgressLayout.setVisibility(View.GONE);
59 | }
60 |
61 | protected void setEmptyText(CharSequence text){
62 | mEmptyText.setText(text);
63 | }
64 |
65 | protected void setupRecyclerView(RecyclerView recyclerView) {
66 | recyclerView.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false));
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/gavinliu/notificationbox/widget/BaseViewHolder.java:
--------------------------------------------------------------------------------
1 | package cn.gavinliu.notificationbox.widget;
2 |
3 | import android.support.v7.widget.RecyclerView;
4 | import android.view.View;
5 |
6 | /**
7 | * Created by Gavin on 2016/10/12.
8 | */
9 |
10 | public abstract class BaseViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
11 |
12 | public BaseViewHolder(View itemView) {
13 | super(itemView);
14 | itemView.setOnClickListener(this);
15 | }
16 |
17 | @Override
18 | public void onClick(View v) {
19 |
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_add_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gavinliu/NotificationBox/d2844df1c7a5e3f2e1aabd40c57c9201a2715d79/app/src/main/res/drawable-xhdpi/ic_add_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_add_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gavinliu/NotificationBox/d2844df1c7a5e3f2e1aabd40c57c9201a2715d79/app/src/main/res/drawable-xxhdpi/ic_add_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_navigate_next_black_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gavinliu/NotificationBox/d2844df1c7a5e3f2e1aabd40c57c9201a2715d79/app/src/main/res/drawable-xxhdpi/ic_navigate_next_black_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxxhdpi/ic_add_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gavinliu/NotificationBox/d2844df1c7a5e3f2e1aabd40c57c9201a2715d79/app/src/main/res/drawable-xxxhdpi/ic_add_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_applist.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
15 |
16 |
22 |
23 |
24 |
25 |
30 |
31 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_setting.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_applist.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
16 |
17 |
26 |
27 |
33 |
34 |
40 |
41 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_detail.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
16 |
17 |
27 |
28 |
40 |
41 |
51 |
52 |
53 |
54 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
17 |
18 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/nb_base_list_fragment.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/nb_empty_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
17 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/nb_preference_screen.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/nb_progress_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gavinliu/NotificationBox/d2844df1c7a5e3f2e1aabd40c57c9201a2715d79/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gavinliu/NotificationBox/d2844df1c7a5e3f2e1aabd40c57c9201a2715d79/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gavinliu/NotificationBox/d2844df1c7a5e3f2e1aabd40c57c9201a2715d79/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/values-v21/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/values-zh-rCN/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | 消息盒子
3 | 消息监听服务
4 |
5 | 软件列表
6 |
7 | 设置
8 |
9 | 功能
10 | 关于
11 | 开放源码
12 | 拦截提醒
13 | 拦截到消息后提醒
14 | 配置权限
15 | 如果拦截失效,请取消权限后,重新配置权限
16 |
17 | 没有监听通知栏的权限
18 |
19 | 点击右下角的按钮,添加所需拦截的App
20 | 还未拦截到该软件的通知消息
21 |
22 | 拦截: %1$s
23 |
24 |
25 |
--------------------------------------------------------------------------------
/app/src/main/res/values-zh-rHK/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | 消息盒子
3 | 消息監聽服務
4 |
5 | 軟件列表
6 |
7 | 設置
8 |
9 | 功能
10 | 關於
11 | 開放源碼
12 | 攔截提醒
13 | 攔截到消息後提醒
14 | 配置權限
15 | 如果攔截失效,請取消權限後,重新配置權限
16 |
17 | 沒有監聽通知欄的權限
18 |
19 | 點擊右下角的按鈕,添加所需攔截的App
20 | 還未攔截到該軟件的通知消息
21 |
22 | 攔截: %1$s
23 |
24 |
25 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #607D8B
4 | #455A64
5 | #03A9F4
6 |
7 | #212121
8 | #757575
9 | #BDBDBD
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 | 24dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/ids.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | NotificationBox
3 | Notification Listener Service
4 |
5 | App List
6 |
7 | Settings
8 |
9 | Feature
10 | About
11 | OpenSource
12 | Intercept reminder
13 | Intercept notification after the reminder
14 | Set permissions
15 | If the blocking is disabled, reset the permissions
16 |
17 | No read notification permissions
18 |
19 | Click on the lower right corner of the button, add the blocking App
20 | The notification message to the app has not yet been intercepted
21 |
22 | Intercept: %1$s
23 |
24 |
25 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
14 |
15 |
19 |
20 |
21 |
22 |
23 |
24 |
28 |
29 |
33 |
34 |
41 |
42 |
57 |
58 |
62 |
63 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/setting.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
7 |
8 |
13 |
14 |
19 |
20 |
21 |
22 |
24 |
25 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:2.2.2'
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
21 | task clean(type: Delete) {
22 | delete rootProject.buildDir
23 | }
24 |
--------------------------------------------------------------------------------
/screenshots.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gavinliu/NotificationBox/d2844df1c7a5e3f2e1aabd40c57c9201a2715d79/screenshots.png
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------