commit 00c4b1dc9eebd0d4986c200c17f6a4db3f4f6da1
Author: 如果当时 <1017848709@qq.com>
Date: Sat Nov 28 15:37:57 2020 +0800
初始备份。
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..aa724b7
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,15 @@
+*.iml
+.gradle
+/local.properties
+/.idea/caches
+/.idea/libraries
+/.idea/modules.xml
+/.idea/workspace.xml
+/.idea/navEditor.xml
+/.idea/assetWizardSettings.xml
+.DS_Store
+/build
+/captures
+.externalNativeBuild
+.cxx
+local.properties
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644
index 0000000..fb7f4a8
--- /dev/null
+++ b/.idea/compiler.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
new file mode 100644
index 0000000..5cd135a
--- /dev/null
+++ b/.idea/gradle.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
new file mode 100644
index 0000000..5bd12c5
--- /dev/null
+++ b/.idea/jarRepositories.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..9422e84
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..23d2272
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,2 @@
+2020-11-28 V1.0
+暂无。
\ No newline at end of file
diff --git a/app/.gitignore b/app/.gitignore
new file mode 100644
index 0000000..42afabf
--- /dev/null
+++ b/app/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
new file mode 100644
index 0000000..b6c4a6c
--- /dev/null
+++ b/app/build.gradle
@@ -0,0 +1,39 @@
+plugins {
+ id 'com.android.application'
+}
+
+android {
+ compileSdkVersion 29
+ buildToolsVersion "30.0.2"
+
+ defaultConfig {
+ applicationId "com.itrycn.tellmenotice"
+ minSdkVersion 23
+ targetSdkVersion 29
+ versionCode 1
+ versionName "1.0"
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+}
+
+dependencies {
+
+ implementation 'androidx.appcompat:appcompat:1.2.0'
+ implementation 'com.google.android.material:material:1.2.1'
+ implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
+ testImplementation 'junit:junit:4.+'
+ androidTestImplementation 'androidx.test.ext:junit:1.1.2'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
+}
\ No newline at end of file
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
new file mode 100644
index 0000000..481bb43
--- /dev/null
+++ b/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/app/src/androidTest/java/com/itrycn/tellmenotice/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/itrycn/tellmenotice/ExampleInstrumentedTest.java
new file mode 100644
index 0000000..bccbd47
--- /dev/null
+++ b/app/src/androidTest/java/com/itrycn/tellmenotice/ExampleInstrumentedTest.java
@@ -0,0 +1,26 @@
+package com.itrycn.tellmenotice;
+
+import android.content.Context;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see Testing documentation
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+ @Test
+ public void useAppContext() {
+ // Context of the app under test.
+ Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ assertEquals("com.itrycn.tellmenotice", appContext.getPackageName());
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..b5ce804
--- /dev/null
+++ b/app/src/main/AndroidManifest.xml
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/itrycn/tellmenotice/Alarm.java b/app/src/main/java/com/itrycn/tellmenotice/Alarm.java
new file mode 100644
index 0000000..6fc5b3c
--- /dev/null
+++ b/app/src/main/java/com/itrycn/tellmenotice/Alarm.java
@@ -0,0 +1,93 @@
+package com.itrycn.tellmenotice;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+
+import java.util.Calendar;
+import java.util.TimeZone;
+
+import static android.content.Context.ALARM_SERVICE;
+
+public class Alarm {
+ private Calendar mCalendar;
+ /**
+ *
+ */
+ private Context mContext;
+ /**
+ * 开启提醒
+ */
+ private void startRemind(){
+
+ //得到日历实例,主要是为了下面的获取时间
+ mCalendar = Calendar.getInstance();
+ mCalendar.setTimeInMillis(System.currentTimeMillis());
+
+ //获取当前毫秒值
+ long systemTime = System.currentTimeMillis();
+
+ //是设置日历的时间,主要是让日历的年月日和当前同步
+ mCalendar.setTimeInMillis(System.currentTimeMillis());
+ // 这里时区需要设置一下,不然可能个别手机会有8个小时的时间差
+ mCalendar.setTimeZone(TimeZone.getTimeZone("GMT+8"));
+ //设置在几点提醒 设置的为13点
+ mCalendar.set(Calendar.HOUR_OF_DAY, 7);
+ //设置在几分提醒 设置的为25分
+ mCalendar.set(Calendar.MINUTE, 58);
+ //下面这两个看字面意思也知道
+ mCalendar.set(Calendar.SECOND, 0);
+ mCalendar.set(Calendar.MILLISECOND, 0);
+
+ //上面设置的就是13点25分的时间点
+
+ //获取上面设置的13点25分的毫秒值
+ long selectTime = mCalendar.getTimeInMillis();
+
+ // 如果当前时间大于设置的时间,那么就从第二天的设定时间开始
+ if(systemTime > selectTime) {
+ mCalendar.add(Calendar.DAY_OF_MONTH, 1);
+ }
+
+ //AlarmReceiver.class为广播接受者
+ Intent intent = new Intent(mContext, BootBroadcastReceiver.class);
+ PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, intent, 0);
+ //得到AlarmManager实例
+ AlarmManager am = (AlarmManager)mContext.getSystemService(ALARM_SERVICE);
+
+ //**********注意!!下面的两个根据实际需求任选其一即可*********
+
+ /**
+ * 单次提醒
+ * mCalendar.getTimeInMillis() 上面设置的13点25分的时间点毫秒值
+ */
+ am.set(AlarmManager.RTC_WAKEUP, mCalendar.getTimeInMillis(), pi);
+
+ /**
+ * 重复提醒
+ * 第一个参数是警报类型;下面有介绍
+ * 第二个参数网上说法不一,很多都是说的是延迟多少毫秒执行这个闹钟,但是我用的刷了MIUI的三星手机的实际效果是与单次提醒的参数一样,即设置的13点25分的时间点毫秒值
+ * 第三个参数是重复周期,也就是下次提醒的间隔 毫秒值 我这里是一天后提醒
+ */
+ am.setRepeating(AlarmManager.RTC_WAKEUP, mCalendar.getTimeInMillis(), (1000 * 60 * 60 * 24), pi);
+
+ }
+
+
+ /**
+ * 关闭提醒
+ */
+ private void stopRemind(){
+
+ Intent intent = new Intent(mContext, BootBroadcastReceiver.class);
+ PendingIntent pi = PendingIntent.getBroadcast(mContext, 0,
+ intent, 0);
+ AlarmManager am = (AlarmManager)mContext.getSystemService(ALARM_SERVICE);
+ //取消警报
+ am.cancel(pi);
+ //Toast.makeText(this, "关闭了提醒", Toast.LENGTH_SHORT).show();
+
+ }
+
+}
diff --git a/app/src/main/java/com/itrycn/tellmenotice/BootBroadcastReceiver.java b/app/src/main/java/com/itrycn/tellmenotice/BootBroadcastReceiver.java
new file mode 100644
index 0000000..d7ffb39
--- /dev/null
+++ b/app/src/main/java/com/itrycn/tellmenotice/BootBroadcastReceiver.java
@@ -0,0 +1,25 @@
+package com.itrycn.tellmenotice;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.media.AudioManager;
+import android.widget.Toast;
+
+import java.util.Calendar;
+
+public class BootBroadcastReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent){
+ if(intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED) || intent.getAction().equals("android.intent.action.QUICKBOOT_POWERON")){ //开机广播
+ Toast.makeText(context, "服务启动成功", Toast.LENGTH_SHORT).show();
+ //Intent intent3 = new Intent(context,MainActivity.class);
+ //intent3.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ //context.startActivity(intent3);
+ Intent intent2 = new Intent(context,NoticeService.class);
+ intent2.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ context.startService(intent2);
+ }
+
+ }
+}
diff --git a/app/src/main/java/com/itrycn/tellmenotice/FloatView.java b/app/src/main/java/com/itrycn/tellmenotice/FloatView.java
new file mode 100644
index 0000000..63a9d1b
--- /dev/null
+++ b/app/src/main/java/com/itrycn/tellmenotice/FloatView.java
@@ -0,0 +1,158 @@
+package com.itrycn.tellmenotice;
+
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.PixelFormat;
+import android.provider.Settings;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.ImageView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class FloatView implements View.OnTouchListener {
+ private Context mContext;
+ private static WindowManager mWm;
+ private WindowManager.LayoutParams mWinParams;
+ private View view;
+ private float mDownX;
+ private float mDownY;
+ private float mMoveX;
+ private float mMoveY;
+
+ public FloatView(Context context) {
+ this.mContext = context;
+
+ view = View.inflate(mContext, R.layout.float_tip, null);
+
+ mWm = (WindowManager) context.getApplicationContext().getSystemService(
+ Context.WINDOW_SERVICE);
+
+ mWinParams = new WindowManager.LayoutParams();
+ //mWinParams.height = WindowManager.LayoutParams.MATCH_PARENT;
+ //mWinParams.width = WindowManager.LayoutParams.MATCH_PARENT;
+ mWinParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+ | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
+ mWinParams.format = PixelFormat.TRANSLUCENT;
+ // mParams.windowAnimations =
+ // com.android.internal.R.style.Animation_Toast;//动画设置
+ //在小米手机的 5.0系统中,需要设置 type为 TYPE_TOAST,才能显示
+ mWinParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+ mWinParams.x = 0;
+ mWinParams.y = 0;
+ mWinParams.width = dip2px(mContext,250);
+ mWinParams.height = dip2px(mContext,170);
+ view.setOnTouchListener(this);
+ }
+ /**
+ * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
+ */
+ public static int dip2px(Context context, float dpValue) {
+ final float scale = context.getResources().getDisplayMetrics().density;
+ return (int) (dpValue * scale + 0.5f);
+ }
+ public void show() {
+ mWm.addView(view, mWinParams);
+ }
+ public void showFloatingWindow(Notification notice, String Title, String Content) {
+ showFloatingWindow(notice,Title,Content,-1);
+ }
+ public void showFloatingWindow(Notification notice, String Title, String Content, int TitleBackColor) {
+ if (Settings.canDrawOverlays(mContext)) {
+ LayoutInflater layoutInflater = LayoutInflater.from(mContext);
+ ImageView image=view.findViewById(R.id.IdIcon);
+ image.setImageIcon(notice.getSmallIcon());
+ image.setOnClickListener(v -> {
+ //打开通知栏的intent,即打开对应的聊天界面
+ PendingIntent pendingIntent = notice.contentIntent;
+ try {
+ pendingIntent.send();
+ if (mWm != null) mWm.removeView(view);
+ } catch (PendingIntent.CanceledException e) {
+ Toast.makeText(mContext, "打开出错->"+e.getMessage(), Toast.LENGTH_SHORT).show();
+ e.printStackTrace();
+ }
+ });
+ //image.setOnTouchListener(new FloatingOnTouchListener());
+ ImageView image_close=view.findViewById(R.id.IdClose);
+ image_close.setImageResource(R.drawable.close);
+ image_close.setOnClickListener(v -> {
+ if (mWm != null) mWm.removeView(view);
+ });
+ TextView idTitle = view.findViewById(R.id.IdTitle);
+ if(TitleBackColor!=-1)
+ {
+ image.setBackgroundColor(TitleBackColor);
+ idTitle.setBackgroundColor(TitleBackColor);
+ image_close.setBackgroundColor(TitleBackColor);
+ }
+ //idTitle.setOnTouchListener(new FloatingOnTouchListener());
+ TextView idContent = view.findViewById(R.id.IdContent);
+ TextView idPostTime = view.findViewById(R.id.IdPostTime);
+ idTitle.setText(Title);
+ idContent.setText(Content);
+ SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");// HH:mm:ss
+ //获取当前时间
+ Date date = new Date(System.currentTimeMillis());
+ idPostTime.setText("时间:"+simpleDateFormat.format(date));
+ //idContent.setOnTouchListener(new FloatingOnTouchListener());
+ mWm.addView(view, mWinParams);
+ }
+ }
+ public void hide(){
+ if(mWm != null){
+ mWm.removeView(view);
+ }
+ }
+
+ @Override
+ public boolean onTouch(View view, MotionEvent event) {
+
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+
+ mDownX = event.getRawX();
+ mDownY = event.getRawY();
+
+ break;
+ case MotionEvent.ACTION_MOVE:
+
+ /**
+ * 最为关键的就是拖动业务的坐标位置的计算
+ */
+
+ mMoveX = event.getRawX();
+ mMoveY = event.getRawY();
+
+ float difX = (mMoveX - mDownX);
+ float difY = (mMoveY - mDownY);
+
+ mWinParams.x += difX;
+ mWinParams.y += difY;
+ mWm.updateViewLayout(view, mWinParams);
+
+ mDownX = mMoveX;
+ mDownY = mMoveY;
+
+ break;
+ case MotionEvent.ACTION_UP:
+
+ break;
+
+ default:
+ break;
+ }
+
+ // 消费触摸事件
+ return true;
+ }
+
+}
diff --git a/app/src/main/java/com/itrycn/tellmenotice/MainActivity.java b/app/src/main/java/com/itrycn/tellmenotice/MainActivity.java
new file mode 100644
index 0000000..3c35db3
--- /dev/null
+++ b/app/src/main/java/com/itrycn/tellmenotice/MainActivity.java
@@ -0,0 +1,136 @@
+package com.itrycn.tellmenotice;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import android.content.ActivityNotFoundException;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.media.AudioManager;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.view.View;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import java.util.Calendar;
+
+public class MainActivity extends AppCompatActivity {
+ ScreenListener screenlistener;
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ if(!isNotificationListenersEnabled())
+ {
+ gotoNotificationAccessSetting(MainActivity.this);
+ }
+ Intent intent2 = new Intent(MainActivity.this,NoticeService.class);
+ startService(intent2);
+ startFloatingButtonService();
+ TextView tv=findViewById(R.id.IdState);
+ tv.setText("睿元智能管家,你的私人管家。\n" +
+ "1.帮你监控系统通知,自动筛选重要通知。\n" +
+ "2.不同通知展现不同的提醒界面和声音。\n" +
+ "3.支持免打扰功能,深夜自动免打扰。");
+ ScreenListener screenlistener = new ScreenListener(this);
+ screenlistener.begin(new ScreenListener.ScreenStateListener() {
+
+ @Override
+ public void onUserPresent() {
+ //Log.e("onUserPresent", "onUserPresent");
+ }
+
+ @Override
+ public void onScreenOn() {
+ //Log.e("onScreenOn", "onScreenOn");
+ }
+
+ @Override
+ public void onScreenOff() {
+ //region 关闭屏幕自动将通知音量调整到最大
+ Calendar c = Calendar.getInstance();
+ int hour = c.get(Calendar.HOUR_OF_DAY); // 时
+ if(hour>=23 || hour<7) {return; } //23点到早上7点,免打扰时间段
+ AudioManager audioManager = (AudioManager) MainActivity.this.getSystemService(Context.AUDIO_SERVICE);
+ int NoticeVolume= audioManager.getStreamVolume(AudioManager.STREAM_NOTIFICATION);
+ int NoticeMaxVolume= audioManager.getStreamMaxVolume(AudioManager.STREAM_NOTIFICATION);
+ if(NoticeVolume= Build.VERSION_CODES.O) {
+ // layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+ // } else {
+ // layoutParams.type = WindowManager.LayoutParams.TYPE_PHONE;
+ //}
+ //layoutParams.format = PixelFormat.TRANSLUCENT;
+ //layoutParams.gravity = Gravity.LEFT | Gravity.TOP;
+ //layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+ // layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
+ // layoutParams.height = WindowManager.LayoutParams.MATCH_PARENT;
+ // layoutParams.x = 300;
+ // layoutParams.y = 300;
+ }
+ @Override
+ public void onDestroy() {
+ sp.unload(MP3_notice);
+ sp.unload(MP3_mm);
+ sp.unload(MP3_Ring);
+ sp.unload(MP3_kuaidi);
+ sp.unload(MP3_Dingding);
+ super.onDestroy();
+ }
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ Log.i("KEVIN", "Service is started" + "-----");
+ //
+ //data = intent.getStringExtra("data");
+ return super.onStartCommand(intent, flags, startId);
+ }
+ SoundPool sp;
+ int MP3_notice;
+ int MP3_mm;
+ int MP3_Ring;
+ int MP3_kuaidi;
+ int MP3_Dingding;
+ String Last_packageName="";
+ String Last_Title="";
+ String Last_Content="";
+ long Last_UpdateTime=0;
+ /**
+ * 播放声音
+ * @param SoundId 声音id
+ * @param loop 循环次数
+ * @param DNDPlay 是否在免打扰时依旧播放
+ */
+ private void PlaySound(int SoundId,int loop,boolean DNDPlay)
+ {
+ if(!DNDPlay) //如果该声音未开启免打扰时允许播放,则检查当前是否属于免打扰
+ {
+ Calendar c = Calendar.getInstance();
+ //int year = c.get(Calendar.YEAR); // 获取当前年份
+ //int month = c.get(Calendar.MONTH) + 1; // 获取当前月份
+ //int day = c.get(Calendar.DAY_OF_MONTH); // 获取当日
+ int dayOfWeek = c.get(Calendar.DAY_OF_WEEK); // 获取当前日期的星期,1 表示星期日、用 2 表示星期一
+ int hour = c.get(Calendar.HOUR_OF_DAY); // 时
+ //int minute = c.get(Calendar.MINUTE); // 分
+ if(hour>=23 || hour<7) {return; } //23点到早上7点,免打扰时间段
+ //if(hour>=23 && hour<7) {return; }
+ }
+ sp.play(SoundId, 1f, 1.0f,1,loop,1);
+ }
+ private long LastDoorRingTime=0;
+ @Override
+ public void onNotificationPosted(StatusBarNotification sbn) {
+ // super.onNotificationPosted(sbn);
+ try {
+ Notification notice=sbn.getNotification();
+ if(notice==null){return;}
+ Bundle extras = notice.extras;
+ String packageName=sbn.getPackageName();
+ String Title="";
+ String Content="";
+ //有些通知不能解析出TEXT内容,这里做个信息能判断
+ if (extras == null && notice.tickerText!=null) {
+ Content=notice.tickerText.toString();
+ }
+ else
+ {
+ Title=extras.getString(Notification.EXTRA_TITLE);
+ Content=extras.getString(Notification.EXTRA_TEXT);
+ }
+ if(Title==null){Title="";}
+ if(Content==null){Content="";}
+ if(Title.length()==0 && Content.length()==0){return;}
+ boolean haveTip=false;//该消息是否需要提醒。
+ Calendar c = Calendar.getInstance();
+ long NowTime=c.getTime().getTime();
+ if(packageName.equals(Last_packageName)
+ && Title.equals(Last_Title)
+ && Content.equals(Last_Content)
+ && Last_UpdateTime+6000>NowTime
+ )
+ {
+ return;
+ }
+ if(packageName.equals("com.tencent.mm")) //如果是微信
+ {
+ //region 微信中有人提到自己
+ String[] strArr = "鑫之风;大头;凤鑫;风鑫;封信;风兴;奉新;凤兴;阿香;凤新".split(";");
+ boolean haveInfo=false;
+ for (int i = 0; i < strArr.length; ++i){
+ if(Content.contains(strArr[i]))
+ {
+ FloatView fv=new FloatView(this);
+ fv.showFloatingWindow(notice,Title,Content);
+ //showFloatingWindow(notice,Title,Content);
+ PlaySound(MP3_mm,0,false);
+ haveInfo=true;
+ haveTip=true;
+ break;
+ }
+ }
+ //endregion
+ if(!haveInfo)
+ {
+ if(Title.contains("球球") || Content.contains("球球")) {
+ String[] strArr2 = "球球独家;口令;拍下;http;拍第;体验;福利;一单;元抢;内部;复制打开;漏洞;好评;0元;抢到;免单;独家".split(";");
+ for (int i = 0; i < strArr2.length; ++i) {
+ if (Content.contains(strArr2[i])) {
+ FloatView fv = new FloatView(this);
+ fv.showFloatingWindow(notice, Title, Content, Color.parseColor("#FF0000"));
+ //showFloatingWindow(notice,Title,Content);
+ PlaySound(MP3_Dingding, 0, false);
+ haveTip=true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ else if(packageName.equals("com.xiaomi.smarthome")) //如果是米家app
+ {
+ //region 米家app处理方式
+ if(Title.equals("GroupSummary") ||Content.equals("GroupSummary")){return;};
+ if(Title.contains("按门铃") || Content.contains("按门铃"))
+ {
+ if(LastDoorRingTime+60000>=NowTime){return;} //如果1分钟内有新的门铃提醒,则自动忽略
+ LastDoorRingTime=c.getTime().getTime();
+ FloatView fv=new FloatView(this);
+ fv.showFloatingWindow(notice,Content,Title, Color.parseColor("#02BD9D"));
+ PlaySound(MP3_Ring,2,false);
+ haveTip=true;
+ }
+ else
+ {
+ FloatView fv=new FloatView(this);
+ if(Title.equals("自动化通知"))
+ {
+ fv.showFloatingWindow(notice,Title, Content, Color.parseColor("#02BD9D"));
+ }
+ else {
+ if(Title.length()>=Content.length()) {
+ fv.showFloatingWindow(notice, Content, Title, Color.parseColor("#02BD9D"));
+ }
+ else {
+ fv.showFloatingWindow(notice,Title, Content, Color.parseColor("#02BD9D"));
+ }
+ }
+ haveTip=true;
+ PlaySound(MP3_Dingding,0,false);
+ }
+ //endregion
+ }
+ else if(packageName.equals("com.android.mms")) //如果是短信
+ {
+ //region 短信中提取快递获取信息
+ String[] strArr = "保安室;快递室;派送成功;代收;".split(";");
+ for (int i = 0; i < strArr.length; ++i){
+ if(Title.contains(strArr[i]) || Content.contains(strArr[i]))
+ {
+ FloatView fv=new FloatView(this);
+ fv.showFloatingWindow(notice,Title,Content);
+ PlaySound(MP3_kuaidi,0,false);
+ haveTip=true;
+ break;
+ }
+ }
+ //endregion
+ }
+ else if(packageName.equals("com.jingyao.easybike") //哈罗出行
+ || packageName.equals("com.sdu.didi.psnger") //滴滴出行
+ || packageName.equals("com.didapinche.booking")) //嘀嗒出行
+ {
+ if(Title.contains("正在运行")){return;}
+ if(Title.contains("哈啰顺风车运行中") || Content.contains("哈啰顺风车运行中")){return;}
+ if(Title.contains("顺风车出行中") || Content.contains("顺风车出行中")){return;}
+ //region 如果是顺风车线路
+ FloatView fv=new FloatView(this);
+ if(packageName.equals("com.jingyao.easybike"))
+ {
+ fv.showFloatingWindow(notice,Title, Content, Color.parseColor("#0391FF"));
+ }
+ else if(packageName.equals("com.sdu.didi.psnger"))
+ {
+ fv.showFloatingWindow(notice,Title, Content, Color.parseColor("#F8934C"));
+ }
+ else if(packageName.equals("com.didapinche.booking"))
+ {
+ fv.showFloatingWindow(notice,Title, Content, Color.parseColor("#FED051"));
+ }
+ else {
+ fv.showFloatingWindow(notice, Title, Content);
+ }
+ haveTip=true;
+ PlaySound(MP3_Dingding,0,false);
+ //endregion
+ }
+ else if(packageName.equals("com.taobao.taobao")
+ || packageName.equals("com.jingdong.app.mall")
+ || packageName.equals("com.xunmeng.pinduoduo")) //如果是淘宝或京东或拼多多
+ {
+ //region 判断是否是物流信息
+ String[] strArr = "签收;发货;派送;派件;".split(";");
+ for (int i = 0; i < strArr.length; ++i){
+ if(Title.contains(strArr[i]) || Content.contains(strArr[i]))
+ {
+ FloatView fv=new FloatView(this);
+ fv.showFloatingWindow(notice,Title,Content, Color.parseColor("#FD5C02"));
+ PlaySound(MP3_Dingding,0,false);
+ haveTip=true;
+ break;
+ }
+ }
+ //endregion
+ }
+ //else {
+ // Toast.makeText(this,packageName+"->"+Title+"-"+Content, Toast.LENGTH_SHORT).show();
+ // sp.play(MP3_notice, 1f, 1.0f, 1, 0, 1);
+ //}
+ if(haveTip)
+ {
+ Last_packageName=packageName;
+ Last_Title=Title;
+ Last_Content=Content;
+ Last_UpdateTime=NowTime;
+ }
+ } catch (Exception e) {
+ Toast.makeText(this, "不可解析的通知->"+e.getMessage(), Toast.LENGTH_SHORT).show();
+ }
+ }
+ private void showFloatingWindow(Notification notice, String Title, String Content) {
+ if (Settings.canDrawOverlays(this)) {
+ LayoutInflater layoutInflater = LayoutInflater.from(this);
+ View displayView = layoutInflater.inflate(R.layout.float_tip, null);
+ displayView.setOnTouchListener(new FloatingOnTouchListener());
+ ImageView image=displayView.findViewById(R.id.IdIcon);
+ image.setImageIcon(notice.getSmallIcon());
+ image.setOnClickListener(v -> {
+ //打开通知栏的intent,即打开对应的聊天界面
+ PendingIntent pendingIntent = notice.contentIntent;
+ try {
+ pendingIntent.send();
+ if (windowManager != null) windowManager.removeView(displayView);
+ } catch (PendingIntent.CanceledException e) {
+ Toast.makeText(this, "打开出错->"+e.getMessage(), Toast.LENGTH_SHORT).show();
+ e.printStackTrace();
+ }
+ });
+ //image.setOnTouchListener(new FloatingOnTouchListener());
+ ImageView image_close=displayView.findViewById(R.id.IdClose);
+ image_close.setImageResource(R.drawable.close);
+ image_close.setOnClickListener(v -> {
+ if (windowManager != null) windowManager.removeView(displayView);
+ });
+ TextView idTitle = displayView.findViewById(R.id.IdTitle);
+ //idTitle.setOnTouchListener(new FloatingOnTouchListener());
+ TextView idContent = displayView.findViewById(R.id.IdContent);
+ TextView idPostTime = displayView.findViewById(R.id.IdPostTime);
+ idTitle.setText(Title);
+ idContent.setText(Content);
+ SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");// HH:mm:ss
+ //获取当前时间
+ Date date = new Date(System.currentTimeMillis());
+ idPostTime.setText("时间:"+simpleDateFormat.format(date));
+ //idContent.setOnTouchListener(new FloatingOnTouchListener());
+ windowManager.addView(displayView, layoutParams);
+ }
+ }
+ private class FloatingOnTouchListener implements View.OnTouchListener {
+ private int x;
+ private int y;
+
+ @Override
+ public boolean onTouch(View view, MotionEvent event) {
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ x = (int) event.getRawX();
+ y = (int) event.getRawY();
+ break;
+ case MotionEvent.ACTION_MOVE:
+ int nowX = (int) event.getRawX();
+ int nowY = (int) event.getRawY();
+ int movedX = nowX - x;
+ int movedY = nowY - y;
+ x = nowX;
+ y = nowY;
+ layoutParams.x = layoutParams.x + movedX;
+ layoutParams.y = layoutParams.y + movedY;
+ windowManager.updateViewLayout(view, layoutParams);
+ break;
+ default:
+ break;
+ }
+ return false;
+ }
+ }
+}
diff --git a/app/src/main/java/com/itrycn/tellmenotice/ScreenListener.java b/app/src/main/java/com/itrycn/tellmenotice/ScreenListener.java
new file mode 100644
index 0000000..9a3c364
--- /dev/null
+++ b/app/src/main/java/com/itrycn/tellmenotice/ScreenListener.java
@@ -0,0 +1,91 @@
+package com.itrycn.tellmenotice;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.PowerManager;
+
+public class ScreenListener {
+ private Context mContext;
+ private ScreenBroadcastReceiver mScreenReceiver;
+ private ScreenStateListener mScreenStateListener;
+
+ public ScreenListener(Context context) {
+ mContext = context;
+ mScreenReceiver = new ScreenBroadcastReceiver();
+ }
+
+ /**
+ * screen状态广播接收者
+ */
+ private class ScreenBroadcastReceiver extends BroadcastReceiver {
+ private String action = null;
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ action = intent.getAction();
+ if (Intent.ACTION_SCREEN_ON.equals(action)) { // 开屏
+ mScreenStateListener.onScreenOn();
+ } else if (Intent.ACTION_SCREEN_OFF.equals(action)) { // 锁屏
+ mScreenStateListener.onScreenOff();
+ } else if (Intent.ACTION_USER_PRESENT.equals(action)) { // 解锁
+ mScreenStateListener.onUserPresent();
+ }
+ }
+ }
+
+ /**
+ * 开始监听screen状态
+ *
+ * @param listener
+ */
+ public void begin(ScreenStateListener listener) {
+ mScreenStateListener = listener;
+ registerListener();
+ getScreenState();
+ }
+
+ /**
+ * 获取screen状态
+ */
+ private void getScreenState() {
+ PowerManager manager = (PowerManager) mContext
+ .getSystemService(Context.POWER_SERVICE);
+ if (manager.isScreenOn()) {
+ if (mScreenStateListener != null) {
+ mScreenStateListener.onScreenOn();
+ }
+ } else {
+ if (mScreenStateListener != null) {
+ mScreenStateListener.onScreenOff();
+ }
+ }
+ }
+
+ /**
+ * 停止screen状态监听
+ */
+ public void unregisterListener() {
+ mContext.unregisterReceiver(mScreenReceiver);
+ }
+
+ /**
+ * 启动screen状态广播接收器
+ */
+ private void registerListener() {
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_SCREEN_ON);
+ filter.addAction(Intent.ACTION_SCREEN_OFF);
+ filter.addAction(Intent.ACTION_USER_PRESENT);
+ mContext.registerReceiver(mScreenReceiver, filter);
+ }
+
+ public interface ScreenStateListener {// 返回给调用者屏幕状态信息
+ public void onScreenOn();
+
+ public void onScreenOff();
+
+ public void onUserPresent();
+ }
+}
diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 0000000..2b068d1
--- /dev/null
+++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/borderline.xml b/app/src/main/res/drawable/borderline.xml
new file mode 100644
index 0000000..3d52e23
--- /dev/null
+++ b/app/src/main/res/drawable/borderline.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/close.png b/app/src/main/res/drawable/close.png
new file mode 100644
index 0000000..0bf7aa9
Binary files /dev/null and b/app/src/main/res/drawable/close.png differ
diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..07d5da9
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..22969f7
--- /dev/null
+++ b/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/float_tip.xml b/app/src/main/res/layout/float_tip.xml
new file mode 100644
index 0000000..da68d07
--- /dev/null
+++ b/app/src/main/res/layout/float_tip.xml
@@ -0,0 +1,91 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 0000000..eca70cf
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..eca70cf
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..a571e60
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000..61da551
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..c41dd28
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000..db5080a
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..6dba46d
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..da31a87
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..15ac681
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..b216f2d
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..f25a419
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..e96783c
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/raw/chattip.mp3 b/app/src/main/res/raw/chattip.mp3
new file mode 100644
index 0000000..08e8b54
Binary files /dev/null and b/app/src/main/res/raw/chattip.mp3 differ
diff --git a/app/src/main/res/raw/dingding.mp3 b/app/src/main/res/raw/dingding.mp3
new file mode 100644
index 0000000..a19b3ad
Binary files /dev/null and b/app/src/main/res/raw/dingding.mp3 differ
diff --git a/app/src/main/res/raw/kuaidi.mp3 b/app/src/main/res/raw/kuaidi.mp3
new file mode 100644
index 0000000..1482837
Binary files /dev/null and b/app/src/main/res/raw/kuaidi.mp3 differ
diff --git a/app/src/main/res/raw/notice.mp3 b/app/src/main/res/raw/notice.mp3
new file mode 100644
index 0000000..fe204e1
Binary files /dev/null and b/app/src/main/res/raw/notice.mp3 differ
diff --git a/app/src/main/res/raw/ring.mp3 b/app/src/main/res/raw/ring.mp3
new file mode 100644
index 0000000..71a1280
Binary files /dev/null and b/app/src/main/res/raw/ring.mp3 differ
diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml
new file mode 100644
index 0000000..7b9f8b9
--- /dev/null
+++ b/app/src/main/res/values-night/themes.xml
@@ -0,0 +1,16 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..f8c6127
--- /dev/null
+++ b/app/src/main/res/values/colors.xml
@@ -0,0 +1,10 @@
+
+
+ #FFBB86FC
+ #FF6200EE
+ #FF3700B3
+ #FF03DAC5
+ #FF018786
+ #FF000000
+ #FFFFFFFF
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..8c73c3c
--- /dev/null
+++ b/app/src/main/res/values/strings.xml
@@ -0,0 +1,4 @@
+
+ 智能管家
+ 睿元智能管家,你的私人管家。\n1.可以帮你监控系统通知,自动筛选对你有用的内容。\n2.不同通知展现不同的提醒界面和声音。
+
\ No newline at end of file
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
new file mode 100644
index 0000000..19c1847
--- /dev/null
+++ b/app/src/main/res/values/themes.xml
@@ -0,0 +1,16 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/test/java/com/itrycn/tellmenotice/ExampleUnitTest.java b/app/src/test/java/com/itrycn/tellmenotice/ExampleUnitTest.java
new file mode 100644
index 0000000..2575c23
--- /dev/null
+++ b/app/src/test/java/com/itrycn/tellmenotice/ExampleUnitTest.java
@@ -0,0 +1,17 @@
+package com.itrycn.tellmenotice;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see Testing documentation
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..e65e0e8
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,24 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+buildscript {
+ repositories {
+ google()
+ jcenter()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:4.2.0-alpha15'
+
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+allprojects {
+ repositories {
+ google()
+ jcenter()
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 0000000..52f5917
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,19 @@
+# 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.
+org.gradle.jvmargs=-Xmx2048m -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
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app"s APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+# Automatically convert third-party libraries to use AndroidX
+android.enableJetifier=true
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..f6b961f
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..ad86d40
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Sat Oct 03 18:50:49 CST 2020
+distributionBase=GRADLE_USER_HOME
+distributionUrl=https://services.gradle.org/distributions/gradle-6.7-bin.zip
+distributionPath=wrapper/dists
+zipStorePath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
diff --git a/gradlew b/gradlew
new file mode 100644
index 0000000..cccdd3d
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# 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
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# 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
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+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" -a "$nonstop" = "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
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000..f955316
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,84 @@
+@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
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@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=
+
+@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 Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_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=%*
+
+: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
diff --git a/readme.md b/readme.md
new file mode 100644
index 0000000..aed8b83
--- /dev/null
+++ b/readme.md
@@ -0,0 +1,10 @@
+# 简介 #
+TellMeNotice是一款重要通知提醒软件,对于重要通知进行语音和悬浮窗弹窗提醒。
+- 微信中提到自己名字的消息进行语音和悬浮窗提醒。
+- 快递派送提醒。
+- 米家app消息优化弹窗,支持按门铃提醒。
+- 支持深夜免打扰。
+- 支持顺风车软件提醒。
+
+# 运行环境 #
+android5.0及以上
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..3b085e4
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,2 @@
+rootProject.name = "TellMeNotice"
+include ':app'