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

@@ -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);
}
}