version:1.1

fix:
add:应用使用数据统计
This commit is contained in:
2021-12-25 17:04:52 +08:00
parent 6c2eb5a1a3
commit b481df8671
55 changed files with 3184 additions and 300 deletions

View File

@@ -1,11 +1,11 @@
apply plugin: 'com.android.application'
def appName() {
return "学习系统"
return "桌面"
}
def releaseTime() {
return new Date().format("yyyyMMddHHmmss", TimeZone.getDefault())
return new Date().format("yyyyMMdd-HHmmss", TimeZone.getDefault())
}
android {
@@ -15,12 +15,27 @@ android {
applicationId "com.uiui.os"
minSdkVersion 24
targetSdkVersion 29
versionCode 1
versionName "1.0"
versionCode 2
versionName "1.1"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
lintOptions {
checkReleaseBuilds false
// Or, if you prefer, you can continue to check for errors in release builds,
// but continue the build even when errors are found:
abortOnError false
}
aaptOptions.cruncherEnabled = false
aaptOptions.useNewCruncher = false
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
signingConfigs {
zhanRui {
storeFile file("src/doc/zhanxun.keystore")
@@ -133,9 +148,24 @@ dependencies {
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
implementation 'com.squareup.okhttp3:okhttp:3.12.12'
implementation 'com.google.code.gson:gson:2.6.2'
//RxJava
// implementation 'io.reactivex.rxjava2:rxjava:2.2.12'
// implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
//
implementation 'com.squareup.okhttp3:okhttp:4.9.1'
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
// implementation 'com.squareup.retrofit2:adapter-rxjava2:2.4.0'
implementation "com.squareup.retrofit2:adapter-rxjava3:2.9.0"
//Gson
implementation 'com.google.code.gson:gson:2.8.7'
implementation 'com.google.zxing:core:3.3.0'
//生命周期管理
implementation 'com.trello.rxlifecycle4:rxlifecycle:4.0.2'
implementation 'com.trello.rxlifecycle4:rxlifecycle-android:4.0.2'
implementation 'com.trello.rxlifecycle4:rxlifecycle-components:4.0.2'
implementation 'com.trello.rxlifecycle4:rxlifecycle-components-preference:4.0.2'
implementation 'com.trello.rxlifecycle4:rxlifecycle-android-lifecycle:4.0.2'
//bindView
implementation 'com.jakewharton:butterknife:10.1.0'
annotationProcessor 'com.jakewharton:butterknife-compiler:10.1.0'
@@ -148,4 +178,9 @@ dependencies {
//指示器
implementation 'com.github.hackware1993:MagicIndicator:1.7.0' // for androidx
implementation 'com.king.view:circleprogressview:1.1.2'
//工具类
implementation 'com.blankj:utilcodex:1.30.6'
//aria
implementation 'com.arialyy.aria:core:3.8.15'
annotationProcessor 'com.arialyy.aria:compiler:3.8.15'
}

View File

@@ -7,32 +7,20 @@
<uses-permission android:name="android.permission.INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
<!--允许访问网络,必选权限-->
<uses-permission android:name="android.permission.INTERNET" />
<!--允许获取精确位置,精准定位必选-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!--允许获取粗略位置,粗略定位必选-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!--允许获取设备和运营商信息用于问题排查和网络定位无gps情况下的定位若需网络定位功能则必选-->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!--允许获取网络状态用于网络定位无gps情况下的定位若需网络定位功能则必选-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!--允许获取wifi网络信息用于网络定位无gps情况下的定位若需网络定位功能则必选-->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!--允许获取wifi状态改变用于网络定位无gps情况下的定位若需网络定位功能则必选-->
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<!--后台获取位置信息,若需后台定位则必选-->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<!--用于申请调用A-GPS模块,卫星定位加速-->
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<!--允许写设备缓存,用于问题排查-->
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<!--允许写入扩展存储,用于写入缓存定位数据-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!--允许读设备等信息,用于问题排查-->
<uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" /> <!-- 允许访问网络,必选权限 -->
<uses-permission android:name="android.permission.INTERNET" /> <!-- 允许获取精确位置,精准定位必选 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <!-- 允许获取粗略位置,粗略定位必选 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <!-- 允许获取设备和运营商信息用于问题排查和网络定位无gps情况下的定位若需网络定位功能则必选 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" /> <!-- 允许获取网络状态用于网络定位无gps情况下的定位若需网络定位功能则必选 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <!-- 允许获取wifi网络信息用于网络定位无gps情况下的定位若需网络定位功能则必选 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <!-- 允许获取wifi状态改变用于网络定位无gps情况下的定位若需网络定位功能则必选 -->
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <!-- 后台获取位置信息,若需后台定位则必选 -->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" /> <!-- 用于申请调用A-GPS模块,卫星定位加速 -->
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" /> <!-- 允许写设备缓存,用于问题排查 -->
<uses-permission android:name="android.permission.WRITE_SETTINGS" /> <!-- 允许写入扩展存储,用于写入缓存定位数据 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- 允许读设备等信息,用于问题排查 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:name=".base.BaseApplication"
@@ -43,7 +31,21 @@
android:largeHeap="true"
android:restoreAnyVersion="true"
android:supportsRtl="true"
android:requestLegacyExternalStorage="true"
android:theme="@style/AppTheme">
<activity android:name=".activity.NoticeActivity"
android:excludeFromRecents="true"
android:theme="@style/activity_styles"/>
<service
android:name=".service.AlarmService"
android:enabled="true"
android:exported="true" />
<service
android:name=".service.MainService"
android:enabled="true"
android:exported="true" />
<activity
android:name=".activity.MainActivity"
android:clearTaskOnLaunch="true"
@@ -65,16 +67,33 @@
<category android:name="android.intent.category.LAUNCHER_APP" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- 高德地图 -->
</activity> <!-- 高德地图 -->
<!-- 设置key -->
<meta-data
android:name="com.amap.api.v2.apikey"
android:value="${AMAP_KEY}" />
<!-- 定位需要的服务 适配Android Q需要加上android:foregroundServiceType="location" -->
android:value="${AMAP_KEY}" /> <!-- 定位需要的服务 适配Android Q需要加上android:foregroundServiceType="location" -->
<service
android:name="com.amap.api.location.APSService"
android:foregroundServiceType="location" />
<receiver
android:name=".receiver.BootReceiver"
android:enabled="true"
android:exported="true">
<intent-filter android:priority="1000">
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.BATTERY_CHANGED" />
<action android:name="android.intent.action.BATTERY_LOW" />
<action android:name="android.intent.action.BATTERY_OKAY" />
<action android:name="android.intent.action.ACTION_POWER_CONNECTED" />
<action android:name="android.intent.action.DATE_CHANGED" />
<action android:name="android.intent.action.ACTION_TIMEZONE_CHANGED" />
<action android:name="android.intent.action.USER_PRESENT" />
<action android:name="android.intent.action.SCREEN_ON" />
<action android:name="android.intent.action.SCREEN_OFF" />
<action android:name="zuoyeos.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
</manifest>

View File

@@ -0,0 +1,161 @@
<?xml version="1.0" encoding="utf-8"?>
<aria>
<!--注意,修改该配置文件中的属性会覆盖代码中所设置的属性-->
<!--Aria框架配置-->
<app>
<!--是否使用AriaCrashHandler来捕获异常异常日志保存在/mnt/sdcard/Android/data/{package_name}/files/log/-->
<useAriaCrashHandler value="true"/>
<!--设置Aria的日志级别{@link ALog#LOG_LEVEL_VERBOSE}-->
<logLevel value="2"/>
<!-- 是否检查网络 true: 检查网络false: 不检查网络-->
<netCheck value="true"/>
<!--除非无法使用注解否则不建议使用广播来接受任务状态true使用广播接收任务状态false不适用广播接收状态 -->
<!-- http://aria.laoyuyu.me/aria_doc/api/use_broadcast.html -->
<useBroadcast value="false"/>
<!--断网的时候是否重试true断网也重试false断网不重试直接走失败的回调-->
<notNetRetry value="true"/>
</app>
<!--普通下载任务-->
<download>
<!--设置任务最大下载速度0表示不限速单位为kb-->
<maxSpeed value="0"/>
<!--
多线程下载是否使用块下载模式,{@code true}使用,{@code false}不使用
注意:
1、使用分块模式在I/O性能底下的手机上合并文件需要的时间会更加长
2、优点是使用多线程的块下载初始化时文件初始化时将不会预占用对应长度的空间
3、只对新的多线程下载任务有效
4、只对多线程的任务有效
-->
<useBlock value="true"/>
<!--设置下载线程数下载线程数不能小于1
注意:
1、线程下载数改变后新的下载任务才会生效
2、如果任务大小小于1m该设置不会生效
3、从3.4.1开始如果线程数为1文件初始化时将不再预占用对应长度的空间下载多少byte则占多大的空间
对于3.4.1之前版本的未完成的老任务,依然采用原来的文件空间占用方式;
-->
<threadNum value="1"/>
<!--设置下载队列最大任务数, 默认为2-->
<maxTaskNum value="1"/>
<!--设置下载失败重试次数默认为10-->
<reTryNum value="10"/>
<!--设置重试间隔单位为毫秒默认2000毫秒-->
<reTryInterval value="5000"/>
<!--设置url连接超时时间单位为毫秒默认5000毫秒-->
<connectTimeOut value="5000"/>
<!--设置IO流读取时间单位为毫秒默认20000毫秒该时间不能少于10000毫秒-->
<iOTimeOut value="10000"/>
<!--设置写文件buff大小该数值大小不能小于2048数值变小下载速度会变慢-->
<buffSize value="8192"/>
<!--设置https ca 证书信息path 为assets目录下的CA证书完整路径name 为CA证书名-->
<ca name="" path=""/>
<!--是否需要转换速度单位转换完成后为1b/s、1kb/s、1mb/s、1gb/s、1tb/s如果不需要将返回byte长度-->
<convertSpeed value="true"/>
<!--执行队列类型见com.arialyy.aria.core.QueueMod默认类型为wait-->
<queueMod value="wait"/>
<!--进度更新更新间隔默认1000毫秒-->
<updateInterval value="1000"/>
</download>
<!--普通上传任务-->
<upload>
<!--设置任务最大上传速度0表示不限速单位为kb-->
<maxSpeed value="0"/>
<!--设置IO流读取时间单位为毫秒默认20000毫秒该时间不能少于10000毫秒-->
<iOTimeOut value="10000"/>
<!--设置写文件buff大小该数值大小不能小于2048数值变小速度会变慢-->
<buffSize value="8192"/>
<!--是否需要转换速度单位转换完成后为1b/s、1kb/s、1mb/s、1gb/s、1tb/s如果不需要将返回byte长度-->
<convertSpeed value="true"/>
<!--设置上传队列最大任务数, 默认为2-->
<maxTaskNum value="2"/>
<!--设置上传失败重试次数默认为10-->
<reTryNum value="3"/>
<!--设置重试间隔,单位为毫秒-->
<reTryInterval value="2000"/>
<!--设置url连接超时时间单位为毫秒默认5000毫秒-->
<connectTimeOut value="5000"/>
<!--执行队列类型见com.arialyy.aria.core.QueueMod默认类型为wait-->
<queueMod value="wait"/>
<!--进度更新更新间隔默认1000毫秒-->
<updateInterval value="1000"/>
</upload>
<!-- 下载类组合任务 -->
<dGroup>
<!--组合任务下载队列最大任务数, 默认为2-->
<maxTaskNum value="1"/>
<!--设置下载失败重试次数默认为10-->
<reTryNum value="10"/>
<!--设置重试间隔单位为毫秒默认2000毫秒-->
<reTryInterval value="5000"/>
<!--执行队列类型见com.arialyy.aria.core.QueueMod默认类型为wait-->
<queueMod value="wait"/>
<!--进度更新更新间隔默认1000毫秒-->
<updateInterval value="1000"/>
<!-- =============================以下为子任务的配置====================================-->
<!--能同时下载的子任务最大任务数默认3-->
<subMaxTaskNum value="1"/>
<!--子任务下载失败时的重试次数默认为5-->
<subReTryNum value="5"/>
<!--子任务下载失败时的重试间隔单位为毫秒默认2000毫秒-->
<subReTryInterval value="5000"/>
<!--子任务url连接超时时间单位为毫秒默认5000毫秒-->
<connectTimeOut value="5000"/>
<!--子任务IO流读取时间单位为毫秒默认20000毫秒该时间不能少于10000毫秒-->
<iOTimeOut value="10000"/>
<!--子任务写文件buff大小该数值大小不能小于2048数值变小下载速度会变慢-->
<buffSize value="8192"/>
<!--子任务 https ca 证书信息path 为assets目录下的CA证书完整路径name 为CA证书名-->
<ca name="" path=""/>
<!--子任务是否需要转换速度单位转换完成后为1b/s、1kb/s、1mb/s、1gb/s、1tb/s如果不需要将返回byte长度-->
<convertSpeed value="true"/>
<!--子任务的最大下载速度0表示不限速单位为kb; -->
<maxSpeed value="0"/>
</dGroup>
</aria>

View File

@@ -7,14 +7,16 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Color;
import android.os.IBinder;
import android.os.RemoteException;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
@@ -23,24 +25,19 @@ import androidx.fragment.app.FragmentTransaction;
import androidx.viewpager.widget.ViewPager;
import com.alarmclock.uiui.IAlarmAidlInterface;
import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationListener;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.qweather.sdk.bean.base.Code;
import com.qweather.sdk.bean.base.Lang;
import com.qweather.sdk.bean.base.Unit;
import com.qweather.sdk.bean.weather.WeatherNowBean;
import com.qweather.sdk.view.QWeather;
import com.uiui.os.R;
import com.uiui.os.base.BaseActivity;
import com.uiui.os.bean.AlarmItem;
import com.uiui.os.bean.BaseResponse;
import com.uiui.os.fragment.AppListFragment;
import com.uiui.os.fragment.BaseFragmentPagerAdapter;
import com.uiui.os.fragment.CustomFragment;
import com.uiui.os.utils.AmapManager;
import com.uiui.os.utils.ApkUtils;
import com.uiui.os.network.NetInterfaceManager;
import com.uiui.os.utils.APKUtils;
import com.uiui.os.utils.TimeUtils;
import com.uiui.os.utils.Utils;
import com.uiui.os.view.ScaleCircleNavigator;
import net.lucode.hackware.magicindicator.MagicIndicator;
@@ -52,6 +49,8 @@ import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import io.reactivex.rxjava3.core.Observer;
import io.reactivex.rxjava3.disposables.Disposable;
public class MainActivity extends BaseActivity {
private String TAG = MainActivity.class.getSimpleName();
@@ -111,9 +110,9 @@ public class MainActivity extends BaseActivity {
customFragment.setAlarmItem(null);
return;
}
Type type = new TypeToken<AlarmItem>() {
Type type = new TypeToken<List<AlarmItem>>() {
}.getType();
AlarmItem alarmItem = new Gson().fromJson(json, type);
List<AlarmItem> alarmItem = new Gson().fromJson(json, type);
customFragment.setAlarmItem(alarmItem);
} catch (RemoteException e) {
e.printStackTrace();
@@ -142,7 +141,7 @@ public class MainActivity extends BaseActivity {
public void initData() {
registmNewAppReceiver();
fragments.add(customFragment);
ArrayList<ApplicationInfo> applicationInfoList = ApkUtils.queryFilterAppInfo(this);
ArrayList<ApplicationInfo> applicationInfoList = APKUtils.queryFilterAppInfo(this);
int x = 0;
for (int i = 0; i <= applicationInfoList.size(); i++) {
if (i != 0 && i % APP_LIST_SIZE == 0) {
@@ -176,7 +175,7 @@ public class MainActivity extends BaseActivity {
private void addData() {
List<Fragment> fragmentList = new ArrayList<>();
ArrayList<ApplicationInfo> applicationInfoList = ApkUtils.queryFilterAppInfo(this);
ArrayList<ApplicationInfo> applicationInfoList = APKUtils.queryFilterAppInfo(this);
int x = 0;
for (int i = 0; i <= applicationInfoList.size(); i++) {
if (i != 0 && i % APP_LIST_SIZE == 0) {
@@ -245,7 +244,58 @@ public class MainActivity extends BaseActivity {
@Override
protected void onResume() {
super.onResume();
String packagename = TimeUtils.getInstance().getAppPackageName();
Log.e("SendcloseApp", "packagename=" + packagename);
TimeUtils.getInstance().setEndTime(System.currentTimeMillis());
if (packagename != null && packagename.length() > 0) {
ApplicationInfo app = APKUtils.getApplicationInfo(this, packagename);
PackageManager pm = getPackageManager();
if (app != null) {
Log.e(TAG, "onResume: " + app.loadLabel(pm).toString());
Log.e(TAG, "onResume: " + app.packageName);
NetInterfaceManager.getInstance().getAppUsageRecordControl()
.sendappUsageRecord(Utils.getSerial(),
app.loadLabel(pm).toString(), app.packageName,
TimeUtils.getInstance().getStartTime() / 1000,
TimeUtils.getInstance().getEndTime() / 1000)
.subscribe(new Observer<BaseResponse>() {
@Override
public void onSubscribe(Disposable d) {
Log.e("onResume", "onSubscribe: ");
}
@Override
public void onNext(BaseResponse baseResponse) {
Log.e("onResume", "onNext: " + baseResponse);
}
@Override
public void onError(Throwable e) {
Log.e("onResume", "onError: " + e.getMessage());
}
@Override
public void onComplete() {
Log.e("onResume", "onComplete: ");
}
});
TimeUtils.getInstance().setAppPackageName("");
} else {
Log.e("fht", "app = null" + packagename);
}
}
getAlarmData();
}
@Override
protected void onRestart() {
super.onRestart();
}
@Override
protected void onStop() {
super.onStop();
}
private void registmNewAppReceiver() {
@@ -264,7 +314,10 @@ public class MainActivity extends BaseActivity {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.e(TAG, "onReceive: " + action);
addData();
if (Intent.ACTION_PACKAGE_ADDED.equals(action)
|| Intent.ACTION_MANAGED_PROFILE_REMOVED.equals(action)) {
addData();
}
}
}
}

View File

@@ -0,0 +1,21 @@
package com.uiui.os.activity;
import com.uiui.os.base.BasePresenter;
import com.uiui.os.base.BaseView;
import com.uiui.os.bean.AlarmClockData;
import java.util.List;
public class MainContact {
public interface Presenter extends BasePresenter<MainView> {
//设置所有信息
void getAlarmClock();
}
public interface MainView extends BaseView {
//获取所有信息
void setAlarmClock(List<AlarmClockData> dataList);
}
}

View File

@@ -0,0 +1,90 @@
package com.uiui.os.activity;
import android.content.Context;
import android.util.Log;
import com.tencent.mmkv.MMKV;
import com.trello.rxlifecycle4.android.ActivityEvent;
import com.uiui.os.bean.AlarmClockData;
import com.uiui.os.bean.BaseResponse;
import com.uiui.os.network.NetInterfaceManager;
import com.uiui.os.utils.AlarmUtils;
import java.util.List;
import io.reactivex.rxjava3.core.Observer;
import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.subjects.BehaviorSubject;
/**
* MainActivity和MainService 的 Presenter
*
* @author jgy02
*/
public class MainPresenter implements MainContact.Presenter {
private static final String TAG = MainPresenter.class.getSimpleName();
private static final int OK = 200;
private MainContact.MainView mView;
private Context mContext;
private BehaviorSubject<ActivityEvent> lifecycle;
public void setLifecycle(BehaviorSubject<ActivityEvent> lifecycle) {
this.lifecycle = lifecycle;
}
public BehaviorSubject<ActivityEvent> getLifecycle() {
return lifecycle;
}
public MainPresenter(Context context) {
this.mContext = context;
Log.e(TAG, "MainPresenter: " + context.getClass());
}
@Override
public void attachView(@androidx.annotation.NonNull MainContact.MainView view) {
this.mView = view;
}
@Override
public void detachView() {
this.mView = null;
}
@Override
public void getAlarmClock() {
MMKV mmkv = MMKV.defaultMMKV();
NetInterfaceManager.getInstance().getAlarmClockApiObservable()
.subscribe(new Observer<BaseResponse<List<AlarmClockData>>>() {
@Override
public void onSubscribe(Disposable d) {
Log.e("getAlarmClock", "onSubscribe: ");
}
@Override
public void onNext(BaseResponse<List<AlarmClockData>> listBaseResponse) {
Log.e("getAlarmClock", "onNext: "+listBaseResponse);
if (listBaseResponse.code == 200) {
List<AlarmClockData> data = listBaseResponse.data;
AlarmUtils.getInstance().setAlarmClockData(data);
} else {
}
}
@Override
public void onError(Throwable e) {
Log.e("getAlarmClock", "onError: " + e.getMessage());
onComplete();
}
@Override
public void onComplete() {
Log.e("getAlarmClock", "onComplete: ");
}
});
}
}

View File

@@ -0,0 +1,125 @@
package com.uiui.os.activity;
import androidx.appcompat.app.AppCompatActivity;
import androidx.constraintlayout.widget.ConstraintLayout;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import com.blankj.utilcode.util.FileUtils;
import com.uiui.os.R;
import com.uiui.os.bean.AlarmClockData;
import com.uiui.os.utils.AlarmUtils;
import com.uiui.os.utils.Utils;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import butterknife.BindView;
import butterknife.ButterKnife;
public class NoticeActivity extends AppCompatActivity {
@BindView(R.id.tv_title)
TextView tv_title;
@BindView(R.id.bt_ok)
Button bt_ok;
@BindView(R.id.constraintLayout)
ConstraintLayout constraintLayout;
private AlarmClockData alarmClockData;
int code;
private MediaPlayer mediaPlayer;
private String TAG = NoticeActivity.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_notice);
ButterKnife.bind(this);
Intent intent = getIntent();
code = intent.getIntExtra("id", -1);
if (code == -1) {
finish();
} else {
HashMap<Integer, AlarmClockData> oldData = AlarmUtils.getInstance().getOldData();
alarmClockData = oldData.get(code);
if (alarmClockData == null) {
finish();
}
showData(alarmClockData);
}
}
private void showData(AlarmClockData alarmClockData) {
tv_title.setText(alarmClockData.getRemarks());
bt_ok.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
HashMap<Integer, AlarmClockData> oldData = AlarmUtils.getInstance().getOldData();
List<AlarmClockData> data = new ArrayList<>();
for (AlarmClockData alarm : oldData.values()) {
if (alarm.getId() == code) {
alarm.setFinished(true);
}
data.add(alarm);
}
AlarmUtils.getInstance().setAlarmString(data);
finish();
}
});
String url = alarmClockData.getVoice();
String md5 = alarmClockData.getVoice_md5();
if (!TextUtils.isEmpty(url)) {
constraintLayout.setVisibility(View.VISIBLE);
String fileName = Utils.getFileNamefromURL(url);
File file = new File(Utils.getDownLoadPath(NoticeActivity.this) + fileName);
String fileMD5 = FileUtils.getFileMD5ToString(file);
// if (!md5.equals(fileMD5)) {
// // TODO: 2021/12/16
// } else {
mediaPlayer = new MediaPlayer();
try {
// 切歌之前先重置,释放掉之前的资源
mediaPlayer.reset();
FileInputStream fis = new FileInputStream(file);
mediaPlayer.setDataSource(fis.getFD());
// 设置播放源
// mediaPlayer.setDataSource(file.getAbsolutePath());
// 开始播放前的准备工作,加载多媒体资源,获取相关信息
mediaPlayer.prepare();
// 开始播放
mediaPlayer.start();
} catch (IOException e) {
e.printStackTrace();
Log.e(TAG, "showData: " + e.getMessage());
}
// }
} else {
constraintLayout.setVisibility(View.GONE);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mediaPlayer != null) {
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
}
mediaPlayer.release();
mediaPlayer = null;
}
}
}

View File

@@ -0,0 +1,61 @@
package com.uiui.os.adapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.uiui.os.R;
import com.uiui.os.bean.AlarmItem;
import java.util.List;
public class AlarmClockAdapter extends RecyclerView.Adapter<AlarmClockAdapter.ViewHolder> {
private List<AlarmItem> alarmItemList;
public void setAlarmItemList(List<AlarmItem> alarmItems) {
this.alarmItemList = alarmItems;
notifyDataSetChanged();
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new AlarmClockAdapter.ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_alarmclock, parent, false));
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
AlarmItem alarmItem = alarmItemList.get(position);
holder.tv_time.setText(alarmItem.mTime);
holder.tv_type.setText(alarmItem.mRepeatType);
if (alarmItem.mActive) {
holder.tv_status.setText("打开");
} else {
holder.tv_status.setText("关闭");
}
}
@Override
public int getItemCount() {
return alarmItemList == null ? 0 : alarmItemList.size();
}
static class ViewHolder extends RecyclerView.ViewHolder {
TextView tv_time;
TextView tv_status;
TextView tv_type;
ViewHolder(@NonNull View itemView) {
super(itemView);
tv_time = itemView.findViewById(R.id.tv_time);
tv_status = itemView.findViewById(R.id.tv_status);
tv_type = itemView.findViewById(R.id.tv_type);
}
}
}

View File

@@ -0,0 +1,53 @@
package com.uiui.os.adapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.uiui.os.R;
import com.uiui.os.bean.AlarmClockData;
import java.util.List;
public class NotificationAdapter extends RecyclerView.Adapter<NotificationAdapter.Holder> {
private List<AlarmClockData> dataList;
@NonNull
@Override
public Holder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new Holder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_notification, parent, false));
}
@Override
public void onBindViewHolder(@NonNull Holder holder, int position) {
AlarmClockData alarmClockData = dataList.get(position);
holder.tv_title.setText("提醒事件:" + alarmClockData.getRemarks());
holder.tv_time.setText("提醒时间:" + alarmClockData.getTime());
}
@Override
public int getItemCount() {
return dataList == null ? 0 : dataList.size();
}
public void setDataList(List<AlarmClockData> data) {
this.dataList = data;
notifyDataSetChanged();
}
class Holder extends RecyclerView.ViewHolder {
TextView tv_title;
TextView tv_time;
public Holder(@NonNull View itemView) {
super(itemView);
tv_title = itemView.findViewById(R.id.tv_title);
tv_time = itemView.findViewById(R.id.tv_time);
}
}
}

View File

@@ -2,39 +2,78 @@ package com.uiui.os.base;
import android.os.Bundle;
import androidx.annotation.CallSuper;
import androidx.annotation.CheckResult;
import androidx.annotation.ContentView;
import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import com.trello.rxlifecycle4.LifecycleProvider;
import com.trello.rxlifecycle4.LifecycleTransformer;
import com.trello.rxlifecycle4.RxLifecycle;
import com.trello.rxlifecycle4.android.ActivityEvent;
import com.trello.rxlifecycle4.android.RxLifecycleAndroid;
import com.uiui.os.R;
import com.zackratos.ultimatebarx.ultimatebarx.java.UltimateBarX;
public abstract class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setBar();
//状态栏改变放在setContentView前后有所不同
setContentView(this.getLayoutId());
initView();
initData();
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.subjects.BehaviorSubject;
public abstract class BaseActivity extends AppCompatActivity implements LifecycleProvider<ActivityEvent> {
public final BehaviorSubject<ActivityEvent> lifecycleSubject = BehaviorSubject.create();
public BaseActivity() {
super();
}
private void setBar() {
@ContentView
public BaseActivity(@LayoutRes int contentLayoutId) {
super(contentLayoutId);
}
@Override
@NonNull
@CheckResult
public final Observable<ActivityEvent> lifecycle() {
return lifecycleSubject.hide();
}
@Override
@NonNull
@CheckResult
public final <T> LifecycleTransformer<T> bindUntilEvent(@NonNull ActivityEvent event) {
return RxLifecycle.bindUntilEvent(lifecycleSubject, event);
}
@Override
@NonNull
@CheckResult
public final <T> LifecycleTransformer<T> bindToLifecycle() {
return RxLifecycleAndroid.bindActivity(lifecycleSubject);
}
@Override
@CallSuper
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
lifecycleSubject.onNext(ActivityEvent.CREATE);
// StatusBarUtil.init(this);
UltimateBarX.statusBar(this)
.transparent()
.colorRes(R.color.colorPrimaryDark)
// .light(true)
.light(true)
.apply();
UltimateBarX.navigationBar(this)
.transparent()
.colorRes(R.color.colorPrimaryDark)
// .light(true)
.light(true)
.apply();
}
@Override
protected void onDestroy() {
super.onDestroy();
setContentView(this.getLayoutId());
initView();
initData();
}
/**
@@ -52,4 +91,39 @@ public abstract class BaseActivity extends AppCompatActivity {
* 初始化数据
*/
public abstract void initData();
@Override
@CallSuper
protected void onStart() {
super.onStart();
lifecycleSubject.onNext(ActivityEvent.START);
}
@Override
@CallSuper
protected void onResume() {
super.onResume();
lifecycleSubject.onNext(ActivityEvent.RESUME);
}
@Override
@CallSuper
protected void onPause() {
lifecycleSubject.onNext(ActivityEvent.PAUSE);
super.onPause();
}
@Override
@CallSuper
protected void onStop() {
lifecycleSubject.onNext(ActivityEvent.STOP);
super.onStop();
}
@Override
@CallSuper
protected void onDestroy() {
lifecycleSubject.onNext(ActivityEvent.DESTROY);
super.onDestroy();
}
}

View File

@@ -3,12 +3,20 @@ package com.uiui.os.base;
import android.annotation.SuppressLint;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import com.arialyy.aria.core.Aria;
import com.qweather.sdk.view.HeConfig;
import com.tencent.mmkv.MMKV;
import com.uiui.os.BuildConfig;
import com.uiui.os.network.NetInterfaceManager;
import com.uiui.os.service.MainService;
import com.uiui.os.utils.AlarmUtils;
import com.uiui.os.utils.AmapManager;
import com.uiui.os.utils.TimeUtils;
public class BaseApplication extends Application {
@@ -35,8 +43,20 @@ public class BaseApplication extends Application {
public void onCreate() {
super.onCreate();
context = this;
if (!BuildConfig.DEBUG) {
catchException();
}
String rootDir = MMKV.initialize(this);
Log.e(TAG, "mmkv root: " + rootDir);
Aria.init(this);
Aria.get(this).getDownloadConfig().setMaxTaskNum(1);
Aria.get(this).getDownloadConfig().setConvertSpeed(true);
TimeUtils.init(this);
AlarmUtils.init(this);
HeConfig.init("HE2111041506381545", "32b5ec69545e44119583a5e0ed4e87df");
AmapManager.init(this);
NetInterfaceManager.init(this);
startService(new Intent(this, MainService.class));
}

View File

@@ -0,0 +1,10 @@
package com.uiui.os.base;
import androidx.annotation.NonNull;
public interface BasePresenter<V extends BaseView> {
void attachView(@NonNull V view);
void detachView();
}

View File

@@ -0,0 +1,56 @@
package com.uiui.os.base;
import android.app.Service;
import android.content.Intent;
import androidx.annotation.NonNull;
import com.trello.rxlifecycle4.LifecycleProvider;
import com.trello.rxlifecycle4.LifecycleTransformer;
import com.trello.rxlifecycle4.RxLifecycle;
import com.trello.rxlifecycle4.android.ActivityEvent;
import com.trello.rxlifecycle4.android.RxLifecycleAndroid;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.subjects.BehaviorSubject;
public abstract class BaseService extends Service implements LifecycleProvider<ActivityEvent> {
public final BehaviorSubject<ActivityEvent> lifecycleSubject = BehaviorSubject.create();
public BaseService() {
super();
}
@Override
public final Observable<ActivityEvent> lifecycle() {
return lifecycleSubject.hide();
}
@Override
public final <T> LifecycleTransformer<T> bindUntilEvent(@NonNull ActivityEvent event) {
return RxLifecycle.bindUntilEvent(lifecycleSubject, event);
}
@Override
public final <T> LifecycleTransformer<T> bindToLifecycle() {
return RxLifecycleAndroid.bindActivity(lifecycleSubject);
}
@Override
public void onCreate() {
super.onCreate();
lifecycleSubject.onNext(ActivityEvent.CREATE);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
lifecycleSubject.onNext(ActivityEvent.STOP);
}
}

View File

@@ -0,0 +1,4 @@
package com.uiui.os.base;
public interface BaseView {
}

View File

@@ -0,0 +1,97 @@
package com.uiui.os.bean;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.gson.Gson;
import com.google.gson.JsonParser;
import java.io.Serializable;
public class AlarmClockData implements Serializable {
private static final long serialVersionUID = -5856502480745183157L;
int id;
int type;
String time;
String remarks;
String voice;
String voice_md5;
boolean finished = false;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public String getRemarks() {
return remarks;
}
public void setRemarks(String remarks) {
this.remarks = remarks;
}
public String getVoice() {
return voice;
}
public void setVoice(String voice) {
this.voice = voice;
}
public String getVoice_md5() {
return voice_md5;
}
public void setVoice_md5(String voice_md5) {
this.voice_md5 = voice_md5;
}
public boolean isFinished() {
return finished;
}
public void setFinished(boolean finished) {
this.finished = finished;
}
@NonNull
@Override
public String toString() {
return JsonParser.parseString(new Gson().toJson(this)).getAsJsonObject().toString();
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj == null) return false;
if (!(obj instanceof AlarmClockData)) return false;
if (id != ((AlarmClockData) obj).id) return false;
if (type != ((AlarmClockData) obj).type) return false;
if (!time.equals(((AlarmClockData) obj).time)) return false;
if (!remarks.equals(((AlarmClockData) obj).remarks)) return false;
if (!voice.equals(((AlarmClockData) obj).voice)) return false;
if (!voice_md5.equals(((AlarmClockData) obj).voice_md5)) return false;
return true;
}
}

View File

@@ -0,0 +1,23 @@
package com.uiui.os.bean;
import androidx.annotation.NonNull;
import com.google.gson.Gson;
import com.google.gson.JsonParser;
import java.io.Serializable;
public class BaseResponse<T> implements Serializable {
private static final long serialVersionUID = 5468533687801294972L;
public int code;
public String msg;
public T data;
@NonNull
@Override
public String toString() {
return JsonParser.parseString(new Gson().toJson(this)).getAsJsonObject().toString();
}
}

View File

@@ -1,12 +1,12 @@
package com.uiui.os.fragment;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.core.app.NavUtils;
import androidx.fragment.app.Fragment;
import android.util.Log;
@@ -16,17 +16,22 @@ import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.google.gson.JsonObject;
import com.uiui.os.R;
import com.uiui.os.utils.ApkUtils;
import com.uiui.os.bean.BaseResponse;
import com.uiui.os.network.NetInterfaceManager;
import com.uiui.os.utils.APKUtils;
import com.uiui.os.utils.BitmapUtils;
import com.uiui.os.utils.IconUtils;
import com.uiui.os.utils.TimeUtils;
import com.uiui.os.view.MyGridLayout;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import io.reactivex.rxjava3.core.Observer;
import io.reactivex.rxjava3.disposables.Disposable;
/**
* A simple {@link Fragment} subclass.
@@ -106,7 +111,7 @@ public class AppListFragment extends Fragment {
@Override
public View getView(int index) {
PackageManager pm = rootView.getContext().getPackageManager();
View view = getLayoutInflater().inflate(R.layout.actions_item,
View view = getLayoutInflater().inflate(R.layout.item_actions,
null);
ImageView iv = view.findViewById(R.id.iv);
TextView tv = view.findViewById(R.id.tv);
@@ -148,12 +153,50 @@ public class AppListFragment extends Fragment {
public void onItemClick(View v, int index) {
ApplicationInfo applicationInfo = applicationInfos.get(index);
if (applicationInfo != null) {
ApkUtils.openPackage(v.getContext(), applicationInfo.packageName);
APKUtils.openPackage(v.getContext(), applicationInfo.packageName);
TimeUtils.getInstance().setAppPackageName(applicationInfo.packageName);
TimeUtils.getInstance().setStartTime(System.currentTimeMillis());
SendRunningApp(getActivity());
}
}
});
}
private void SendRunningApp(Context context) {
String packageName = TimeUtils.getInstance().getAppPackageName();
long time = TimeUtils.getInstance().getStartTime();
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("app_package", packageName);
jsonObject.addProperty("version_name", APKUtils.getAPPVersionName(context, packageName));
jsonObject.addProperty("start_time", time / 1000);
String jsonString = jsonObject.toString();
Log.e(TAG, "SendRunningApp: " + jsonString);
NetInterfaceManager.getInstance()
.getRunningAppObservable(jsonString)
.subscribe(new Observer<BaseResponse>() {
@Override
public void onSubscribe(Disposable d) {
Log.e("SendRunningApp", "onSubscribe: ");
}
@Override
public void onNext(BaseResponse baseResponse) {
Log.e("SendRunningApp", "onSubscribe: " + baseResponse);
}
@Override
public void onError(Throwable e) {
Log.e("SendRunningApp", "onError: " + e.getMessage());
onComplete();
}
@Override
public void onComplete() {
Log.e("SendRunningApp", "onComplete: ");
}
});
}
public void setAppList(ArrayList<ApplicationInfo> appList) {
this.applicationInfos = appList;
}

View File

@@ -5,13 +5,20 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.BatteryManager;
import android.os.Bundle;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.SystemClock;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -22,45 +29,73 @@ import android.widget.TextView;
import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationListener;
import com.blankj.utilcode.util.NetworkUtils;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.king.view.circleprogressview.CircleProgressView;
import com.qweather.sdk.bean.base.Code;
import com.qweather.sdk.bean.base.Lang;
import com.qweather.sdk.bean.base.Unit;
import com.qweather.sdk.bean.weather.WeatherNowBean;
import com.qweather.sdk.view.QWeather;
import com.tencent.mmkv.MMKV;
import com.uiui.os.BuildConfig;
import com.uiui.os.R;
import com.uiui.os.adapter.AlarmClockAdapter;
import com.uiui.os.adapter.NotificationAdapter;
import com.uiui.os.bean.AlarmClockData;
import com.uiui.os.bean.AlarmItem;
import com.uiui.os.utils.AmapManager;
import com.uiui.os.utils.ApkUtils;
import com.uiui.os.utils.APKUtils;
import com.uiui.os.utils.AppUtil;
import com.uiui.os.utils.Utils;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
/**
* A simple {@link Fragment} subclass.
* Use the {@link CustomFragment#newInstance} factory method to
* create an instance of this fragment.
*/
public class CustomFragment extends Fragment {
public class CustomFragment extends Fragment implements NetworkUtils.OnNetworkStatusChangedListener {
@BindView(R.id.tv_add)
TextView tv_add;
@BindView(R.id.tv_battery)
TextView tv_battery;
@BindView(R.id.tv_location)
TextView tv_location;
@BindView(R.id.iv_pic)
ImageView iv_pic;
@BindView(R.id.tv_temp)
TextView tv_temp;
@BindView(R.id.cpv)
CircleProgressView cpv;
@BindView(R.id.cl_alarm)
ConstraintLayout cl_alarm;
@BindView(R.id.iv_charging)
ImageView iv_charging;
@BindView(R.id.recyclerView)
RecyclerView recyclerView;
@BindView(R.id.rv_clock)
RecyclerView rv_clock;
@BindView(R.id.wifi_ssid)
TextView wifi_ssid;
@BindView(R.id.cl_wifi)
ConstraintLayout cl_wifi;
private String TAG = CustomFragment.class.getSimpleName();
private TextView tv_time,tv_add, tv_type, tv_status;
private ImageView iv_pic;
private TextView tv_temp;
private TextView tv_battery;
private TextView tv_location;
private CircleProgressView cpv;
private ConstraintLayout cl_alarm;
private ImageView iv_charging;
private int[] mShaderColors = new int[]{0xFFfa3db5, 0xFFF8867E, 0xFFF79F6B, 0xFFF79F6B, 0xFFF79F6B, 0xFFF8867E, 0xFFfa3db5};
private View rootView;
private List<AlarmItem> alarmItemList;
private NotificationAdapter notificationAdapter;
private AlarmClockAdapter alarmClockAdapter;
private MMKV mmkv;
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
@@ -71,9 +106,6 @@ public class CustomFragment extends Fragment {
private String mParam1;
private String mParam2;
private View rootView;
private AlarmItem alarmItem;
public CustomFragment() {
// Required empty public constructor
}
@@ -96,18 +128,20 @@ public class CustomFragment extends Fragment {
return fragment;
}
public void setAlarmItem(AlarmItem item) {
this.alarmItem = item;
public void setAlarmItem(List<AlarmItem> alarmItem) {
this.alarmItemList = alarmItem;
setAlarm();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
NetworkUtils.registerNetworkStatusChangedListener(this);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
mmkv = MMKV.defaultMMKV();
registerBatteryReceiver();
getActivity().registerReceiver(mbatteryReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
}
@@ -128,6 +162,39 @@ public class CustomFragment extends Fragment {
BatteryReceiver batteryReceiver;
@Override
public void onDisconnected() {
wifi_ssid.setText("WiFi未连接");
}
@Override
public void onConnected(NetworkUtils.NetworkType networkType) {
if (networkType == NetworkUtils.NetworkType.NETWORK_WIFI) {
wifi_ssid.setText(getConnectWifiSsid());
} else {
wifi_ssid.setText("WiFi未连接");
}
}
private String getConnectWifiSsid() {
WifiManager wifiManager = (WifiManager) getActivity().getSystemService(Context.WIFI_SERVICE);
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
Log.d("wifiInfo", wifiInfo.toString());
Log.d("SSID", wifiInfo.getSSID());
return wifiInfo.getSSID();
}
/**
* 检查wifi是否处开连接状态
*
* @return
*/
public boolean isWifiConnect() {
ConnectivityManager connManager = (ConnectivityManager) getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo mWifiInfo = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
return mWifiInfo.isConnected();
}
private class BatteryReceiver extends BroadcastReceiver {
@Override
@@ -139,7 +206,7 @@ public class CustomFragment extends Fragment {
// 最大电量
int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, 0);
int elec = (level * 100) / scale;
Log.e(TAG, "electricity:=" + elec + "%");
Log.i(TAG, "electricity:=" + elec + "%");
tv_battery.setText(elec + "%");
} else if (Intent.ACTION_POWER_CONNECTED.equals(action)
|| Intent.ACTION_POWER_DISCONNECTED.equals(action)
@@ -155,14 +222,14 @@ public class CustomFragment extends Fragment {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.e(TAG, "onReceive: " + action);
Log.i(TAG, "onReceive: " + action);
if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
int status = intent.getIntExtra("status", BatteryManager.BATTERY_STATUS_UNKNOWN);
if (status == BatteryManager.BATTERY_STATUS_CHARGING) {
if (rootView != null) {
iv_charging.setVisibility(View.VISIBLE);
}
}else {
} else {
if (rootView != null) {
iv_charging.setVisibility(View.GONE);
}
@@ -176,67 +243,63 @@ public class CustomFragment extends Fragment {
Bundle savedInstanceState) {
// Inflate the layout for this fragment
rootView = inflater.inflate(R.layout.fragment_custom, container, false);
ButterKnife.bind(this, rootView);
initView();
initData();
return rootView;
}
private void initView() {
tv_time = rootView.findViewById(R.id.tv_time);
tv_add = rootView.findViewById(R.id.tv_add);
tv_type = rootView.findViewById(R.id.tv_type);
tv_status = rootView.findViewById(R.id.tv_status);
iv_pic = rootView.findViewById(R.id.iv_pic);
tv_temp = rootView.findViewById(R.id.tv_temp);
tv_location = rootView.findViewById(R.id.tv_location);
tv_battery = rootView.findViewById(R.id.tv_battery);
Log.e(TAG, "initView: " + Utils.getBatteryLevel(getActivity()));
tv_battery.setText(Utils.getBatteryLevel(getActivity()) + "%");
cpv = rootView.findViewById(R.id.cpv);
cpv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
killBackgroundApp();
}
});
cl_alarm = rootView.findViewById(R.id.cl_alarm);
cl_alarm.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ApkUtils.openPackage(getActivity(), "com.alarmclock.uiui");
APKUtils.openPackage(getActivity(), "com.alarmclock.uiui");
}
});
iv_charging = rootView.findViewById(R.id.iv_charging);
notificationAdapter = new NotificationAdapter();
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
recyclerView.setAdapter(notificationAdapter);
if (isWifiConnect()) {
wifi_ssid.setText(getConnectWifiSsid());
} else {
wifi_ssid.setText("WiFi未连接");
}
cl_wifi.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS)); //直接进入手机中的wifi网络设置界面
}
});
alarmClockAdapter = new AlarmClockAdapter();
rv_clock.setLayoutManager(new LinearLayoutManager(getActivity()));
rv_clock.setAdapter(alarmClockAdapter);
setAlarm();
refreshMemory();
}
private void setAlarm() {
if (rootView == null) return;
if (alarmItem == null) {
tv_time.setText("暂无闹钟");
tv_time.setVisibility(View.GONE);
if (alarmItemList == null) {
tv_add.setVisibility(View.VISIBLE);
tv_type.setVisibility(View.GONE);
tv_status.setVisibility(View.GONE);
rv_clock.setVisibility(View.GONE);
} else {
tv_time.setText(alarmItem.mTime);
tv_time.setVisibility(View.VISIBLE);
tv_add.setVisibility(View.GONE);
tv_type.setText(alarmItem.mRepeatType);
tv_type.setVisibility(View.VISIBLE);
tv_status.setVisibility(View.VISIBLE);
if (alarmItem.mActive) {
tv_status.setText("打开");
} else {
tv_status.setText("关闭");
}
rv_clock.setVisibility(View.VISIBLE);
alarmClockAdapter.setAlarmItemList(alarmItemList);
}
}
private void initData() {
initAmap();
getAlarmClock();
}
private void initAmap() {
@@ -258,6 +321,17 @@ public class CustomFragment extends Fragment {
});
}
private void getAlarmClock() {
String jsonString = mmkv.decodeString("AlarmClock", "");
if (!TextUtils.isEmpty(jsonString)) {
Type type = new TypeToken<List<AlarmClockData>>() {
}.getType();
Gson gson = new Gson();
List<AlarmClockData> data = gson.fromJson(jsonString, type);
notificationAdapter.setDataList(data);
}
}
private void getweather(double longitude, double latitude) {
/**
* 实况天气数据
@@ -276,7 +350,7 @@ public class CustomFragment extends Fragment {
@Override
public void onSuccess(WeatherNowBean weatherBean) {
Log.e(TAG, "getWeather onSuccess: " + new Gson().toJson(weatherBean));
// Log.e(TAG, "getWeather onSuccess: " + new Gson().toJson(weatherBean));
//先判断返回的status是否正确当status正确时获取数据若status不正确可查看status对应的Code值找到原因
if (Code.OK == weatherBean.getCode()) {
WeatherNowBean.NowBaseBean now = weatherBean.getNow();
@@ -295,7 +369,7 @@ public class CustomFragment extends Fragment {
private void killBackgroundApp() {
List<String> pkgList = ApkUtils.queryFilterAppList(getActivity());
List<String> pkgList = APKUtils.queryFilterAppList(getActivity());
for (String pkg : pkgList) {
if (pkg.equalsIgnoreCase(BuildConfig.APPLICATION_ID)) continue;
killBackgroundProcesses(pkg);
@@ -333,6 +407,7 @@ public class CustomFragment extends Fragment {
@Override
public void onDestroy() {
super.onDestroy();
NetworkUtils.unregisterNetworkStatusChangedListener(this);
if (batteryReceiver != null) {
getActivity().unregisterReceiver(batteryReceiver);
}

View File

@@ -0,0 +1,178 @@
package com.uiui.os.network;
import android.annotation.SuppressLint;
import android.content.Context;
import android.util.Log;
import com.uiui.os.bean.AlarmClockData;
import com.uiui.os.bean.BaseResponse;
import com.uiui.os.network.api.AlarmClockApi;
import com.uiui.os.network.api.AppUsageRecordApi;
import com.uiui.os.network.api.RunNewApp;
import com.uiui.os.network.api.SendScreenshotApi;
import com.uiui.os.utils.MD5Util;
import com.uiui.os.utils.Utils;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.schedulers.Schedulers;
import okhttp3.Cache;
import okhttp3.Headers;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Protocol;
import okhttp3.Request;
import okhttp3.Response;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
public class NetInterfaceManager {
@SuppressLint("StaticFieldLeak")
private static NetInterfaceManager INSTANCE;
private Context mContext;
private Retrofit mRetrofit;
private OkHttpClient okHttpClient;
private final ConcurrentHashMap<String, Long> requestIdsMap = new ConcurrentHashMap<>();
//超时时间
private static int timeOut = 30;
// 缓存文件最大限制大小20M
private static long cacheSize = 1024 * 1024 * 64;
public static final String HTTP_KEY = "YTM3YTAxNTJmMmZmNzkyM2E2YzIwZjlhZTc0NzNmMGI=";
public static final String CUSTOM_REPEAT_REQ_PROTOCOL = "MY_CUSTOM_REPEAT_REQ_PROTOCOL";
private NetInterfaceManager(Context context) {
this.mContext = context;
if (okHttpClient == null) {
Interceptor interceptor = new Interceptor() {
@NotNull
@Override
public Response intercept(@NotNull Chain chain) throws IOException {
Request request = chain.request();
//相同的请求
String requestKey = MD5Util.getUpperMD5Str(request.method() + request.url().toString());
long time = System.currentTimeMillis();//请求时间
try {
if (requestIdsMap.size() > 0 && requestIdsMap.containsKey(requestKey)) {
Log.e("REPEAT-REQUEST", "重复请求:" + requestKey + " Method @" + request.method() + " --- " + " URL = " + request.url());
chain.call().cancel();
return new Response.Builder()
.protocol(Protocol.get(CUSTOM_REPEAT_REQ_PROTOCOL))
.request(request) //multi thread
.build();
}
requestIdsMap.put(requestKey, time);
Log.e("REPEAT-REQUEST", "注册请求:" + requestKey + " Method @" + request.method() + " --- " + " URL = " + request.url());
// Request.Builder builder = request.newBuilder();
// builder.addHeader("header", jsonObject.toString());
return chain.proceed(request);
} catch (IOException e) {
throw e;
} finally {
if (requestIdsMap.containsKey(requestKey) && requestIdsMap.containsValue(time)) {//请求任务完成删除map中的数据
requestIdsMap.remove(requestKey);
Log.e("REPEAT-REQUEST", "移除请求:" + requestKey + " Method @" + request.method() + " --- " + " URL = " + request.url());
}
}
}
};
//如果无法生存缓存文件目录,检测权限使用已经加上,检测手机是否把文件读写权限禁止了
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.connectTimeout(timeOut, TimeUnit.SECONDS); // 设置连接超时时间
builder.writeTimeout(timeOut, TimeUnit.SECONDS);// 设置写入超时时间
builder.readTimeout(timeOut, TimeUnit.SECONDS);// 设置读取数据超时时间
builder.retryOnConnectionFailure(true);// 设置进行连接失败重试
builder.addInterceptor(interceptor);
// 设置缓存文件路径
String cacheDirectory = mContext.getExternalCacheDir().getAbsolutePath() + "/OkHttpCache";
Cache cache = new Cache(new File(cacheDirectory), cacheSize);
builder.cache(cache);// 设置缓存
okHttpClient = builder.build();
}
if (mRetrofit == null) {
mRetrofit = new Retrofit.Builder()
.client(okHttpClient)
.baseUrl(URLAddress.ROOT_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava3CallAdapterFactory.create())
.build();
}
}
/**
* 打印全局统一拦截添加的Http Headers
* <p>
* 全局拦截的http 没法在配置中直接打印处理因为先http 请求然后打印然后拦截添加的
*
* @param request
*/
private static void logRequestHeaders(Request request) {
Log.e("OKhttp ", " 开始打印HTTP请求 Headers \n");
Headers headers = request.headers();
for (int i = 0, count = headers.size(); i < count; i++) {
String name = headers.name(i);
// Skip headers from the request body as they are explicitly logged above.
if (!"Content-Type".equalsIgnoreCase(name) && !"Content-Length".equalsIgnoreCase(name)) {
Log.e("OKhttp: " + i + " ", name + ": " + headers.value(i));
}
}
Log.e("OKhttp ", " 打印HTTP请求完成 Headers \n");
}
public static void init(Context context) {
if (INSTANCE == null) {
INSTANCE = new NetInterfaceManager(context);
}
}
public static NetInterfaceManager getInstance() {
if (INSTANCE == null) {
throw new IllegalStateException("You must be init NetworkManager first");
}
return INSTANCE;
}
public OkHttpClient getOkHttpClient() {
return okHttpClient;
}
/**
* 通过sn获取设备的信息
*
* @return
*/
public Observable<BaseResponse<List<AlarmClockData>>> getAlarmClockApiObservable() {
return mRetrofit
.create(AlarmClockApi.class)
.getAlarmClockApiApi(Utils.getSerial())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
public Observable<BaseResponse> getRunningAppObservable(String json) {
return mRetrofit.create(RunNewApp.class)
.sendRunningInfo(Utils.getSerial(), json)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
public AppUsageRecordApi getAppUsageRecordControl() {
return mRetrofit.create(AppUsageRecordApi.class);
}
public SendScreenshotApi getScreenshotApi() {
return mRetrofit.create(SendScreenshotApi.class);
}
}

View File

@@ -0,0 +1,13 @@
package com.uiui.os.network;
public class URLAddress {
public static final String ROOT_URL = "https://led.aolelearn.cn/android/";
//获取闹钟
public static final String GET_ALARM_CLOCK = "getAlarmClock";
//应用使用记录
public static final String APP_USAGE_RECORD = "appUsageRecord";
//正在运行的应用
public static final String RUN_NEW_APP = "app/runNewApp";
//上传截图
public static final String SEND_SCREENSHOT = "sn/uploadScreenshot";
}

View File

@@ -0,0 +1,18 @@
package com.uiui.os.network.api;
import com.uiui.os.bean.AlarmClockData;
import com.uiui.os.bean.BaseResponse;
import com.uiui.os.network.URLAddress;
import java.util.List;
import io.reactivex.rxjava3.core.Observable;
import retrofit2.http.GET;
import retrofit2.http.Query;
public interface AlarmClockApi {
@GET(URLAddress.GET_ALARM_CLOCK)
Observable<BaseResponse<List<AlarmClockData>>> getAlarmClockApiApi(
@Query("sn") String sn
);
}

View File

@@ -0,0 +1,21 @@
package com.uiui.os.network.api;
import com.uiui.os.bean.BaseResponse;
import com.uiui.os.network.URLAddress;
import io.reactivex.rxjava3.core.Observable;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.POST;
public interface AppUsageRecordApi {
@FormUrlEncoded
@POST(URLAddress.APP_USAGE_RECORD)
Observable<BaseResponse> sendappUsageRecord(
@Field("sn") String sn,
@Field("app_name") String app_name,
@Field("app_package") String app_package,
@Field("open_time") long open_time,
@Field("close_time") long close_time
);
}

View File

@@ -0,0 +1,18 @@
package com.uiui.os.network.api;
import com.uiui.os.bean.BaseResponse;
import com.uiui.os.network.URLAddress;
import io.reactivex.rxjava3.core.Observable;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.POST;
public interface RunNewApp {
@FormUrlEncoded
@POST(URLAddress.RUN_NEW_APP)
Observable<BaseResponse> sendRunningInfo(
@Field("sn") String sn,
@Field("app") String app
);
}

View File

@@ -0,0 +1,23 @@
package com.uiui.os.network.api;
import com.uiui.os.bean.BaseResponse;
import com.uiui.os.network.URLAddress;
import java.util.Map;
import io.reactivex.rxjava3.core.Observable;
import okhttp3.MultipartBody;
import retrofit2.http.Multipart;
import retrofit2.http.POST;
import retrofit2.http.Part;
import retrofit2.http.Query;
public interface SendScreenshotApi {
@Multipart
@POST(URLAddress.SEND_SCREENSHOT)
Observable<BaseResponse> sendScreenshot(
@Query("sn") String sn,
@Part MultipartBody.Part file
);
}

View File

@@ -0,0 +1,88 @@
package com.uiui.os.receiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.SystemClock;
import android.text.TextUtils;
import android.util.Log;
import com.uiui.os.service.MainService;
import java.util.concurrent.TimeUnit;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.core.ObservableOnSubscribe;
import io.reactivex.rxjava3.core.Observer;
import io.reactivex.rxjava3.disposables.Disposable;
public class BootReceiver extends BroadcastReceiver {
private static String TAG = BootReceiver.class.getSimpleName();
public static final String BOOT_COMPLETED = "zuoyeos.action.BOOT_COMPLETED";
static {
getLockedState();
}
private static void getLockedState() {
Observable.create((ObservableOnSubscribe<Long>) emitter -> start = emitter::onNext)
.throttleLast(1, TimeUnit.HOURS)
.subscribe(new Observer<Long>() {
@Override
public void onSubscribe(Disposable d) {
Log.e("getLockedState", "onSubscribe: ");
}
@Override
public void onNext(Long aLong) {
}
@Override
public void onError(Throwable e) {
Log.e("getLockedState", "onError: " + e.getMessage());
}
@Override
public void onComplete() {
Log.e("getLockedState", "onComplete: ");
}
});
}
private interface Start {
void onstar(long time);
}
private static Start start;
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.e(TAG, "action:" + action);
if (TextUtils.isEmpty(action)) {
return;
}
switch (action) {
default:
break;
case BOOT_COMPLETED:
MainService.mPresenter.getAlarmClock();
case Intent.ACTION_BOOT_COMPLETED:
break;
case Intent.ACTION_BATTERY_CHANGED:
case Intent.ACTION_BATTERY_LOW:
case Intent.ACTION_BATTERY_OKAY:
case Intent.ACTION_POWER_CONNECTED:
case Intent.ACTION_POWER_DISCONNECTED:
case Intent.ACTION_DATE_CHANGED:
case Intent.ACTION_TIME_TICK:
case Intent.ACTION_USER_PRESENT:
case Intent.ACTION_SCREEN_OFF:
case Intent.ACTION_SCREEN_ON:
break;
}
}
}

View File

@@ -0,0 +1,17 @@
package com.uiui.os.service;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
public class AlarmService extends Service {
public AlarmService() {
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}

View File

@@ -0,0 +1,318 @@
package com.uiui.os.service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.IBinder;
import android.os.PowerManager;
import android.text.TextUtils;
import android.text.format.Formatter;
import android.util.Log;
import com.arialyy.annotations.Download;
import com.arialyy.aria.core.Aria;
import com.arialyy.aria.core.task.DownloadTask;
import com.blankj.utilcode.util.ImageUtils;
import com.blankj.utilcode.util.NetworkUtils;
import com.uiui.os.activity.MainContact;
import com.uiui.os.activity.MainPresenter;
import com.uiui.os.activity.NoticeActivity;
import com.uiui.os.base.BaseService;
import com.uiui.os.bean.AlarmClockData;
import com.uiui.os.bean.BaseResponse;
import com.uiui.os.network.NetInterfaceManager;
import com.uiui.os.utils.CmdUtil;
import com.uiui.os.utils.ForegroundAppUtil;
import com.uiui.os.utils.TimeUtils;
import com.uiui.os.utils.ToastUtil;
import com.uiui.os.utils.Utils;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.core.ObservableEmitter;
import io.reactivex.rxjava3.core.ObservableOnSubscribe;
import io.reactivex.rxjava3.core.ObservableSource;
import io.reactivex.rxjava3.core.Observer;
import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.functions.Function;
import io.reactivex.rxjava3.schedulers.Schedulers;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
public class MainService extends BaseService implements MainContact.MainView, NetworkUtils.OnNetworkStatusChangedListener {
private static final String TAG = MainService.class.getSimpleName();
public static MainPresenter mPresenter;
public MainService() {
}
@Override
public void onDisconnected() {
}
@Override
public void onConnected(NetworkUtils.NetworkType networkType) {
}
@Override
public IBinder onBind(Intent intent) {
Log.e(TAG, "onBind: ");
return null;
}
@Override
public void onCreate() {
super.onCreate();
Log.e(TAG, "onCreate: ");
Aria.init(this);
Aria.download(this).register();
mPresenter = new MainPresenter(this);
mPresenter.attachView(this);
mPresenter.setLifecycle(lifecycleSubject);
NetworkUtils.registerNetworkStatusChangedListener(this);
mPresenter.getAlarmClock();
registerAlarmReceiver();
registerTimeReceiver();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e(TAG, "onStartCommand: ");
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
mPresenter.detachView();
NetworkUtils.unregisterNetworkStatusChangedListener(this);
if (alarmReceiver != null) {
unregisterReceiver(alarmReceiver);
}
if (mTimeChangedReceiver != null) {
unregisterReceiver(mTimeChangedReceiver);
}
}
@Override
public void setAlarmClock(List<AlarmClockData> dataList) {
}
public static final String ALARMWAKEUP = "ALARM_WAKEUP";
private void registerAlarmReceiver() {
if (alarmReceiver == null) {
alarmReceiver = new AlarmReceiver();
}
IntentFilter filter = new IntentFilter();
filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
filter.addAction(ALARMWAKEUP);
registerReceiver(alarmReceiver, filter);
}
private AlarmReceiver alarmReceiver = new AlarmReceiver();
private class AlarmReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (TextUtils.isEmpty(action)) return;
Log.e(TAG, "onReceive: " + action);
String title = intent.getStringExtra("title");
int code = intent.getIntExtra("id", -1);
Log.e(TAG, "onReceive: title = " + title);
if (ALARMWAKEUP.equals(action)) {
Intent noticeIntent = new Intent();
noticeIntent.putExtra("id", code);
noticeIntent.setClass(MainService.this, NoticeActivity.class);
noticeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(noticeIntent);
}
}
}
//监听时间和日期变化
public void registerTimeReceiver() {
mTimeChangedReceiver = new TimeChangedReceiver();
IntentFilter filter = new IntentFilter();
filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
filter.addAction(Intent.ACTION_DATE_CHANGED);
filter.addAction(Intent.ACTION_TIME_CHANGED);
filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
filter.addAction(Intent.ACTION_TIME_TICK);
registerReceiver(mTimeChangedReceiver, filter);
}
private TimeChangedReceiver mTimeChangedReceiver;
private class TimeChangedReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_DATE_CHANGED.equals(intent.getAction())) {
Log.e(TAG, "TimeChangedReceiver:" + "data changed");
} else if (Intent.ACTION_TIME_CHANGED.equals(intent.getAction())) {
Log.e(TAG, "TimeChangedReceiver:" + "time changed");
} else if (Intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
Log.e(TAG, "TimeChangedReceiver:" + "timezone changed");
} else if (Intent.ACTION_TIME_TICK.equals(intent.getAction())) {
Log.e(TAG, "TimeChangedReceiver:" + "time tick");
isScreenshot();
}
}
}
private final static long ONE_HOURS_TIME = 60 * 60 * 1000;
private final static long TEN_MINUTES_TIME = 60 * 10 * 1000;
private void isScreenshot() {
//1、检测应用使用情况如果设备长时间运行一个应用超过1小时启动截屏一次。
//2、检测设备在非正常时间使用时使用第三方应用在运行10分钟后启动截屏功能一次
//屏幕未点亮时不用截图
// TODO: 2021/12/20 计算当前app打开时间
String topPackageName = ForegroundAppUtil.getForegroundPackageName(MainService.this);
Log.e(TAG, "isScreenshot: " + topPackageName);
String pkg = TimeUtils.getInstance().getAppPackageName();
if (TextUtils.isEmpty(pkg)) {
return;
}
PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
//true为打开false为关闭
boolean screenOn = powerManager.isInteractive();
Log.e(TAG, "isScreenshot: screenOn = " + screenOn);
if (!screenOn) return;
long startTime = TimeUtils.getInstance().getStartTime();
if (TimeUtils.getInstance().isNormalTime()) {//正常时间段
if (System.currentTimeMillis() - startTime >= ONE_HOURS_TIME) {
Log.e(TAG, "isScreenshot: " + "截图");
doscreenshot(this);
}
} else {//非正常时间段
if (System.currentTimeMillis() - startTime >= TEN_MINUTES_TIME) {
Log.e(TAG, "isScreenshot: " + "截图");
doscreenshot(this);
}
}
}
private static Observable<Integer> getScreenshot(Context context, String filePath) {
Observable<Integer> screenshotObservable = Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> e) {
int code = CmdUtil.execute("screencap -p " + filePath).code;
e.onNext(code);
e.onComplete();
}
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
return screenshotObservable;
}
private static Observable<BaseResponse> getSendFile(String path, MultipartBody.Part body) {
return NetInterfaceManager.getInstance()
.getScreenshotApi()
.sendScreenshot(Utils.getSerial(), body)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
public static void doscreenshot(Context context) {
long time = System.currentTimeMillis();
String path = context.getExternalFilesDir("db").getAbsolutePath();
String filePath = path + File.separator + time + ".png";
getScreenshot(context, filePath).concatMap(new Function<Integer, ObservableSource<BaseResponse>>() {
@Override
public ObservableSource<BaseResponse> apply(Integer integer) throws Exception {
if (integer != 0) {
throw new FileNotFoundException();
}
File file = new File(filePath);
if (!file.exists()) {
throw new FileNotFoundException(filePath);
}
Bitmap bitmap = BitmapFactory.decodeFile(filePath);
if (bitmap.getWidth() < bitmap.getHeight()) {
bitmap = ImageUtils.rotate(bitmap, -90, bitmap.getWidth(), bitmap.getHeight());
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
file.createNewFile();
FileOutputStream fos = new FileOutputStream(file);
InputStream is = new ByteArrayInputStream(baos.toByteArray());
int x;
byte[] b = new byte[1024 * 100];
while ((x = is.read(b)) != -1) {
fos.write(b, 0, x);
}
fos.close();
RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), file);
MultipartBody.Part body = MultipartBody.Part.createFormData("file", file.getName(), requestFile);
return getSendFile(filePath, body);
}
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<BaseResponse>() {
@Override
public void onSubscribe(Disposable d) {
Log.e("screenshot", "onSubscribe: ");
}
@Override
public void onNext(BaseResponse baseResponse) {
Log.e("screenshot", "onNext: " + baseResponse);
}
@Override
public void onError(Throwable e) {
Log.e("screenshot", "onError: " + e.getMessage());
onComplete();
}
@Override
public void onComplete() {
Log.e("screenshot", "onComplete: ");
}
});
}
//在这里处理任务执行中的状态,如进度进度条的刷新
@Download.onTaskRunning
protected void running(DownloadTask task) {
Log.e("aria", "正在下载:" + task.getPercent() + ":" + task.getExtendField());
ToastUtil.show("正在下载:" + task.getPercent() + "%" + "\t" + Formatter.formatFileSize(MainService.this, task.getSpeed()) + "/s");
}
@Download.onTaskComplete
void taskComplete(DownloadTask task) {
//在这里处理任务完成的状态
}
@Download.onTaskFail
void taskFail(DownloadTask task, Exception e) {
}
}

View File

@@ -1,9 +1,11 @@
package com.uiui.os.utils;
import android.app.Application;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.text.TextUtils;
@@ -17,7 +19,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class ApkUtils {
public class APKUtils {
private static String[] excludePackageName = {BuildConfig.APPLICATION_ID};
@@ -56,6 +58,7 @@ public class ApkUtils {
/**
* 获取第三方应用
*
* @param context
* @return
*/
@@ -77,6 +80,29 @@ public class ApkUtils {
return applicationInfos;
}
public static PackageInfo getPackageInfo(Context context, String pkg) {
PackageManager packageManager = context.getPackageManager();
PackageInfo packageInfo = null;
try {
packageInfo = packageManager.getPackageInfo(pkg, 0);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return packageInfo;
}
public static ApplicationInfo getApplicationInfo(Context context, String pkg) {
PackageManager packageManager = context.getPackageManager();
ApplicationInfo applicationInfo = null;
try {
applicationInfo = packageManager.getApplicationInfo(pkg, 0);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return applicationInfo;
}
public static void openApp(Context context, String packageName) {
Intent intent = context.getPackageManager().getLaunchIntentForPackage(packageName);
if (intent != null) {
@@ -86,14 +112,14 @@ public class ApkUtils {
}
public static Intent getAppOpenIntentByPackageName(Context context,String packageName){
public static Intent getAppOpenIntentByPackageName(Context context, String packageName) {
//Activity完整名
String mainAct = null;
//根据包名寻找
PackageManager pkgMag = context.getPackageManager();
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED|Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED | Intent.FLAG_ACTIVITY_NEW_TASK);
List<ResolveInfo> list = pkgMag.queryIntentActivities(intent,
PackageManager.GET_ACTIVITIES);
@@ -138,4 +164,20 @@ public class ApkUtils {
return false;
}
public static String getAPPVersionName(Context context, String packageName) {
String versionName = "0";
if (TextUtils.isEmpty(packageName)) {
return versionName;
}
PackageManager pm = context.getPackageManager();
try {
PackageInfo packageInfo = pm.getPackageInfo(packageName, 0);
versionName = packageInfo.versionName;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return versionName;
}
}

View File

@@ -0,0 +1,287 @@
package com.uiui.os.utils;
import android.annotation.SuppressLint;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;
import androidx.core.content.ContextCompat;
import com.arialyy.aria.core.Aria;
import com.blankj.utilcode.util.FileUtils;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.tencent.mmkv.MMKV;
import com.uiui.os.bean.AlarmClockData;
import com.uiui.os.service.MainService;
import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.Type;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
public class AlarmUtils {
@SuppressLint("StaticFieldLeak")
private static AlarmUtils sInstance;
private static String TAG = AlarmUtils.class.getSimpleName();
private Context mContext;
private AlarmManager alarmManager;
private MMKV mmkv = MMKV.defaultMMKV();
private AlarmUtils(Context context) {
this.mContext = context;
alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
}
public static void init(Context context) {
if (sInstance == null) {
sInstance = new AlarmUtils(context);
}
}
public static AlarmUtils getInstance() {
if (sInstance == null) {
throw new IllegalStateException("You must be init AmapManager first");
}
return sInstance;
}
private List<AlarmClockData> alarmClockDataList;
private HashSet<PendingIntent> pendingIntents;
public void setAlarmClockData(List<AlarmClockData> data) {
this.alarmClockDataList = data;
if (pendingIntents == null) {
pendingIntents = getOldPendingIntents();
}
for (PendingIntent pendingIntent : pendingIntents) {
alarmManager.cancel(pendingIntent);
}
List<AlarmClockData> newData = mergeData(data);
for (AlarmClockData clockData : newData) {
setAlarm(clockData);
}
String jsonString = new Gson().toJson(newData);
Log.e(TAG, "setAlarmClockData: " + jsonString);
mmkv.encode("AlarmClock", jsonString);
}
private List<AlarmClockData> mergeData(List<AlarmClockData> data) {
HashMap<Integer, AlarmClockData> oldData = getOldData();
List<AlarmClockData> tempData = new ArrayList<>();
for (AlarmClockData alarm : data) {
AlarmClockData oldAlarm = oldData.get(alarm.getId());
if (oldAlarm == null) {
tempData.add(alarm);
} else {
if (oldAlarm.equals(alarm)) {
tempData.add(oldAlarm);
} else {
tempData.add(alarm);
}
}
}
return tempData;
}
public void setAlarmString(List<AlarmClockData> alarmClockData) {
String jsonString = new Gson().toJson(alarmClockData);
Log.e(TAG, "setAlarmString: " + jsonString);
mmkv.encode("AlarmClock", jsonString);
}
public HashMap<Integer, AlarmClockData> getOldData() {
String jsonString = mmkv.decodeString("AlarmClock", "");
Log.e(TAG, "getOldPendingIntents: " + jsonString);
if (TextUtils.isEmpty(jsonString)) {
return new HashMap<>();
} else {
Type type = new TypeToken<List<AlarmClockData>>() {
}.getType();
Gson gson = new Gson();
List<AlarmClockData> data = gson.fromJson(jsonString, type);
HashMap hashMap = new HashMap();
for (AlarmClockData clockData : data) {
hashMap.put(clockData.getId(), clockData);
}
return hashMap;
}
}
private HashSet<PendingIntent> getOldPendingIntents() {
HashSet<PendingIntent> pendingIntents = new HashSet<>();
HashMap<Integer, AlarmClockData> data = getOldData();
for (AlarmClockData alarmClockData : data.values()) {
pendingIntents.add(getPendingIntent(alarmClockData));
}
return pendingIntents;
}
private PendingIntent getPendingIntent(AlarmClockData alarmClock) {
Intent intent = new Intent(MainService.ALARMWAKEUP);
intent.putExtra("title", alarmClock.getRemarks());
intent.putExtra("id", alarmClock.getId());
PendingIntent startPendingIntent = PendingIntent.getBroadcast(mContext, alarmClock.getId(), intent, PendingIntent.FLAG_CANCEL_CURRENT);
return startPendingIntent;
}
private long getTimestamp(String timeString) {
if (TextUtils.isEmpty(timeString)) {
return 0;
}
if (timeString.length() == 8) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
try {
Date date = simpleDateFormat.parse(timeString);
long timestamp = date.getTime() + getZeroTiemstamp();
return timestamp;
} catch (ParseException e) {
return 0;
}
} else {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
Date date = simpleDateFormat.parse(timeString);
long timestamp = date.getTime();
return timestamp;
} catch (ParseException e) {
return 0;
}
}
}
private long getZeroTiemstamp() {
long nowTime = System.currentTimeMillis();
long dayMillisecond = 60 * 60 * 24 * 1000;
long zeroTime = ((nowTime) / dayMillisecond) * dayMillisecond;
Log.e(TAG, "getZeroTiemstamp: " + zeroTime);
return zeroTime;
}
private static final int ONCE = 1;
private static final int LOOP = 2;
public void setAlarm(AlarmClockData alarm) {
int id = alarm.getId();
int type = alarm.getType();
String timeString = alarm.getTime();
long timestamp = getTimestamp(timeString);
String title = alarm.getRemarks();
boolean finished = alarm.isFinished();
String url = alarm.getVoice();
String md5 = alarm.getVoice_md5();
if (!TextUtils.isEmpty(url)) {
ariaDownload(url, md5);
}
if (type == ONCE) {
if (!finished) {
if (timestamp < System.currentTimeMillis()) {
Intent intent = new Intent(MainService.ALARMWAKEUP);
intent.putExtra("title", title);
intent.putExtra("id", id);
mContext.sendBroadcast(intent);
} else {
setOnceAlarm(MainService.ALARMWAKEUP, title, id, timestamp);
}
}
} else if (type == LOOP) {
setDayLoopAlarm(MainService.ALARMWAKEUP, title, id, timestamp);
}
}
/**
* @param action
* @param requestCode
* @param timestamp 设置一次性闹钟
*/
public void setOnceAlarm(String action, String extra, int requestCode, long timestamp) {
Intent intent = new Intent(action);
intent.putExtra("title", extra);
intent.putExtra("id", requestCode);
PendingIntent startPendingIntent = PendingIntent.getBroadcast(mContext, requestCode, intent, PendingIntent.FLAG_CANCEL_CURRENT);
pendingIntents.add(startPendingIntent);
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, timestamp, startPendingIntent);
Log.e(TAG, "setOnceAlarm: " + "id: " + requestCode + " title: " + extra + " timeString: " + timestamp);
}
/**
* @param action
* @param requestCode
* @param timestamp 设置循环周期为一天的闹钟
*/
public void setDayLoopAlarm(String action, String extra, int requestCode, long timestamp) {
setLoopAlarm(action, extra, requestCode, AlarmManager.INTERVAL_DAY, timestamp);
}
/**
* @param action
* @param requestCode
* @param timestamp 设置循环周期为一小时的闹钟
*/
public void setHourLoopAlarm(String action, String extra, int requestCode, long timestamp) {
setLoopAlarm(action, extra, requestCode, AlarmManager.INTERVAL_HOUR, timestamp);
}
/**
* @param action
* @param requestCode
* @param intervalMillis
* @param timestamp 循环闹钟
*/
public void setLoopAlarm(String action, String extra, int requestCode, long intervalMillis, long timestamp) {
Intent intent = new Intent(action);
intent.putExtra("title", extra);
intent.putExtra("id", requestCode);
PendingIntent startPendingIntent = PendingIntent.getBroadcast(mContext, requestCode, intent, PendingIntent.FLAG_CANCEL_CURRENT);
pendingIntents.add(startPendingIntent);
alarmManager.setWindow(AlarmManager.RTC_WAKEUP, timestamp, intervalMillis, startPendingIntent);
Log.e(TAG, "setLoopAlarm: " + "title: " + extra + " timeString: " + timestamp);
}
public void ariaDownload(String url, String md5) {
String fileName = Utils.getFileNamefromURL(url);
File file = new File(Utils.getDownLoadPath(mContext) + fileName);
if (file.exists() && !file.isDirectory()) {
String fileMD5 = FileUtils.getFileMD5ToString(file);
Log.e("ariaDownload", "fileOnlineMD5=" + md5);
Log.e("ariaDownload", "fileMD5=" + fileMD5);
if (!md5.equals(fileMD5)) {
Aria.download(this)
.load(url) //读取下载地址
.setFilePath(Utils.getDownLoadPath(mContext) + fileName)
// .ignoreFilePathOccupy()
.setExtendField(md5)
.create(); //启动下载}
} else {
Log.e("ariaDownload", "fileName = " + fileName + " exists");
}
} else {
Aria.download(this)
.load(url) //读取下载地址
.setFilePath(Utils.getDownLoadPath(mContext) + fileName)
// .ignoreFilePathOccupy()
.setExtendField(md5)
.create(); //启动下载}
}
}
}

View File

@@ -0,0 +1,103 @@
package com.uiui.os.utils;
import android.text.TextUtils;
import android.util.Log;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
public class CmdUtil {
private static final String TAG = "CmdUtil";
private static final String COMMAND_SH = "sh";
private static final String COMMAND_EXIT = "exit\n";
private static final String COMMAND_LINE_END = "\n";
/**
* 运行命令
*
* @param command 命令
* @return 结果
*/
public static Result execute(String command) {
Log.i(TAG, "execute() command = " + command);
Result result = new Result();
if (TextUtils.isEmpty(command)) {
Log.w(TAG, "WARNING: command should not be null or empty");
return result;
}
Process process = null;
DataOutputStream dos = null;
try {
process = Runtime.getRuntime().exec(COMMAND_SH);
dos = new DataOutputStream(process.getOutputStream());
dos.write(command.trim().getBytes());
dos.writeBytes(COMMAND_LINE_END);
dos.flush();
dos.writeBytes(COMMAND_EXIT);
dos.flush();
result.code = process.waitFor();
result.success = readBuffer(new BufferedReader(new InputStreamReader(process.getInputStream())));
result.error = readBuffer(new BufferedReader(new InputStreamReader(process.getErrorStream())));
Log.i(TAG, "result = " + result);
} catch (IOException ioe) {
ioe.printStackTrace();
Log.e(TAG, ioe.getMessage());
} catch (InterruptedException ie) {
ie.printStackTrace();
Log.e(TAG, ie.getMessage());
} finally {
try {
if (null != dos) {
dos.close();
}
} catch (IOException ioe) {
ioe.printStackTrace();
Log.e(TAG, ioe.getMessage());
}
if (null != process) {
process.destroy();
}
}
return result;
}
private static String readBuffer(BufferedReader bufferedReader) throws IOException {
StringBuilder sb = new StringBuilder();
String s;
while ((s = bufferedReader.readLine()) != null) {
sb.append(s);
}
return sb.toString();
}
/**
* Command执行结果
*/
public static final class Result {
public static final int SUCCESS = 0;
public static final int ERROR = -1;
public int code = ERROR;
public String error;
public String success;
@Override
public String toString() {
return "Result{" +
"code=" + code +
", error='" + error + '\'' +
", success='" + success + '\'' +
'}';
}
}
}

View File

@@ -0,0 +1,116 @@
package com.uiui.os.utils;
import android.app.ActivityManager;
import android.app.usage.UsageStats;
import android.app.usage.UsageStatsManager;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.provider.Settings;
import android.text.TextUtils;
import java.util.List;
public class ForegroundAppUtil {
private static final long END_TIME = System.currentTimeMillis();
private static final long TIME_INTERVAL = 7 * 24 * 60 * 60 * 1000L;
private static final long START_TIME = END_TIME - TIME_INTERVAL;
public static final String TOPAPP_KEY = "TOP_ALWAYS_SHOW_APP_NAME";
private static String TAG = ForegroundAppUtil.class.getSimpleName();
public static String getForegroundPackageName(Context context) {
//系统应用可以直接获取
ActivityManager mActivityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> runningTaskInfos = mActivityManager.getRunningTasks(1);
return runningTaskInfos.get(0).topActivity.getPackageName();
}
/**
* 获取栈顶的应用包名
*/
public static String getForegroundActivityName(Context context) {
String currentClassName = "";
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
ActivityManager manager = (ActivityManager) context.getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
currentClassName = manager.getRunningTasks(1).get(0).topActivity.getPackageName();
} else {
UsageStats initStat = getForegroundUsageStats(context, START_TIME, END_TIME);
if (initStat != null) {
currentClassName = initStat.getPackageName();
}
}
return currentClassName;
}
/**
* 判断当前应用是否在前台
*/
public static boolean isForegroundApp(Context context) {
return TextUtils.equals(getForegroundActivityName(context), context.getPackageName());
}
/**
* 获取时间段内,
*/
public static long getTotleForegroundTime(Context context) {
UsageStats usageStats = getCurrentUsageStats(context, START_TIME, END_TIME);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
return usageStats != null ? usageStats.getTotalTimeInForeground() : 0;
}
return 0;
}
/**
* 获取记录前台应用的UsageStats对象
*/
private static UsageStats getForegroundUsageStats(Context context, long startTime, long endTime) {
UsageStats usageStatsResult = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
List<UsageStats> usageStatses = getUsageStatsList(context, startTime, endTime);
if (usageStatses == null || usageStatses.isEmpty()) return null;
for (UsageStats usageStats : usageStatses) {
if (usageStatsResult == null || usageStatsResult.getLastTimeUsed() < usageStats.getLastTimeUsed()) {
usageStatsResult = usageStats;
}
}
}
return usageStatsResult;
}
/**
* 获取记录当前应用的UsageStats对象
*/
public static UsageStats getCurrentUsageStats(Context context, long startTime, long endTime) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
List<UsageStats> usageStatses = getUsageStatsList(context, startTime, endTime);
if (usageStatses == null || usageStatses.isEmpty()) return null;
for (UsageStats usageStats : usageStatses) {
if (TextUtils.equals(usageStats.getPackageName(), context.getPackageName())) {
return usageStats;
}
}
}
return null;
}
/**
* 通过UsageStatsManager获取List<UsageStats>集合
*/
public static List<UsageStats> getUsageStatsList(Context context, long startTime, long endTime) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
UsageStatsManager manager = (UsageStatsManager) context.getApplicationContext().getSystemService(Context.USAGE_STATS_SERVICE);
//UsageStatsManager.INTERVAL_WEEKLYUsageStatsManager的参数定义了5个具体查阅源码
List<UsageStats> usageStatses = manager.queryUsageStats(UsageStatsManager.INTERVAL_BEST, startTime, endTime);
if (usageStatses == null || usageStatses.size() == 0) {// 没有权限,获取不到数据
Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.getApplicationContext().startActivity(intent);
return null;
}
return usageStatses;
}
return null;
}
}

View File

@@ -0,0 +1,112 @@
package com.uiui.os.utils;
import android.annotation.SuppressLint;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD5Util {
public static String packetMD5(String str) {
MessageDigest messageDigest = null;
try {
messageDigest = MessageDigest.getInstance("MD5");
messageDigest.reset();
messageDigest.update(str.getBytes("UTF-8"));
} catch (NoSuchAlgorithmException e) {
System.out.println("NoSuchAlgorithmException caught!");
System.exit(-1);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
byte[] byteArray = messageDigest.digest();
StringBuffer md5StrBuff = new StringBuffer();
for (int i = 0; i < byteArray.length; i++) {
if (Integer.toHexString(0xFF & byteArray[i]).length() == 1)
md5StrBuff.append("0").append(
Integer.toHexString(0xFF & byteArray[i]));
else
md5StrBuff.append(Integer.toHexString(0xFF & byteArray[i]));
}
return md5StrBuff.toString();
}
@SuppressLint("DefaultLocale")
public static String getUpperMD5Str(String str) {
MessageDigest messageDigest = null;
try {
messageDigest = MessageDigest.getInstance("MD5");
messageDigest.reset();
messageDigest.update(str.getBytes("UTF-8"));
} catch (NoSuchAlgorithmException e) {
System.out.println("NoSuchAlgorithmException caught!");
System.exit(-1);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
byte[] byteArray = messageDigest.digest();
StringBuffer md5StrBuff = new StringBuffer();
for (int i = 0; i < byteArray.length; i++) {
if (Integer.toHexString(0xFF & byteArray[i]).length() == 1)
md5StrBuff.append("0").append(
Integer.toHexString(0xFF & byteArray[i]));
else
md5StrBuff.append(Integer.toHexString(0xFF & byteArray[i]));
}
return md5StrBuff.toString().toUpperCase();
}
/**
* 获取16位的MD5 值得
*
* @param str
* @return
*/
@SuppressLint("DefaultLocale")
public static String getUpperMD5Str16(String str) {
MessageDigest messageDigest = null;
try {
messageDigest = MessageDigest.getInstance("MD5");
messageDigest.reset();
messageDigest.update(str.getBytes("UTF-8"));
} catch (NoSuchAlgorithmException e) {
System.out.println("NoSuchAlgorithmException caught!");
System.exit(-1);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
byte[] byteArray = messageDigest.digest();
StringBuffer md5StrBuff = new StringBuffer();
for (int i = 0; i < byteArray.length; i++) {
if (Integer.toHexString(0xFF & byteArray[i]).length() == 1)
md5StrBuff.append("0").append(
Integer.toHexString(0xFF & byteArray[i]));
else
md5StrBuff.append(Integer.toHexString(0xFF & byteArray[i]));
}
return md5StrBuff.toString().toUpperCase().substring(8, 24);
}
}

View File

@@ -0,0 +1,93 @@
package com.uiui.os.utils;
import android.annotation.SuppressLint;
import android.content.Context;
import android.util.Log;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class TimeUtils {
@SuppressLint("StaticFieldLeak")
private static TimeUtils sInstance;
private Context mContext;
private SimpleDateFormat ruleSDF = new SimpleDateFormat("HH:mm:ss");
private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private String TAG = TimeUtils.class.getSimpleName();
private TimeUtils(Context context) {
this.mContext = context;
}
public static void init(Context context) {
if (sInstance == null) {
sInstance = new TimeUtils(context);
}
}
public static TimeUtils getInstance() {
if (sInstance == null) {
throw new IllegalStateException("You must be init TimeUtils first");
}
return sInstance;
}
private static String normalStartTime = "8:00:00";
private static String unusualStartTime = "22:00:00";
private String appPackageName;
private long endTime = 0;
private long startTime = 0;
public void setAppPackageName(String name) {
this.appPackageName = name;
}
public String getAppPackageName() {
return appPackageName;
}
public void setStartTime(long time) {
this.startTime = time;
}
public long getStartTime() {
return startTime;
}
public void setEndTime(long time) {
this.endTime = time;
}
public long getEndTime() {
return endTime;
}
private static final long DAY_TIME = 1000 * 60 * 60 * 24;
public boolean isNormalTime() {
long nowTime = System.currentTimeMillis();
String nowTimeString = ruleSDF.format(new Date(nowTime)); // 时间戳转换日期
try {
Date startDate = ruleSDF.parse(normalStartTime);
Date endDate = ruleSDF.parse(unusualStartTime);
Date now = ruleSDF.parse(nowTimeString);
Log.e(TAG, "isScreenshot: startDate = " + startDate);
Log.e(TAG, "isScreenshot: endDate = " + endDate);
Log.e(TAG, "isScreenshot: now = " + now);
if (startDate.getTime() <= now.getTime() && now.getTime() <= endDate.getTime()) {
return true;
} else if (endDate.getTime() < now.getTime() && now.getTime() <= startDate.getTime() + DAY_TIME) {
return false;
}
} catch (ParseException e) {
e.printStackTrace();
Log.e(TAG, "isScreenshot: " + e.getMessage());
}
return false;
}
}

View File

@@ -0,0 +1,93 @@
package com.uiui.os.utils;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Color;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;
import com.blankj.utilcode.util.ToastUtils;
import com.uiui.os.BuildConfig;
/**
* Created by haoge on 2017/3/2.
*/
public class ToastUtil {
private static final String TAG = ToastUtil.class.getSimpleName();
@SuppressLint("StaticFieldLeak")
private static Context mContext;
private static Handler mainHandler = new Handler(Looper.getMainLooper());
private static Toast debugToast;
private static Toast toast;
@SuppressLint("ShowToast")
public static void init(Context context) {
mContext = context;
toast = Toast.makeText(mContext, "", Toast.LENGTH_SHORT);
debugToast = Toast.makeText(mContext, "", Toast.LENGTH_SHORT);
}
private static long time1 = 0L;
private static long time2 = 0L;
public static void show(final String msg) {
ToastUtils.make()
// .setBgColor(ColorUtils.getColor(R.color.toast_color))
.setTextColor(Color.DKGRAY)
// .setGravity(Gravity.CENTER, 0, 0)
.setNotUseSystemToast()
.show(msg);
}
public static void betaShow(final String msg) {
if ( BuildConfig.DEBUG) {
ToastUtils.make()
// .setBgColor(ColorUtils.getColor(R.color.toast_color))
.setTextColor(Color.RED)
// .setGravity(Gravity.CENTER, 0, 0)
.setNotUseSystemToast()
.setDurationIsLong(true)
.show(msg);
} else {
Log.e(TAG, "debugShow: " + msg);
}
}
private static Toast mToast = null;
//android 8.0以后限制
//https://www.jianshu.com/p/d9813ad03d59
//https://www.jianshu.com/p/050ce052b873
public static void showToast(Context context, String text, int duration) {
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.P) {
Toast.makeText(context, text, duration).show();
} else {
if (mToast == null) {
mToast = Toast.makeText(context, text, duration);
} else {
mToast.setText(text);
mToast.setDuration(duration);
}
mToast.show();
}
}
// public static void showInCenter(String msg) {
// mainHandler.post(() -> {
// if (toast != null) {
// toast.setGravity(Gravity.CENTER, 0, 0);
// toast.setText(msg);
// toast.show();
// }
// });
// }
}

View File

@@ -1,13 +1,66 @@
package com.uiui.os.utils;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.BatteryManager;
import android.os.Build;
import android.os.Environment;
import android.util.Log;
import androidx.core.content.ContextCompat;
import com.uiui.os.BuildConfig;
import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.Method;
import java.math.BigInteger;
import java.security.MessageDigest;
public class Utils {
/**
* 获取设备序列号
*
* @return
*/
@SuppressLint("MissingPermission")
public static String getSerial() {
String serial = "unknow";
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {//9.0+
serial = Build.getSerial();
} else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N) {//8.0+
serial = Build.SERIAL;
} else {//8.0-
Class<?> c = Class.forName("android.os.SystemProperties");
Method get = c.getMethod("get", String.class);
serial = (String) get.invoke(c, "ro.serialno");
}
} catch (Exception e) {
e.printStackTrace();
Log.e("e", "读取设备序列号异常:" + e.toString());
}
if (BuildConfig.DEBUG) {
// return "QNG2DKB00463";
}
return serial;
}
public static String getDeviceSN() {
String serial = null;
try {
Class<?> c = Class.forName("android.os.SystemProperties");
Method get = c.getMethod("get", String.class);
serial = (String) get.invoke(c, "persist.sys.hrSerial");
} catch (Exception e) {
e.printStackTrace();
}
return serial;
}
/**
* 获取电量
*
@@ -23,4 +76,14 @@ public class Utils {
}
}
public static String getDownLoadPath(Context context) {
String path = ContextCompat.getExternalFilesDirs(context, Environment.DIRECTORY_DOWNLOADS)[0].getAbsolutePath();
return path + File.separator;
}
public static String getFileNamefromURL(String url) {
int position = url.lastIndexOf("/");
return url.substring(position + 1);
}
}

View File

@@ -66,6 +66,5 @@ public class CustomContent extends FrameLayout implements CustomContentCallbacks
@Override
public void onViewAdded(View child) {
super.onViewAdded(child);
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 内部颜色 -->
<solid
android:color="@color/yellow" />
<!-- 圆角的幅度 -->
<corners
android:topLeftRadius="8dp"
android:topRightRadius="8dp"
android:bottomLeftRadius="8dp"
android:bottomRightRadius="8dp" />
<padding
android:top="4dp"
android:bottom="4dp"
android:left="4dp"
android:right="4dp"
/>
</shape>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 内部颜色 -->
<solid android:color="@color/notice_blue" />
<!-- 圆角的幅度 -->
<corners
android:bottomLeftRadius="30dp"
android:bottomRightRadius="30dp"
android:topLeftRadius="30dp"
android:topRightRadius="30dp" />
<padding
android:bottom="4dp"
android:left="8dp"
android:right="8dp"
android:top="4dp" />
</shape>

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 内部颜色 -->
<solid android:color="@color/ok_button" />
<!-- 圆角的幅度 -->
<corners
android:bottomLeftRadius="100dp"
android:bottomRightRadius="100dp"
android:topLeftRadius="100dp"
android:topRightRadius="100dp" />
</shape>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 内部颜色 -->
<solid android:color="@color/white" />
<!-- 圆角的幅度 -->
<corners
android:bottomLeftRadius="30dp"
android:bottomRightRadius="30dp"
android:topLeftRadius="30dp"
android:topRightRadius="30dp" />
<padding
android:bottom="4dp"
android:left="8dp"
android:right="8dp"
android:top="4dp" />
</shape>

View File

@@ -5,7 +5,6 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -75,8 +74,6 @@
android:textStyle="bold"
app:layout_constraintStart_toStartOf="@+id/tv_temp"
app:layout_constraintTop_toBottomOf="@+id/tv_temp" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
@@ -93,23 +90,18 @@
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="我的图片"
android:text="爱心守护"
android:textColor="@color/black"
android:textSize="19sp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_content"
android:layout_width="0dp"
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/textView4"
app:layout_constraintTop_toBottomOf="@+id/textView4" />
</androidx.constraintlayout.widget.ConstraintLayout>
@@ -120,38 +112,29 @@
android:layout_weight="2"
android:background="@drawable/custom_background">
<com.king.view.circleprogressview.CircleProgressView
android:id="@+id/cpv"
android:layout_width="180dp"
android:layout_height="180dp"
android:layout_margin="20dp"
app:cpvDuration="1000"
app:cpvLabelTextSize="34sp"
app:cpvNormalColor="#D8D6D7"
app:cpvShowTick="false"
app:cpvStrokeWidth="30dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView2" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="一键加速"
android:text="紧急呼叫"
android:textColor="@color/black"
android:textSize="19sp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:layout_width="64dp"
android:layout_height="80dp"
android:adjustViewBounds="true"
android:scaleType="centerCrop"
android:src="@drawable/sos_icon"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
<LinearLayout
@@ -160,17 +143,17 @@
android:layout_weight="1"
android:orientation="horizontal">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_alarm"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_margin="8dp"
android:layout_weight="1"
android:background="@drawable/custom_background">
android:background="@drawable/custom_background"
tools:ignore="NestedWeights">
<TextView
android:id="@+id/textView7"
android:id="@+id/textView5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
@@ -182,17 +165,6 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_time"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:textColor="@color/black"
android:textSize="22sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:layout_editor_absoluteX="0dp" />
<TextView
android:id="@+id/tv_add"
android:layout_width="wrap_content"
@@ -207,25 +179,15 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_type"
android:layout_width="wrap_content"
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_clock"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="48dp"
android:layout_marginTop="20dp"
android:textColor="@color/black"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_time" />
<TextView
android:id="@+id/tv_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginEnd="48dp"
android:textColor="@color/black"
android:overScrollMode="never"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_time" />
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView5" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
@@ -250,33 +212,35 @@
<ImageView
android:id="@+id/iv_charging"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginTop="4dp"
android:layout_width="70dp"
android:layout_height="40dp"
android:adjustViewBounds="true"
android:scaleType="centerInside"
android:scaleType="centerCrop"
android:src="@drawable/charging"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@+id/tv_battery"
app:layout_constraintStart_toStartOf="@+id/tv_battery"
app:layout_constraintTop_toBottomOf="@+id/tv_battery" />
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_battery"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:gravity="center"
android:maxLines="1"
android:singleLine="true"
android:textColor="@color/black"
android:textSize="50sp"
android:textSize="24sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.497"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
app:layout_constraintTop_toBottomOf="@+id/iv_charging" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_wifi"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_margin="8dp"
@@ -284,11 +248,12 @@
android:background="@drawable/custom_background">
<TextView
android:id="@+id/textView9"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="快速扫码"
android:text="我的WiFi"
android:textColor="@color/black"
android:textSize="19sp"
android:textStyle="bold"
@@ -296,14 +261,28 @@
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:layout_width="64dp"
android:layout_height="64dp"
android:src="@drawable/scan_qrcode"
android:id="@+id/imageView3"
android:layout_width="60dp"
android:layout_height="50dp"
android:adjustViewBounds="true"
android:scaleType="centerCrop"
android:src="@drawable/wifi_icon"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/wifi_ssid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:textColor="@color/black"
android:textSize="24sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imageView3" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
@@ -313,31 +292,33 @@
android:layout_weight="1"
android:background="@drawable/custom_background">
<com.king.view.circleprogressview.CircleProgressView
android:id="@+id/cpv"
android:layout_width="140dp"
android:layout_height="140dp"
app:cpvDuration="1000"
app:cpvLabelTextSize="34sp"
app:cpvNormalColor="#D8D6D7"
app:cpvShowTick="false"
app:cpvStrokeWidth="20dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="我的文件"
android:text="一键加速"
android:textColor="@color/black"
android:textSize="19sp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="接收小程序传过来的文件"
android:textColor="@color/black"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
</LinearLayout>
</com.uiui.os.view.CustomContent>

View File

@@ -89,22 +89,18 @@
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="我的便签"
android:text="爱心守护"
android:textColor="@color/black"
android:textSize="19sp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_content"
android:layout_width="0dp"
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginEnd="16dp"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/textView4"
app:layout_constraintTop_toBottomOf="@+id/textView4" />
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
@@ -122,32 +118,28 @@
android:layout_weight="1"
android:background="@drawable/custom_background">
<com.king.view.circleprogressview.CircleProgressView
android:id="@+id/cpv"
android:layout_width="180dp"
android:layout_height="180dp"
android:layout_margin="8dp"
app:cpvDuration="1000"
app:cpvNormalColor="#D8D6D7"
app:cpvShowTick="false"
app:cpvStrokeWidth="28dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView6" />
<TextView
android:id="@+id/textView6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="一键加速"
android:text="紧急呼叫"
android:textColor="@color/black"
android:textSize="19sp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:layout_width="64dp"
android:layout_height="80dp"
android:adjustViewBounds="true"
android:scaleType="centerCrop"
android:src="@drawable/sos_icon"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
@@ -171,17 +163,6 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_time"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:textColor="@color/black"
android:textSize="22sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:layout_editor_absoluteX="0dp" />
<TextView
android:id="@+id/tv_add"
android:layout_width="wrap_content"
@@ -196,25 +177,15 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_type"
android:layout_width="wrap_content"
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_clock"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="64dp"
android:layout_marginTop="20dp"
android:textColor="@color/black"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_time" />
<TextView
android:id="@+id/tv_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginEnd="64dp"
android:textColor="@color/black"
android:overScrollMode="never"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_time" />
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView5" />
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
@@ -245,33 +216,35 @@
<ImageView
android:id="@+id/iv_charging"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginTop="4dp"
android:layout_width="70dp"
android:layout_height="40dp"
android:adjustViewBounds="true"
android:scaleType="centerInside"
android:src="@drawable/charging"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@+id/tv_battery"
app:layout_constraintStart_toStartOf="@+id/tv_battery"
app:layout_constraintTop_toBottomOf="@+id/tv_battery" />
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_battery"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:gravity="center"
android:maxLines="1"
android:singleLine="true"
android:textColor="@color/black"
android:textSize="50sp"
android:textSize="24sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.497"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
app:layout_constraintTop_toBottomOf="@+id/iv_charging" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_wifi"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_margin="8dp"
@@ -283,7 +256,7 @@
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="快速扫码"
android:text="我的WiFi"
android:textColor="@color/black"
android:textSize="19sp"
android:textStyle="bold"
@@ -291,14 +264,26 @@
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/imageView3"
android:layout_width="64dp"
android:layout_height="64dp"
android:src="@drawable/scan_qrcode"
android:src="@drawable/wifi_icon"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/wifi_ssid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:textColor="@color/black"
android:textSize="24sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imageView3" />
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
@@ -309,35 +294,40 @@
android:orientation="horizontal">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="0dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="8dp"
android:layout_weight="1"
android:background="@drawable/custom_background">
<com.king.view.circleprogressview.CircleProgressView
android:id="@+id/cpv"
android:layout_width="160dp"
android:layout_height="160dp"
android:layout_margin="8dp"
app:cpvDuration="1000"
app:cpvNormalColor="#D8D6D7"
app:cpvShowTick="false"
app:cpvStrokeWidth="28dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="我的文件"
android:text="一键加速"
android:textColor="@color/black"
android:textSize="19sp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="接收小程序传过来的文件"
android:textColor="@color/black"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
</LinearLayout>

View File

@@ -0,0 +1,68 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activity.NoticeActivity">
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="72dp"
android:text="测试标题"
android:textColor="@color/white"
android:textSize="50sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/constraintLayout"
android:layout_width="240dp"
android:layout_height="wrap_content"
android:layout_marginTop="108dp"
android:background="@drawable/notice_voice_background"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.497"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_title">
<TextView
android:id="@+id/textView8"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="30秒"
android:textSize="30sp"
android:textColor="@color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:layout_width="32dp"
android:layout_height="32dp"
android:src="@drawable/voice_white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<Button
android:id="@+id/bt_ok"
android:layout_width="100dp"
android:layout_height="100dp"
android:text="OK"
android:textSize="30sp"
android:textColor="@color/white"
android:layout_marginBottom="148dp"
android:background="@drawable/ok_background"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -20,6 +20,6 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/actions_item_drawablePaddding"
android:textColor="@color/White"
android:textColor="@color/white"
android:textSize="@dimen/actions_item_font" />
</LinearLayout>

View File

@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:background="@drawable/tv_background"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/tv_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="4dp"
android:gravity="center_horizontal"
android:text="time"
android:textColor="@color/white"
android:textSize="22sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/textView10"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView10"
android:layout_width="1dp"
android:layout_height="wrap_content"
android:layout_marginEnd="80dp"
android:background="@color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:text="tv_status"
android:textColor="@color/white"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@+id/textView10"
app:layout_constraintTop_toTopOf="parent"
/>
<TextView
android:id="@+id/tv_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:text="tv_type"
android:textColor="@color/white"
android:textSize="17sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@+id/tv_status"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.533" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="16dp"
android:background="@drawable/alarmclcok_background">
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:text="提醒事件"
android:textColor="@color/black"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="提醒时间"
android:textColor="@color/black"
app:layout_constraintStart_toStartOf="@+id/tv_title"
app:layout_constraintTop_toBottomOf="@+id/tv_title" />
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="180dp"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:background="@drawable/voice_background"
app:layout_constraintStart_toStartOf="@+id/tv_title"
app:layout_constraintTop_toBottomOf="@+id/tv_time">
<TextView
android:id="@+id/textView8"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="30秒"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:layout_width="16dp"
android:layout_height="16dp"
android:src="@drawable/voice"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -3,12 +3,14 @@
<color name="colorPrimary">#37353a</color>
<color name="colorPrimaryDark">#272727</color>
<color name="colorAccent">#454347</color>
<color name="White">#ffffff</color>
<color name="white">#ffffff</color>
<color name="transparent_white">#FFFFFF</color>
<color name="black">#000000</color>
<color name="white">#ffffff</color>
<color name="tv_add_color">#4880ff</color>
<color name="yellow">#F8B551</color>
<color name="notice_blue">#0480FF</color>
<color name="ok_button">#4D4B50</color>
</resources>

View File

@@ -10,4 +10,24 @@
<item name="android:fitsSystemWindows">true</item>
</style>
<style name="activity_styles" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- <item name="android:windowFullscreen">true</item>-->
<!--设置dialog的背景-->
<item name="android:windowBackground">@android:color/transparent</item>
<!--设置Dialog的windowFrame框为无-->
<item name="android:windowFrame">@null</item>
<!--设置无标题-->
<item name="windowNoTitle">true</item>
<!--是否浮现在activity之上-->
<item name="android:windowIsFloating">false</item>
<!--是否半透明-->
<!-- <item name="android:windowIsTranslucent">true</item>-->
<!--设置窗口内容不覆盖-->
<item name="android:windowContentOverlay">@null</item>
<!--设置动画在这里使用让它继承系统的Animation.Dialog-->
<item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
<!--背景是否模糊显示-->
<item name="android:backgroundDimEnabled">true</item>
</style>
</resources>

View File

@@ -1,2 +1,2 @@
rootProject.name='桌面OS'
rootProject.name='老人平板桌面'
include ':app'