init
17
.gitignore
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
*.iml
|
||||||
|
.gradle
|
||||||
|
/local.properties
|
||||||
|
/.idea/caches
|
||||||
|
/.idea/libraries
|
||||||
|
/.idea/modules.xml
|
||||||
|
/.idea/workspace.xml
|
||||||
|
/.idea/navEditor.xml
|
||||||
|
/.idea/assetWizardSettings.xml
|
||||||
|
.DS_Store
|
||||||
|
/build
|
||||||
|
/captures
|
||||||
|
.externalNativeBuild
|
||||||
|
.cxx
|
||||||
|
/app/src/androidTest/java/com/uiui/os/
|
||||||
|
/app/src/test/java/com/uiui/os/
|
||||||
|
/.idea/
|
||||||
1
app/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/build
|
||||||
151
app/build.gradle
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
apply plugin: 'com.android.application'
|
||||||
|
|
||||||
|
def appName() {
|
||||||
|
return "学习系统"
|
||||||
|
}
|
||||||
|
|
||||||
|
def releaseTime() {
|
||||||
|
return new Date().format("yyyyMMddHHmmss", TimeZone.getDefault())
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileSdkVersion 29
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
applicationId "com.uiui.os"
|
||||||
|
minSdkVersion 24
|
||||||
|
targetSdkVersion 29
|
||||||
|
versionCode 1
|
||||||
|
versionName "1.0"
|
||||||
|
|
||||||
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
}
|
||||||
|
|
||||||
|
signingConfigs {
|
||||||
|
zhanRui {
|
||||||
|
storeFile file("src/doc/zhanxun.keystore")
|
||||||
|
storePassword "123456"
|
||||||
|
keyAlias "zhanxun"
|
||||||
|
keyPassword "123456"
|
||||||
|
v1SigningEnabled true
|
||||||
|
v2SigningEnabled true
|
||||||
|
}
|
||||||
|
debug {
|
||||||
|
storeFile file("src/doc/xueshibaoos.jks")
|
||||||
|
storePassword "123456"
|
||||||
|
keyAlias "xueshibaoos"
|
||||||
|
keyPassword "123456"
|
||||||
|
v2SigningEnabled false
|
||||||
|
}
|
||||||
|
release {// 签名文件
|
||||||
|
storeFile file("src/doc/xueshibaoos.jks")
|
||||||
|
storePassword "123456"
|
||||||
|
keyAlias "xueshibaoos"
|
||||||
|
keyPassword "123456"
|
||||||
|
v2SigningEnabled false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
zhanRuiRelease.initWith(release)
|
||||||
|
zhanRuiRelease {
|
||||||
|
manifestPlaceholders = [
|
||||||
|
AMAP_KEY: "70f37634f84b00c5c7347c545bc2a3b9"
|
||||||
|
]
|
||||||
|
buildConfigField "boolean", "LOG_DEBUG", "false"
|
||||||
|
signingConfig signingConfigs.zhanRui
|
||||||
|
}
|
||||||
|
|
||||||
|
zhanRuiDebug.initWith(debug)
|
||||||
|
zhanRuiDebug {
|
||||||
|
manifestPlaceholders = [
|
||||||
|
AMAP_KEY: "70f37634f84b00c5c7347c545bc2a3b9"
|
||||||
|
]
|
||||||
|
buildConfigField "boolean", "LOG_DEBUG", "true"
|
||||||
|
versionNameSuffix "-debug"
|
||||||
|
debuggable true
|
||||||
|
signingConfig signingConfigs.zhanRui
|
||||||
|
}
|
||||||
|
debug {
|
||||||
|
manifestPlaceholders = [
|
||||||
|
AMAP_KEY: "70f37634f84b00c5c7347c545bc2a3b9"
|
||||||
|
]
|
||||||
|
// 显示Log
|
||||||
|
buildConfigField "boolean", "LOG_DEBUG", "true"
|
||||||
|
versionNameSuffix "-debug"
|
||||||
|
minifyEnabled false
|
||||||
|
//Zipalign优化
|
||||||
|
zipAlignEnabled true
|
||||||
|
signingConfig signingConfigs.debug
|
||||||
|
applicationVariants.all { variant ->
|
||||||
|
variant.outputs.each { output ->
|
||||||
|
if (outputFile != null) {
|
||||||
|
def fileName = "${appName()}-V${defaultConfig.versionName}-${releaseTime()}.apk"
|
||||||
|
output.outputFileName = fileName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
release {
|
||||||
|
manifestPlaceholders = [
|
||||||
|
AMAP_KEY: "70f37634f84b00c5c7347c545bc2a3b9"
|
||||||
|
]
|
||||||
|
// 不显示Log
|
||||||
|
buildConfigField "boolean", "LOG_DEBUG", "false"
|
||||||
|
//混淆
|
||||||
|
minifyEnabled false
|
||||||
|
//Zipalign优化
|
||||||
|
zipAlignEnabled true
|
||||||
|
//前一部分代表系统默认的android程序的混淆文件,该文件已经包含了基本的混淆声明,后一个文件是自己的定义混淆文件
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||||
|
//签名
|
||||||
|
signingConfig signingConfigs.release
|
||||||
|
// 将release版本的包名重命名,加上版本及日期
|
||||||
|
applicationVariants.all { variant ->
|
||||||
|
variant.outputs.each { output ->
|
||||||
|
def outputFile = ""
|
||||||
|
if (outputFile != null) {
|
||||||
|
def fileName = "${appName()}-${variant.versionCode}-V${variant.versionName}-${releaseTime()}-${buildType.name}.apk"
|
||||||
|
output.outputFileName = new File(outputFile, fileName)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
|
implementation files('libs/QWeather_Public_Android_V4.6.jar')
|
||||||
|
|
||||||
|
implementation 'androidx.appcompat:appcompat:1.3.1'
|
||||||
|
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
|
||||||
|
implementation "androidx.recyclerview:recyclerview:1.2.1"
|
||||||
|
// For control over item selection of both touch and mouse driven selection
|
||||||
|
implementation "androidx.recyclerview:recyclerview-selection:1.1.0"
|
||||||
|
implementation "androidx.viewpager2:viewpager2:1.0.0"
|
||||||
|
// Java language implementation
|
||||||
|
implementation "androidx.fragment:fragment:1.3.6"
|
||||||
|
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||||
|
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'
|
||||||
|
//bindView
|
||||||
|
implementation 'com.jakewharton:butterknife:10.1.0'
|
||||||
|
annotationProcessor 'com.jakewharton:butterknife-compiler:10.1.0'
|
||||||
|
//高德地图定位
|
||||||
|
implementation 'com.amap.api:location:5.1.0'
|
||||||
|
//MMKV
|
||||||
|
implementation 'com.tencent:mmkv-static:1.2.10'
|
||||||
|
//状态栏透明
|
||||||
|
implementation 'com.gitee.zackratos:UltimateBarX:0.7.1'
|
||||||
|
//指示器
|
||||||
|
implementation 'com.github.hackware1993:MagicIndicator:1.7.0' // for androidx
|
||||||
|
implementation 'com.king.view:circleprogressview:1.1.2'
|
||||||
|
}
|
||||||
BIN
app/libs/QWeather_Public_Android_V4.6.jar
Normal file
21
app/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# Add project specific ProGuard rules here.
|
||||||
|
# You can control the set of applied configuration files using the
|
||||||
|
# proguardFiles setting in build.gradle.
|
||||||
|
#
|
||||||
|
# For more details, see
|
||||||
|
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||||
|
|
||||||
|
# If your project uses WebView with JS, uncomment the following
|
||||||
|
# and specify the fully qualified class name to the JavaScript interface
|
||||||
|
# class:
|
||||||
|
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||||
|
# public *;
|
||||||
|
#}
|
||||||
|
|
||||||
|
# Uncomment this to preserve the line number information for
|
||||||
|
# debugging stack traces.
|
||||||
|
#-keepattributes SourceFile,LineNumberTable
|
||||||
|
|
||||||
|
# If you keep the line number information, uncomment this to
|
||||||
|
# hide the original source file name.
|
||||||
|
#-renamesourcefileattribute SourceFile
|
||||||
BIN
app/src/doc/xueshibaoos.jks
Normal file
BIN
app/src/doc/zhanxun.keystore
Normal file
80
app/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="com.uiui.os"
|
||||||
|
android:sharedUserId="android.uid.system">
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.DELETE_PACKAGES" />
|
||||||
|
<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_EXTERNAL_STORAGE" />
|
||||||
|
|
||||||
|
<application
|
||||||
|
android:name=".base.BaseApplication"
|
||||||
|
android:allowBackup="true"
|
||||||
|
android:hardwareAccelerated="true"
|
||||||
|
android:icon="@mipmap/ic_launcher"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:largeHeap="true"
|
||||||
|
android:restoreAnyVersion="true"
|
||||||
|
android:supportsRtl="true"
|
||||||
|
android:theme="@style/AppTheme">
|
||||||
|
<activity
|
||||||
|
android:name=".activity.MainActivity"
|
||||||
|
android:clearTaskOnLaunch="true"
|
||||||
|
android:enabled="true"
|
||||||
|
android:excludeFromRecents="true"
|
||||||
|
android:launchMode="singleTask"
|
||||||
|
android:resizeableActivity="true"
|
||||||
|
android:resumeWhilePausing="true"
|
||||||
|
android:screenOrientation="unspecified"
|
||||||
|
android:stateNotNeeded="true"
|
||||||
|
android:taskAffinity="com.example.taskaffinity.newtask"
|
||||||
|
android:windowSoftInputMode="adjustPan">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
|
<category android:name="android.intent.category.HOME" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<category android:name="android.intent.category.MONKEY" />
|
||||||
|
<category android:name="android.intent.category.LAUNCHER_APP" />
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
|
||||||
|
<!-- 高德地图 -->
|
||||||
|
<!-- 设置key -->
|
||||||
|
<meta-data
|
||||||
|
android:name="com.amap.api.v2.apikey"
|
||||||
|
android:value="${AMAP_KEY}" />
|
||||||
|
<!-- 定位需要的服务 适配Android Q需要加上android:foregroundServiceType="location" -->
|
||||||
|
<service
|
||||||
|
android:name="com.amap.api.location.APSService"
|
||||||
|
android:foregroundServiceType="location" />
|
||||||
|
</application>
|
||||||
|
</manifest>
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
// IAlarmAidlInterface.aidl
|
||||||
|
package com.alarmclock.uiui;
|
||||||
|
|
||||||
|
// Declare any non-default types here with import statements
|
||||||
|
|
||||||
|
interface IAlarmAidlInterface {
|
||||||
|
/**
|
||||||
|
* Demonstrates some basic types that you can use as parameters
|
||||||
|
* and return values in AIDL.
|
||||||
|
*/
|
||||||
|
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
|
||||||
|
double aDouble, String aString);
|
||||||
|
String getAlarm();
|
||||||
|
}
|
||||||
9
app/src/main/java/com/uiui/os/AppInfo.java
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
package com.uiui.os;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class AppInfo implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -5488458740561098181L;
|
||||||
|
|
||||||
|
}
|
||||||
270
app/src/main/java/com/uiui/os/activity/MainActivity.java
Normal file
@@ -0,0 +1,270 @@
|
|||||||
|
package com.uiui.os.activity;
|
||||||
|
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.ComponentName;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
|
import android.content.ServiceConnection;
|
||||||
|
import android.content.pm.ApplicationInfo;
|
||||||
|
import android.content.res.Configuration;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.os.RemoteException;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.KeyEvent;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.fragment.app.FragmentManager;
|
||||||
|
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.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.view.ScaleCircleNavigator;
|
||||||
|
|
||||||
|
import net.lucode.hackware.magicindicator.MagicIndicator;
|
||||||
|
import net.lucode.hackware.magicindicator.ViewPagerHelper;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import butterknife.BindView;
|
||||||
|
import butterknife.ButterKnife;
|
||||||
|
|
||||||
|
public class MainActivity extends BaseActivity {
|
||||||
|
private String TAG = MainActivity.class.getSimpleName();
|
||||||
|
|
||||||
|
@BindView(R.id.viewPager)
|
||||||
|
ViewPager viewPager;
|
||||||
|
@BindView(R.id.magicIndicator)
|
||||||
|
MagicIndicator magicIndicator;
|
||||||
|
|
||||||
|
private FragmentManager fragmentManager;
|
||||||
|
private FragmentTransaction fragmentTransaction;
|
||||||
|
private BaseFragmentPagerAdapter adapter;
|
||||||
|
private List<Fragment> fragments;
|
||||||
|
private CustomFragment customFragment;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getLayoutId() {
|
||||||
|
return R.layout.activity_main;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initView() {
|
||||||
|
ButterKnife.bind(this);
|
||||||
|
fragmentManager = getSupportFragmentManager();
|
||||||
|
fragmentTransaction = fragmentManager.beginTransaction();
|
||||||
|
fragments = new ArrayList<>();
|
||||||
|
adapter = new BaseFragmentPagerAdapter(fragmentManager, fragments);
|
||||||
|
// fragmentTransaction.add(R.id.viewPager, appListFragment);
|
||||||
|
// fragmentTransaction.commit();
|
||||||
|
customFragment = new CustomFragment();
|
||||||
|
mAlarmServiceConnection = new ServiceConnection() {
|
||||||
|
@Override
|
||||||
|
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||||
|
Log.e(TAG, "onServiceConnected: ");
|
||||||
|
mIAlarmAidlInterface = IAlarmAidlInterface.Stub.asInterface(service);
|
||||||
|
getAlarmData();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onServiceDisconnected(ComponentName name) {
|
||||||
|
Log.e(TAG, "onServiceDisconnected: ");
|
||||||
|
mIAlarmAidlInterface = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
bindAlarmService();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getAlarmData() {
|
||||||
|
if (mIAlarmAidlInterface == null) {
|
||||||
|
bindAlarmService();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
String json = mIAlarmAidlInterface.getAlarm();
|
||||||
|
Log.e(TAG, "onServiceConnected: " + json);
|
||||||
|
if (json.equalsIgnoreCase("暂无闹钟")) {
|
||||||
|
customFragment.setAlarmItem(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Type type = new TypeToken<AlarmItem>() {
|
||||||
|
}.getType();
|
||||||
|
AlarmItem alarmItem = new Gson().fromJson(json, type);
|
||||||
|
customFragment.setAlarmItem(alarmItem);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ServiceConnection mAlarmServiceConnection;
|
||||||
|
private IAlarmAidlInterface mIAlarmAidlInterface;
|
||||||
|
|
||||||
|
private void bindAlarmService() {
|
||||||
|
if (mIAlarmAidlInterface == null) {
|
||||||
|
//这是连接aidl服务的代码
|
||||||
|
Intent intent = new Intent();
|
||||||
|
intent.setAction("com.alarmclock.uiui.IAlarmAidlInterface");
|
||||||
|
intent.setPackage("com.alarmclock.uiui");
|
||||||
|
intent.setComponent(new ComponentName("com.alarmclock.uiui", "com.alarmclock.uiui.AIDLAlarmService"));
|
||||||
|
bindService(intent, mAlarmServiceConnection, Context.BIND_AUTO_CREATE);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final static int APP_LIST_SIZE = 12;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initData() {
|
||||||
|
registmNewAppReceiver();
|
||||||
|
fragments.add(customFragment);
|
||||||
|
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) {
|
||||||
|
AppListFragment appListFragment = new AppListFragment();
|
||||||
|
appListFragment.setAppList(new ArrayList<>(applicationInfoList.subList(x, i)));
|
||||||
|
fragments.add(appListFragment);
|
||||||
|
x = i;
|
||||||
|
} else if (i == applicationInfoList.size()) {
|
||||||
|
AppListFragment appListFragment = new AppListFragment();
|
||||||
|
fragments.add(appListFragment);
|
||||||
|
appListFragment.setAppList(new ArrayList<>(applicationInfoList.subList(x, i)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
viewPager.setAdapter(adapter);
|
||||||
|
ScaleCircleNavigator scaleCircleNavigator = new ScaleCircleNavigator(this);
|
||||||
|
scaleCircleNavigator.setCircleCount(fragments.size());
|
||||||
|
scaleCircleNavigator.setNormalCircleColor(Color.DKGRAY);
|
||||||
|
scaleCircleNavigator.setSelectedCircleColor(Color.LTGRAY);
|
||||||
|
scaleCircleNavigator.setCircleClickListener(new ScaleCircleNavigator.OnCircleClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(int index) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
magicIndicator.setNavigator(scaleCircleNavigator);
|
||||||
|
ViewPagerHelper.bind(magicIndicator, viewPager);
|
||||||
|
if (fragments.size() > 1) {
|
||||||
|
viewPager.setCurrentItem(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addData() {
|
||||||
|
List<Fragment> fragmentList = new ArrayList<>();
|
||||||
|
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) {
|
||||||
|
AppListFragment appListFragment = new AppListFragment();
|
||||||
|
appListFragment.setAppList(new ArrayList<>(applicationInfoList.subList(x, i)));
|
||||||
|
fragmentList.add(appListFragment);
|
||||||
|
x = i;
|
||||||
|
} else if (i == applicationInfoList.size()) {
|
||||||
|
AppListFragment appListFragment = new AppListFragment();
|
||||||
|
fragmentList.add(appListFragment);
|
||||||
|
appListFragment.setAppList(new ArrayList<>(applicationInfoList.subList(x, i)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 1; i <= fragmentList.size(); i++) {
|
||||||
|
if (fragments.get(i) != null) {
|
||||||
|
adapter.replaceFragment(i, fragmentList.get(i - 1));
|
||||||
|
fragments.remove(i);
|
||||||
|
fragments.add(i, fragmentList.get(i - 1));
|
||||||
|
} else {
|
||||||
|
adapter.addFragment(fragmentList.get(i - 1));
|
||||||
|
fragments.add(fragmentList.get(i - 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||||
|
if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return super.onKeyDown(keyCode, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onNewIntent(Intent intent) {
|
||||||
|
super.onNewIntent(intent);
|
||||||
|
Log.e(TAG, "onNewIntent: " + intent.getAction());
|
||||||
|
String action = intent.getAction();
|
||||||
|
if (TextUtils.isEmpty(action)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (action) {
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
case Intent.ACTION_MAIN:
|
||||||
|
viewPager.setCurrentItem(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onConfigurationChanged(@NonNull Configuration newConfig) {
|
||||||
|
super.onConfigurationChanged(newConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
if (mNewAppReceiver != null) {
|
||||||
|
unregisterReceiver(mNewAppReceiver);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private NewAppReceiver mNewAppReceiver;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
getAlarmData();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void registmNewAppReceiver() {
|
||||||
|
mNewAppReceiver = new NewAppReceiver();
|
||||||
|
IntentFilter filter = new IntentFilter();
|
||||||
|
filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
|
||||||
|
filter.addAction(Intent.ACTION_PACKAGE_ADDED);
|
||||||
|
filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
|
||||||
|
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
|
||||||
|
filter.addDataScheme("package");
|
||||||
|
registerReceiver(mNewAppReceiver, filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
class NewAppReceiver extends BroadcastReceiver {
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
String action = intent.getAction();
|
||||||
|
Log.e(TAG, "onReceive: " + action);
|
||||||
|
addData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
55
app/src/main/java/com/uiui/os/base/BaseActivity.java
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
package com.uiui.os.base;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setBar() {
|
||||||
|
UltimateBarX.statusBar(this)
|
||||||
|
.transparent()
|
||||||
|
.colorRes(R.color.colorPrimaryDark)
|
||||||
|
// .light(true)
|
||||||
|
.apply();
|
||||||
|
UltimateBarX.navigationBar(this)
|
||||||
|
.transparent()
|
||||||
|
.colorRes(R.color.colorPrimaryDark)
|
||||||
|
// .light(true)
|
||||||
|
.apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置布局
|
||||||
|
*/
|
||||||
|
public abstract int getLayoutId();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化视图
|
||||||
|
*/
|
||||||
|
public abstract void initView();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化数据
|
||||||
|
*/
|
||||||
|
public abstract void initData();
|
||||||
|
}
|
||||||
70
app/src/main/java/com/uiui/os/base/BaseApplication.java
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
package com.uiui.os.base;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.app.Application;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.qweather.sdk.view.HeConfig;
|
||||||
|
import com.uiui.os.utils.AmapManager;
|
||||||
|
|
||||||
|
|
||||||
|
public class BaseApplication extends Application {
|
||||||
|
private static final String TAG = BaseApplication.class.getSimpleName();
|
||||||
|
|
||||||
|
@SuppressLint("StaticFieldLeak")
|
||||||
|
public static Context context;
|
||||||
|
@SuppressLint("StaticFieldLeak")
|
||||||
|
private static BaseApplication instance;
|
||||||
|
|
||||||
|
public static Context getAppContext() {
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 单例模式中获取唯一的ExitApplication实例
|
||||||
|
public static BaseApplication getInstance() {
|
||||||
|
if (null == instance) {
|
||||||
|
instance = new BaseApplication();
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate() {
|
||||||
|
super.onCreate();
|
||||||
|
context = this;
|
||||||
|
HeConfig.init("HE2111041506381545", "32b5ec69545e44119583a5e0ed4e87df");
|
||||||
|
AmapManager.init(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void catchException() {
|
||||||
|
Thread.setDefaultUncaughtExceptionHandler(
|
||||||
|
new Thread.UncaughtExceptionHandler() {
|
||||||
|
@Override
|
||||||
|
public void uncaughtException(Thread t, Throwable e) {
|
||||||
|
Log.e("捕获异常子线程:", Thread.currentThread().getName() +
|
||||||
|
"在:" + e.getStackTrace()[0].getClassName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
//下面是新增方法!
|
||||||
|
new Handler(Looper.getMainLooper()).post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
Looper.loop(); //会先执行这个方法,然后在执行下面的异常捕获方法!
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e("捕获异常主线程:", Thread.currentThread().getName() + "在:" + e.getStackTrace()[0].getClassName());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
21
app/src/main/java/com/uiui/os/bean/AlarmItem.java
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
package com.uiui.os.bean;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class AlarmItem implements Serializable {
|
||||||
|
private static final long serialVersionUID = -2760428066543837757L;
|
||||||
|
public String mTitle;
|
||||||
|
public String mTime;
|
||||||
|
public String mRepeatType;
|
||||||
|
public String mRepeatCode;
|
||||||
|
public boolean mActive;
|
||||||
|
|
||||||
|
public AlarmItem(String time, String repeatNormal, String repeatDefine, boolean active) {
|
||||||
|
// this.mTitle = title;
|
||||||
|
this.mTime = time;
|
||||||
|
this.mRepeatType = repeatNormal;
|
||||||
|
this.mRepeatCode = repeatDefine;
|
||||||
|
this.mActive = active;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
166
app/src/main/java/com/uiui/os/fragment/AppListFragment.java
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
package com.uiui.os.fragment;
|
||||||
|
|
||||||
|
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;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import com.uiui.os.R;
|
||||||
|
import com.uiui.os.utils.ApkUtils;
|
||||||
|
import com.uiui.os.utils.BitmapUtils;
|
||||||
|
import com.uiui.os.utils.IconUtils;
|
||||||
|
import com.uiui.os.view.MyGridLayout;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple {@link Fragment} subclass.
|
||||||
|
* Use the {@link AppListFragment#newInstance} factory method to
|
||||||
|
* create an instance of this fragment.
|
||||||
|
*/
|
||||||
|
public class AppListFragment extends Fragment {
|
||||||
|
// TODO: Rename parameter arguments, choose names that match
|
||||||
|
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
|
||||||
|
private static final String ARG_PARAM1 = "param1";
|
||||||
|
private static final String ARG_PARAM2 = "param2";
|
||||||
|
|
||||||
|
// TODO: Rename and change types of parameters
|
||||||
|
private String mParam1;
|
||||||
|
private String mParam2;
|
||||||
|
|
||||||
|
private ArrayList<ApplicationInfo> applicationInfos;
|
||||||
|
private MyGridLayout gridLayout;
|
||||||
|
private String TAG = AppListFragment.class.getSimpleName();
|
||||||
|
|
||||||
|
public AppListFragment() {
|
||||||
|
// Required empty public constructor
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this factory method to create a new instance of
|
||||||
|
* this fragment using the provided parameters.
|
||||||
|
*
|
||||||
|
* @param param1 Parameter 1.
|
||||||
|
* @param param2 Parameter 2.
|
||||||
|
* @return A new instance of fragment AppListFragment.
|
||||||
|
*/
|
||||||
|
// TODO: Rename and change types and number of parameters
|
||||||
|
public static AppListFragment newInstance(String param1, String param2) {
|
||||||
|
AppListFragment fragment = new AppListFragment();
|
||||||
|
Bundle args = new Bundle();
|
||||||
|
args.putString(ARG_PARAM1, param1);
|
||||||
|
args.putString(ARG_PARAM2, param2);
|
||||||
|
fragment.setArguments(args);
|
||||||
|
return fragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
if (savedInstanceState != null) {
|
||||||
|
applicationInfos = savedInstanceState.getParcelableArrayList("applicationInfos");
|
||||||
|
}
|
||||||
|
if (getArguments() != null) {
|
||||||
|
mParam1 = getArguments().getString(ARG_PARAM1);
|
||||||
|
mParam2 = getArguments().getString(ARG_PARAM2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private View rootView;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
// Inflate the layout for this fragment
|
||||||
|
rootView = inflater.inflate(R.layout.fragment_applist, container, false);
|
||||||
|
initView();
|
||||||
|
return rootView;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initView() {
|
||||||
|
if (applicationInfos.size() != 12) {
|
||||||
|
applicationInfos.addAll(new ArrayList<>(Arrays.asList(new ApplicationInfo[12 - applicationInfos.size()])));
|
||||||
|
}
|
||||||
|
gridLayout = rootView.findViewById(R.id.list);
|
||||||
|
if (getActivity().getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
||||||
|
gridLayout.set(4, 3);
|
||||||
|
} else {
|
||||||
|
gridLayout.set(3, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
gridLayout.setGridAdapter(new MyGridLayout.GridAdatper() {
|
||||||
|
@Override
|
||||||
|
public View getView(int index) {
|
||||||
|
PackageManager pm = rootView.getContext().getPackageManager();
|
||||||
|
View view = getLayoutInflater().inflate(R.layout.actions_item,
|
||||||
|
null);
|
||||||
|
ImageView iv = view.findViewById(R.id.iv);
|
||||||
|
TextView tv = view.findViewById(R.id.tv);
|
||||||
|
LinearLayout linearLayout = view.findViewById(R.id.btn_booktag);
|
||||||
|
ApplicationInfo applicationInfo = applicationInfos.get(index);
|
||||||
|
|
||||||
|
if (applicationInfo != null) {
|
||||||
|
Log.e(TAG, "getView: " + applicationInfo.packageName);
|
||||||
|
int i = IconUtils.appClassNameList.indexOf(applicationInfo.packageName);
|
||||||
|
if (i != -1) {
|
||||||
|
String val = IconUtils.appIconList.get(i);
|
||||||
|
int resID = getActivity().getResources().getIdentifier(val, "drawable", "com.uiui.os");
|
||||||
|
if (resID == 0) {
|
||||||
|
iv.setImageDrawable(applicationInfo.loadIcon(pm));
|
||||||
|
} else {
|
||||||
|
iv.setImageDrawable(getActivity().getResources().getDrawable(resID));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
iv.setImageBitmap(BitmapUtils.getIconBitmap(rootView.getContext(), applicationInfo.loadIcon(pm)));
|
||||||
|
}
|
||||||
|
tv.setText(applicationInfo.loadLabel(pm));
|
||||||
|
// linearLayout.setEnabled(true);
|
||||||
|
} else {
|
||||||
|
// linearLayout.setEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCount() {
|
||||||
|
// return applicationInfos == null ? 0 : applicationInfos.size();
|
||||||
|
return applicationInfos.size();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
gridLayout.setApplicationInfos(applicationInfos);
|
||||||
|
gridLayout.setOnItemClickListener(new MyGridLayout.OnItemClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onItemClick(View v, int index) {
|
||||||
|
ApplicationInfo applicationInfo = applicationInfos.get(index);
|
||||||
|
if (applicationInfo != null) {
|
||||||
|
ApkUtils.openPackage(v.getContext(), applicationInfo.packageName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAppList(ArrayList<ApplicationInfo> appList) {
|
||||||
|
this.applicationInfos = appList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSaveInstanceState(@NonNull Bundle outState) {
|
||||||
|
outState.putParcelableArrayList("applicationInfos", applicationInfos);
|
||||||
|
super.onSaveInstanceState(outState);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,204 @@
|
|||||||
|
package com.uiui.os.fragment;
|
||||||
|
|
||||||
|
import android.util.SparseArray;
|
||||||
|
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.fragment.app.FragmentManager;
|
||||||
|
import androidx.fragment.app.FragmentPagerAdapter;
|
||||||
|
import androidx.fragment.app.FragmentTransaction;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载显示Fragment的ViewPagerAdapter基类
|
||||||
|
* 提供可以刷新的方法
|
||||||
|
*
|
||||||
|
* @author Fly
|
||||||
|
* @e-mail 1285760616@qq.com
|
||||||
|
* @time 2018/3/22
|
||||||
|
*/
|
||||||
|
public class BaseFragmentPagerAdapter extends FragmentPagerAdapter {
|
||||||
|
private List<Fragment> mFragmentList;
|
||||||
|
private FragmentManager mFragmentManager;
|
||||||
|
/**下面两个值用来保存Fragment的位置信息,用以判断该位置是否需要更新*/
|
||||||
|
private SparseArray<String> mFragmentPositionMap;
|
||||||
|
private SparseArray<String> mFragmentPositionMapAfterUpdate;
|
||||||
|
|
||||||
|
public BaseFragmentPagerAdapter(FragmentManager fm, List<Fragment> fragments) {
|
||||||
|
super(fm);
|
||||||
|
mFragmentList = fragments;
|
||||||
|
mFragmentManager = fm;
|
||||||
|
mFragmentList = fragments;
|
||||||
|
mFragmentPositionMap = new SparseArray<>();
|
||||||
|
mFragmentPositionMapAfterUpdate = new SparseArray<>();
|
||||||
|
setFragmentPositionMap();
|
||||||
|
setFragmentPositionMapForUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存更新之前的位置信息,用<hashCode, position>的键值对结构来保存
|
||||||
|
*/
|
||||||
|
private void setFragmentPositionMap() {
|
||||||
|
mFragmentPositionMap.clear();
|
||||||
|
for (int i = 0; i < mFragmentList.size(); i++) {
|
||||||
|
mFragmentPositionMap.put(Long.valueOf(getItemId(i)).intValue(), String.valueOf(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存更新之后的位置信息,用<hashCode, position>的键值对结构来保存
|
||||||
|
*/
|
||||||
|
private void setFragmentPositionMapForUpdate() {
|
||||||
|
mFragmentPositionMapAfterUpdate.clear();
|
||||||
|
for (int i = 0; i < mFragmentList.size(); i++) {
|
||||||
|
mFragmentPositionMapAfterUpdate.put(Long.valueOf(getItemId(i)).intValue(), String.valueOf(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在此方法中找到需要更新的位置返回POSITION_NONE,否则返回POSITION_UNCHANGED即可
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int getItemPosition(Object object) {
|
||||||
|
int hashCode = object.hashCode();
|
||||||
|
//查找object在更新后的列表中的位置
|
||||||
|
String position = mFragmentPositionMapAfterUpdate.get(hashCode);
|
||||||
|
//更新后的列表中不存在该object的位置了
|
||||||
|
if (position == null) {
|
||||||
|
return POSITION_NONE;
|
||||||
|
} else {
|
||||||
|
//如果更新后的列表中存在该object的位置, 查找该object之前的位置并判断位置是否发生了变化
|
||||||
|
int size = mFragmentPositionMap.size();
|
||||||
|
for (int i = 0; i < size ; i++) {
|
||||||
|
int key = mFragmentPositionMap.keyAt(i);
|
||||||
|
if (key == hashCode) {
|
||||||
|
String index = mFragmentPositionMap.get(key);
|
||||||
|
if (position.equals(index)) {
|
||||||
|
//位置没变依然返回POSITION_UNCHANGED
|
||||||
|
return POSITION_UNCHANGED;
|
||||||
|
} else {
|
||||||
|
//位置变了
|
||||||
|
return POSITION_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return POSITION_UNCHANGED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将指定的Fragment替换/更新为新的Fragment
|
||||||
|
* @param oldFragment 旧Fragment
|
||||||
|
* @param newFragment 新Fragment
|
||||||
|
*/
|
||||||
|
public void replaceFragment(Fragment oldFragment, Fragment newFragment) {
|
||||||
|
int position = mFragmentList.indexOf(oldFragment);
|
||||||
|
if (position == -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//从Transaction移除旧的Fragment
|
||||||
|
removeFragmentInternal(oldFragment);
|
||||||
|
//替换List中对应的Fragment
|
||||||
|
mFragmentList.set(position, newFragment);
|
||||||
|
//刷新Adapter
|
||||||
|
notifyItemChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将指定位置的Fragment替换/更新为新的Fragment,同{@link #replaceFragment(Fragment oldFragment, Fragment newFragment)}
|
||||||
|
* @param position 旧Fragment的位置
|
||||||
|
* @param newFragment 新Fragment
|
||||||
|
*/
|
||||||
|
public void replaceFragment(int position, Fragment newFragment) {
|
||||||
|
Fragment oldFragment = mFragmentList.get(position);
|
||||||
|
removeFragmentInternal(oldFragment);
|
||||||
|
mFragmentList.set(position, newFragment);
|
||||||
|
notifyItemChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移除指定的Fragment
|
||||||
|
* @param fragment 目标Fragment
|
||||||
|
*/
|
||||||
|
public void removeFragment(Fragment fragment) {
|
||||||
|
//先从List中移除
|
||||||
|
mFragmentList.remove(fragment);
|
||||||
|
//然后从Transaction移除
|
||||||
|
removeFragmentInternal(fragment);
|
||||||
|
//最后刷新Adapter
|
||||||
|
notifyItemChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移除指定位置的Fragment,同 {@link #removeFragment(Fragment fragment)}
|
||||||
|
* @param position
|
||||||
|
*/
|
||||||
|
public void removeFragment(int position) {
|
||||||
|
Fragment fragment = mFragmentList.get(position);
|
||||||
|
//然后从List中移除
|
||||||
|
mFragmentList.remove(fragment);
|
||||||
|
//先从Transaction移除
|
||||||
|
removeFragmentInternal(fragment);
|
||||||
|
//最后刷新Adapter
|
||||||
|
notifyItemChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加Fragment
|
||||||
|
* @param fragment 目标Fragment
|
||||||
|
*/
|
||||||
|
public void addFragment(Fragment fragment) {
|
||||||
|
mFragmentList.add(fragment);
|
||||||
|
notifyItemChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在指定位置插入一个Fragment
|
||||||
|
* @param position 插入位置
|
||||||
|
* @param fragment 目标Fragment
|
||||||
|
*/
|
||||||
|
public void insertFragment(int position, Fragment fragment) {
|
||||||
|
mFragmentList.add(position, fragment);
|
||||||
|
notifyItemChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void notifyItemChanged() {
|
||||||
|
//刷新之前重新收集位置信息
|
||||||
|
setFragmentPositionMapForUpdate();
|
||||||
|
notifyDataSetChanged();
|
||||||
|
setFragmentPositionMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从Transaction移除Fragment
|
||||||
|
* @param fragment 目标Fragment
|
||||||
|
*/
|
||||||
|
private void removeFragmentInternal(Fragment fragment) {
|
||||||
|
FragmentTransaction transaction = mFragmentManager.beginTransaction();
|
||||||
|
transaction.remove(fragment);
|
||||||
|
transaction.commitNow();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 此方法不用position做返回值即可破解fragment tag异常的错误
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public long getItemId(int position) {
|
||||||
|
// 获取当前数据的hashCode,其实这里不用hashCode用自定义的可以关联当前Item对象的唯一值也可以,只要不是直接返回position
|
||||||
|
return mFragmentList.get(position).hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Fragment getItem(int position) {
|
||||||
|
return mFragmentList.get(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCount() {
|
||||||
|
return mFragmentList.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Fragment> getFragments() {
|
||||||
|
return mFragmentList;
|
||||||
|
}
|
||||||
|
}
|
||||||
343
app/src/main/java/com/uiui/os/fragment/CustomFragment.java
Normal file
@@ -0,0 +1,343 @@
|
|||||||
|
package com.uiui.os.fragment;
|
||||||
|
|
||||||
|
import android.app.ActivityManager;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
|
import android.os.BatteryManager;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
|
import android.os.SystemClock;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
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.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.uiui.os.BuildConfig;
|
||||||
|
import com.uiui.os.R;
|
||||||
|
import com.uiui.os.bean.AlarmItem;
|
||||||
|
import com.uiui.os.utils.AmapManager;
|
||||||
|
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.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 {
|
||||||
|
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};
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: Rename parameter arguments, choose names that match
|
||||||
|
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
|
||||||
|
private static final String ARG_PARAM1 = "param1";
|
||||||
|
private static final String ARG_PARAM2 = "param2";
|
||||||
|
|
||||||
|
// TODO: Rename and change types of parameters
|
||||||
|
private String mParam1;
|
||||||
|
private String mParam2;
|
||||||
|
|
||||||
|
private View rootView;
|
||||||
|
private AlarmItem alarmItem;
|
||||||
|
|
||||||
|
public CustomFragment() {
|
||||||
|
// Required empty public constructor
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this factory method to create a new instance of
|
||||||
|
* this fragment using the provided parameters.
|
||||||
|
*
|
||||||
|
* @param param1 Parameter 1.
|
||||||
|
* @param param2 Parameter 2.
|
||||||
|
* @return A new instance of fragment CustomFragment.
|
||||||
|
*/
|
||||||
|
// TODO: Rename and change types and number of parameters
|
||||||
|
public static CustomFragment newInstance(String param1, String param2) {
|
||||||
|
CustomFragment fragment = new CustomFragment();
|
||||||
|
Bundle args = new Bundle();
|
||||||
|
args.putString(ARG_PARAM1, param1);
|
||||||
|
args.putString(ARG_PARAM2, param2);
|
||||||
|
fragment.setArguments(args);
|
||||||
|
return fragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAlarmItem(AlarmItem item) {
|
||||||
|
this.alarmItem = item;
|
||||||
|
setAlarm();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
if (getArguments() != null) {
|
||||||
|
mParam1 = getArguments().getString(ARG_PARAM1);
|
||||||
|
mParam2 = getArguments().getString(ARG_PARAM2);
|
||||||
|
}
|
||||||
|
registerBatteryReceiver();
|
||||||
|
getActivity().registerReceiver(mbatteryReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void registerBatteryReceiver() {
|
||||||
|
if (null == batteryReceiver) {
|
||||||
|
batteryReceiver = new BatteryReceiver();
|
||||||
|
}
|
||||||
|
IntentFilter filter = new IntentFilter();
|
||||||
|
filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
|
||||||
|
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
|
||||||
|
filter.addAction(Intent.ACTION_BATTERY_LOW);
|
||||||
|
filter.addAction(Intent.ACTION_BATTERY_OKAY);
|
||||||
|
filter.addAction(Intent.ACTION_POWER_CONNECTED);
|
||||||
|
filter.addAction(Intent.ACTION_POWER_DISCONNECTED);
|
||||||
|
getActivity().registerReceiver(batteryReceiver, filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
BatteryReceiver batteryReceiver;
|
||||||
|
|
||||||
|
private class BatteryReceiver extends BroadcastReceiver {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
String action = intent.getAction();
|
||||||
|
if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
|
||||||
|
// 当前电量
|
||||||
|
int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
|
||||||
|
// 最大电量
|
||||||
|
int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, 0);
|
||||||
|
int elec = (level * 100) / scale;
|
||||||
|
Log.e(TAG, "electricity:=" + elec + "%");
|
||||||
|
tv_battery.setText(elec + "%");
|
||||||
|
} else if (Intent.ACTION_POWER_CONNECTED.equals(action)
|
||||||
|
|| Intent.ACTION_POWER_DISCONNECTED.equals(action)
|
||||||
|
|| Intent.ACTION_BATTERY_LOW.equals(action)
|
||||||
|
|| Intent.ACTION_BATTERY_OKAY.equals(action)
|
||||||
|
) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private BroadcastReceiver mbatteryReceiver = new BroadcastReceiver() {
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
String action = intent.getAction();
|
||||||
|
Log.e(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 {
|
||||||
|
if (rootView != null) {
|
||||||
|
iv_charging.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
|
Bundle savedInstanceState) {
|
||||||
|
// Inflate the layout for this fragment
|
||||||
|
rootView = inflater.inflate(R.layout.fragment_custom, container, false);
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
iv_charging = rootView.findViewById(R.id.iv_charging);
|
||||||
|
setAlarm();
|
||||||
|
refreshMemory();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setAlarm() {
|
||||||
|
if (rootView == null) return;
|
||||||
|
if (alarmItem == null) {
|
||||||
|
tv_time.setText("暂无闹钟");
|
||||||
|
tv_time.setVisibility(View.GONE);
|
||||||
|
tv_add.setVisibility(View.VISIBLE);
|
||||||
|
tv_type.setVisibility(View.GONE);
|
||||||
|
tv_status.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("关闭");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initData() {
|
||||||
|
initAmap();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initAmap() {
|
||||||
|
AMapLocationClient aMapLocationClient = AmapManager.getInstance().getLocationClient();
|
||||||
|
aMapLocationClient.stopLocation();
|
||||||
|
aMapLocationClient.startLocation();
|
||||||
|
aMapLocationClient.setLocationListener(new AMapLocationListener() {
|
||||||
|
@Override
|
||||||
|
public void onLocationChanged(AMapLocation aMapLocation) {
|
||||||
|
Log.e(TAG, "onLocationChanged: " + aMapLocation);
|
||||||
|
if (aMapLocation.getErrorCode() == 0) {
|
||||||
|
String city = aMapLocation.getCity();
|
||||||
|
getweather(aMapLocation.getLongitude(), aMapLocation.getLatitude());
|
||||||
|
tv_location.setText(city);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getweather(double longitude, double latitude) {
|
||||||
|
/**
|
||||||
|
* 实况天气数据
|
||||||
|
* @param location 所查询的地区,可通过该地区名称、ID、IP和经纬度进行查询经纬度格式:经度,纬度
|
||||||
|
* (英文,分隔,十进制格式,北纬东经为正,南纬西经为负)
|
||||||
|
* @param lang (选填)多语言,可以不使用该参数,默认为简体中文
|
||||||
|
* @param unit (选填)单位选择,公制(m)或英制(i),默认为公制单位
|
||||||
|
* @param listener 网络访问结果回调
|
||||||
|
*/
|
||||||
|
|
||||||
|
QWeather.getWeatherNow(getActivity(), "" + longitude + "," + latitude, Lang.ZH_HANS, Unit.METRIC, new QWeather.OnResultWeatherNowListener() {
|
||||||
|
@Override
|
||||||
|
public void onError(Throwable e) {
|
||||||
|
Log.e(TAG, "getWeather onError: " + e);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSuccess(WeatherNowBean 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();
|
||||||
|
String imageName = "he" + now.getIcon();
|
||||||
|
// int resId = getResources().getIdentifier(imageName, "drawable", getActivity().getPackageName());
|
||||||
|
// iv_pic.setImageDrawable(getActivity().getDrawable(resId));
|
||||||
|
tv_temp.setText(now.getTemp() + "℃");
|
||||||
|
} else {
|
||||||
|
//在此查看返回数据失败的原因
|
||||||
|
Code code = weatherBean.getCode();
|
||||||
|
Log.e(TAG, "failed code: " + code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void killBackgroundApp() {
|
||||||
|
List<String> pkgList = ApkUtils.queryFilterAppList(getActivity());
|
||||||
|
for (String pkg : pkgList) {
|
||||||
|
if (pkg.equalsIgnoreCase(BuildConfig.APPLICATION_ID)) continue;
|
||||||
|
killBackgroundProcesses(pkg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void killBackgroundProcesses(String packageName) {
|
||||||
|
ActivityManager activityManager;
|
||||||
|
try {
|
||||||
|
activityManager = (ActivityManager)
|
||||||
|
getActivity().getSystemService(Context.ACTIVITY_SERVICE);
|
||||||
|
activityManager.killBackgroundProcesses(packageName);
|
||||||
|
Method forceStopPackage = activityManager.getClass()
|
||||||
|
.getDeclaredMethod("forceStopPackage", String.class);
|
||||||
|
// Log.e(TAG, "killBackgroundProcesses: " + packageName);
|
||||||
|
forceStopPackage.setAccessible(true);
|
||||||
|
forceStopPackage.invoke(activityManager, packageName);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "killBackgroundProcesses: " + e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
refreshMemory();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void refreshMemory() {
|
||||||
|
long avail = AppUtil.getAvailMemory(getActivity());
|
||||||
|
long total = AppUtil.getTotalMemory(getActivity());
|
||||||
|
int x = (int) (((total - avail) / (double) total) * 100);
|
||||||
|
cpv.setProgressColor(mShaderColors);
|
||||||
|
cpv.showAnimation(0, x, 1000);
|
||||||
|
float x2 = (((total - avail) / (float) total));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
if (batteryReceiver != null) {
|
||||||
|
getActivity().unregisterReceiver(batteryReceiver);
|
||||||
|
}
|
||||||
|
if (mbatteryReceiver != null) {
|
||||||
|
getActivity().unregisterReceiver(mbatteryReceiver);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
78
app/src/main/java/com/uiui/os/utils/AmapManager.java
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
package com.uiui.os.utils;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.amap.api.location.AMapLocation;
|
||||||
|
import com.amap.api.location.AMapLocationClient;
|
||||||
|
import com.amap.api.location.AMapLocationClientOption;
|
||||||
|
import com.amap.api.location.AMapLocationListener;
|
||||||
|
|
||||||
|
public class AmapManager {
|
||||||
|
private static AmapManager sInstance;
|
||||||
|
private Context mContext;
|
||||||
|
public static AMapLocationClient locationClient = null;
|
||||||
|
private String TAG = AmapManager.class.getSimpleName();
|
||||||
|
|
||||||
|
private AmapManager(Context context) {
|
||||||
|
this.mContext = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void init(Context context) {
|
||||||
|
if (sInstance == null) {
|
||||||
|
sInstance = new AmapManager(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AmapManager getInstance() {
|
||||||
|
if (sInstance == null) {
|
||||||
|
throw new IllegalStateException("You must be init AmapManager first");
|
||||||
|
}
|
||||||
|
|
||||||
|
return sInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AMapLocationClient getLocationClient() {
|
||||||
|
if (null == locationClient) {
|
||||||
|
initAmap();
|
||||||
|
}
|
||||||
|
return locationClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initAmap() {
|
||||||
|
locationClient = new AMapLocationClient(mContext);
|
||||||
|
AMapLocationClientOption option = new AMapLocationClientOption();
|
||||||
|
option.setLocationPurpose(AMapLocationClientOption.AMapLocationPurpose.SignIn);
|
||||||
|
option.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
|
||||||
|
option.setNeedAddress(true);
|
||||||
|
//获取一次定位结果:
|
||||||
|
//该方法默认为false。
|
||||||
|
option.setOnceLocation(true);
|
||||||
|
//获取最近3s内精度最高的一次定位结果:
|
||||||
|
//设置setOnceLocationLatest(boolean b)接口为true,启动定位时SDK会返回最近3s内精度最高的一次定位结果。
|
||||||
|
// 如果设置其为true,setOnceLocation(boolean b)接口也会被设置为true,反之不会,默认为false。
|
||||||
|
option.setOnceLocationLatest(true);
|
||||||
|
locationClient.setLocationOption(option);
|
||||||
|
//设置定位模式为AMapLocationMode.Hight_Accuracy,高精度模式。
|
||||||
|
//设置定位监听
|
||||||
|
locationClient.setLocationListener(new AMapLocationListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLocationChanged(AMapLocation aMapLocation) {
|
||||||
|
//errCode等于0代表定位成功,其他的为定位失败,具体的可以参照官网定位错误码说明
|
||||||
|
if (aMapLocation.getErrorCode() == 0) {
|
||||||
|
Log.e(TAG, "onLocationChanged: " + "定位成功");
|
||||||
|
Log.e(TAG, "onLocationChanged: " + aMapLocation.getAddress());
|
||||||
|
} else {
|
||||||
|
//定位失败
|
||||||
|
Log.e(TAG, "onLocationChanged: " + "定位失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
//设置场景模式后最好调用一次stop,再调用start以保证场景模式生效
|
||||||
|
locationClient.stopLocation();
|
||||||
|
locationClient.startLocation();
|
||||||
|
Log.e(TAG, "initAmap: " + "startLocation");
|
||||||
|
}
|
||||||
|
}
|
||||||
141
app/src/main/java/com/uiui/os/utils/ApkUtils.java
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
package com.uiui.os.utils;
|
||||||
|
|
||||||
|
import android.content.ComponentName;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.pm.ApplicationInfo;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.content.pm.ResolveInfo;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.uiui.os.BuildConfig;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class ApkUtils {
|
||||||
|
private static String[] excludePackageName = {BuildConfig.APPLICATION_ID};
|
||||||
|
|
||||||
|
|
||||||
|
public static ArrayList<ApplicationInfo> queryFilterAppInfo(Context context) {
|
||||||
|
PackageManager pm = context.getPackageManager();
|
||||||
|
// 查询所有已经安装的应用程序
|
||||||
|
List<ApplicationInfo> appInfos = pm.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES);// GET_UNINSTALLED_PACKAGES代表已删除,但还有安装目录的
|
||||||
|
ArrayList<ApplicationInfo> applicationInfos = new ArrayList<>();
|
||||||
|
|
||||||
|
// 创建一个类别为CATEGORY_LAUNCHER的该包名的Intent
|
||||||
|
Intent resolveIntent = new Intent(Intent.ACTION_MAIN, null);
|
||||||
|
resolveIntent.addCategory(Intent.CATEGORY_LAUNCHER);
|
||||||
|
|
||||||
|
// 通过getPackageManager()的queryIntentActivities方法遍历,得到所有能打开的app的packageName
|
||||||
|
List<ResolveInfo> resolveinfoList = pm.queryIntentActivities(resolveIntent, 0);
|
||||||
|
Set<String> allowPackages = new HashSet();
|
||||||
|
for (ResolveInfo resolveInfo : resolveinfoList) {
|
||||||
|
allowPackages.add(resolveInfo.activityInfo.packageName);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ApplicationInfo app : appInfos) {
|
||||||
|
// if((app.flags & ApplicationInfo.FLAG_SYSTEM) <= 0)//通过flag排除系统应用,会将电话、短信也排除掉
|
||||||
|
// {
|
||||||
|
// applicationInfos.add(app);
|
||||||
|
// }
|
||||||
|
// if(app.uid > 10000){//通过uid排除系统应用,在一些手机上效果不好
|
||||||
|
// applicationInfos.add(app);
|
||||||
|
// }
|
||||||
|
if (allowPackages.contains(app.packageName) && !Arrays.asList(excludePackageName).contains(app.packageName)) {
|
||||||
|
// if (allowPackages.contains(app.packageName)) {
|
||||||
|
applicationInfos.add(app);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return applicationInfos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取第三方应用
|
||||||
|
* @param context
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static List<String> queryFilterAppList(Context context) {
|
||||||
|
PackageManager pm = context.getPackageManager();
|
||||||
|
// 查询所有已经安装的应用程序
|
||||||
|
List<ApplicationInfo> appInfos = pm.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES);// GET_UNINSTALLED_PACKAGES代表已删除,但还有安装目录的
|
||||||
|
List<String> applicationInfos = new ArrayList<>();
|
||||||
|
for (ApplicationInfo app : appInfos) {
|
||||||
|
// Log.e("queryFilterAppInfo", String.valueOf(app.flags));
|
||||||
|
// Log.e("queryFilterAppInfo", String.valueOf((app.flags & mask)));
|
||||||
|
if ((app.flags & ApplicationInfo.FLAG_SYSTEM) == 1) {
|
||||||
|
//通过flag排除系统应用,会将电话、短信也排除掉
|
||||||
|
} else {
|
||||||
|
applicationInfos.add(app.packageName);
|
||||||
|
Log.e("queryFilterAppInfo", app.packageName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return applicationInfos;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void openApp(Context context, String packageName) {
|
||||||
|
Intent intent = context.getPackageManager().getLaunchIntentForPackage(packageName);
|
||||||
|
if (intent != null) {
|
||||||
|
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
context.startActivity(intent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
List<ResolveInfo> list = pkgMag.queryIntentActivities(intent,
|
||||||
|
PackageManager.GET_ACTIVITIES);
|
||||||
|
for (int i = 0; i < list.size(); i++) {
|
||||||
|
ResolveInfo info = list.get(i);
|
||||||
|
if (info.activityInfo.packageName.equals(packageName)) {
|
||||||
|
mainAct = info.activityInfo.name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (TextUtils.isEmpty(mainAct)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
intent.setComponent(new ComponentName(packageName, mainAct));
|
||||||
|
return intent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Context getPackageContext(Context context, String packageName) {
|
||||||
|
Context pkgContext = null;
|
||||||
|
if (context.getPackageName().equals(packageName)) {
|
||||||
|
pkgContext = context;
|
||||||
|
} else {
|
||||||
|
// 创建第三方应用的上下文环境
|
||||||
|
try {
|
||||||
|
pkgContext = context.createPackageContext(packageName,
|
||||||
|
Context.CONTEXT_IGNORE_SECURITY
|
||||||
|
| Context.CONTEXT_INCLUDE_CODE);
|
||||||
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pkgContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean openPackage(Context context, String packageName) {
|
||||||
|
Context pkgContext = getPackageContext(context, packageName);
|
||||||
|
Intent intent = getAppOpenIntentByPackageName(context, packageName);
|
||||||
|
if (pkgContext != null && intent != null) {
|
||||||
|
pkgContext.startActivity(intent);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
91
app/src/main/java/com/uiui/os/utils/AppUtil.java
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2012 www.amsoft.cn
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.uiui.os.utils;
|
||||||
|
|
||||||
|
|
||||||
|
import android.app.ActivityManager;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.FileReader;
|
||||||
|
|
||||||
|
public class AppUtil {
|
||||||
|
|
||||||
|
private static String TAG = AppUtil.class.getSimpleName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 描述:获取可用内存.
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static long getAvailMemory(Context context) {
|
||||||
|
// 获取android当前可用内存大小
|
||||||
|
ActivityManager activityManager = (ActivityManager) context
|
||||||
|
.getSystemService(Context.ACTIVITY_SERVICE);
|
||||||
|
ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
|
||||||
|
activityManager.getMemoryInfo(memoryInfo);
|
||||||
|
// 当前系统可用内存 ,将获得的内存大小规格化
|
||||||
|
|
||||||
|
return memoryInfo.availMem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param context
|
||||||
|
* @return 可用的内存大小
|
||||||
|
*/
|
||||||
|
public static long getFreeMemory(Context context) {
|
||||||
|
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
|
||||||
|
ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
|
||||||
|
activityManager.getMemoryInfo(memoryInfo);
|
||||||
|
long freeMem = memoryInfo.totalMem - memoryInfo.availMem;
|
||||||
|
// Log.e("getHardware", "getFreeMemory: " + freeMem);
|
||||||
|
return freeMem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 描述:总内存.
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static long getTotalMemory(Context context) {
|
||||||
|
// 系统内存信息文件
|
||||||
|
String file = "/proc/meminfo";
|
||||||
|
String memInfo;
|
||||||
|
String[] strs;
|
||||||
|
long memory = 0;
|
||||||
|
|
||||||
|
try {
|
||||||
|
FileReader fileReader = new FileReader(file);
|
||||||
|
BufferedReader bufferedReader = new BufferedReader(fileReader, 8192);
|
||||||
|
// 读取meminfo第一行,系统内存大小
|
||||||
|
memInfo = bufferedReader.readLine();
|
||||||
|
strs = memInfo.split("\\s+");
|
||||||
|
for (String str : strs) {
|
||||||
|
Log.e(TAG, "getTotalMemory: " + str + "\t");
|
||||||
|
}
|
||||||
|
// 获得系统总内存,单位KB
|
||||||
|
memory = Integer.valueOf(strs[1]).intValue();
|
||||||
|
bufferedReader.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
// Byte转位KB或MB
|
||||||
|
return memory * 1024;
|
||||||
|
}
|
||||||
|
}
|
||||||
72
app/src/main/java/com/uiui/os/utils/BitmapUtils.java
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
package com.uiui.os.utils;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.PixelFormat;
|
||||||
|
import android.graphics.drawable.AdaptiveIconDrawable;
|
||||||
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.os.Build;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
|
||||||
|
public class BitmapUtils {
|
||||||
|
public static Bitmap Bytes2Bimap(byte[] b) {
|
||||||
|
if (b.length != 0) {
|
||||||
|
return BitmapFactory.decodeByteArray(b, 0, b.length);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] Bitmap2Bytes(Bitmap bitmap) {
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
|
||||||
|
byte[] data = baos.toByteArray();
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Drawable转换成一个Bitmap
|
||||||
|
*
|
||||||
|
* @param drawable drawable对象
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static final Bitmap drawableToBitmap(Drawable drawable) {
|
||||||
|
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(),
|
||||||
|
drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565);
|
||||||
|
Canvas canvas = new Canvas(bitmap);
|
||||||
|
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
|
||||||
|
drawable.draw(canvas);
|
||||||
|
return bitmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static Bitmap drawableToBitamp(Drawable drawable) {
|
||||||
|
Bitmap bitmap;
|
||||||
|
BitmapDrawable bd = (BitmapDrawable) drawable;
|
||||||
|
bitmap = bd.getBitmap();
|
||||||
|
return bitmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bitmap getIconBitmap(Context context, Drawable drawable) {
|
||||||
|
try {
|
||||||
|
if (drawable == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && drawable instanceof AdaptiveIconDrawable) {
|
||||||
|
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
|
||||||
|
Canvas canvas = new Canvas(bitmap);
|
||||||
|
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
|
||||||
|
drawable.draw(canvas);
|
||||||
|
return bitmap;
|
||||||
|
} else {
|
||||||
|
return ((BitmapDrawable) drawable).getBitmap();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
61
app/src/main/java/com/uiui/os/utils/IconUtils.java
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
package com.uiui.os.utils;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class IconUtils {
|
||||||
|
public static List<String> appClassNameList = new ArrayList<String>() {
|
||||||
|
{
|
||||||
|
this.add("com.android.appstore");//应用市场
|
||||||
|
this.add("com.android.browser");//浏览器
|
||||||
|
this.add("com.android.calculator2");//计算器
|
||||||
|
this.add("com.android.calendar");//日历
|
||||||
|
this.add("com.android.camera");//相机
|
||||||
|
this.add("com.android.camera2");//相机
|
||||||
|
this.add("com.android.contacts");//通讯录
|
||||||
|
this.add("com.android.deskclock");//时钟
|
||||||
|
this.add("com.android.dialer");//电话
|
||||||
|
this.add("com.android.dialer");//电话
|
||||||
|
this.add("com.android.gallery3d");//图库
|
||||||
|
this.add("com.android.mms.ui");//信息
|
||||||
|
this.add("com.android.music");//音乐
|
||||||
|
this.add("com.android.providers.downloads.ui");//下载
|
||||||
|
this.add("com.android.quicksearchbox");//搜索
|
||||||
|
this.add("com.android.settings");//设置
|
||||||
|
this.add("com.android.soundrecorder");//录音机
|
||||||
|
this.add("com.android.stk.StkMain");//sim卡
|
||||||
|
this.add("com.android.vdieo");//视频
|
||||||
|
this.add("com.mediatek.filemanager");//文件管理
|
||||||
|
this.add("com.android.documentsui");//下载
|
||||||
|
this.add("com.mediatek.fmradio");//收音机
|
||||||
|
this.add("com.android.fmradio");//收音机
|
||||||
|
this.add("com.android.email");//电子邮件
|
||||||
|
}
|
||||||
|
};
|
||||||
|
public static List<String> appIconList = new ArrayList<String>() {{
|
||||||
|
this.add("com_android_appstore");
|
||||||
|
this.add("com_android_browser");
|
||||||
|
this.add("com_android_calculator2");
|
||||||
|
this.add("com_android_calendar");
|
||||||
|
this.add("com_android_camera");
|
||||||
|
this.add("com_android_camera");
|
||||||
|
this.add("com_android_contacts");
|
||||||
|
this.add("com_android_deskclock");
|
||||||
|
this.add("com_android_dialer");
|
||||||
|
this.add("com_android_dialer");
|
||||||
|
this.add("com_android_gallery3d_app");
|
||||||
|
this.add("com_android_mms_ui");
|
||||||
|
this.add("com_android_music");
|
||||||
|
this.add("com_android_providers_downloads_ui");
|
||||||
|
this.add("com_android_quicksearchbox");
|
||||||
|
this.add("com_android_settings");
|
||||||
|
this.add("com_android_soundrecorder");
|
||||||
|
this.add("com_android_stk_stkmain");
|
||||||
|
this.add("com_android_vdieo");
|
||||||
|
this.add("com_mediatek_filemanager");
|
||||||
|
this.add("com_mediatek_filemanager");
|
||||||
|
this.add("com_mediatek_fmradio");
|
||||||
|
this.add("com_mediatek_fmradio");//收音机
|
||||||
|
this.add("com_android_email");
|
||||||
|
}};
|
||||||
|
}
|
||||||
26
app/src/main/java/com/uiui/os/utils/Utils.java
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package com.uiui.os.utils;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.ContextWrapper;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
|
import android.os.BatteryManager;
|
||||||
|
import android.os.Build;
|
||||||
|
|
||||||
|
public class Utils {
|
||||||
|
/**
|
||||||
|
* 获取电量
|
||||||
|
*
|
||||||
|
* @param mContext
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
synchronized public static int getBatteryLevel(Context mContext) {
|
||||||
|
if (Build.VERSION.SDK_INT >= 21) {
|
||||||
|
return ((BatteryManager) mContext.getSystemService(Context.BATTERY_SERVICE)).getIntProperty(4);
|
||||||
|
} else {
|
||||||
|
Intent intent = (new ContextWrapper(mContext)).registerReceiver(null, new IntentFilter("android.intent.action.BATTERY_CHANGED"));
|
||||||
|
return intent.getIntExtra("level", -1) * 100 / intent.getIntExtra("scale", -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
71
app/src/main/java/com/uiui/os/view/CustomContent.java
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
package com.uiui.os.view;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.FrameLayout;
|
||||||
|
|
||||||
|
import androidx.annotation.AttrRes;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
|
||||||
|
public class CustomContent extends FrameLayout implements CustomContentCallbacks {
|
||||||
|
|
||||||
|
public CustomContent(@NonNull Context context) {
|
||||||
|
super(context);
|
||||||
|
init(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CustomContent(@NonNull Context context, @Nullable AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
init(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CustomContent(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {
|
||||||
|
super(context, attrs, defStyleAttr);
|
||||||
|
init(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init(Context context){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onFinishInflate() {
|
||||||
|
super.onFinishInflate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onShow(boolean fromResume) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onHide() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onScrollProgressChanged(float progress) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 滑到负一屏是否再允许滑动,true:允许滑动到主屏,false:不允许再滑动
|
||||||
|
@Override
|
||||||
|
public boolean isScrollingAllowed() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onTouchEvent(MotionEvent event) {
|
||||||
|
return super.onTouchEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onViewAdded(View child) {
|
||||||
|
super.onViewAdded(child);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package com.uiui.os.view;
|
||||||
|
|
||||||
|
|
||||||
|
// add by codemx.cn ---- 20190712 ---plus- start
|
||||||
|
// modify by codemx.cn ---- 20190712 ---plus- start
|
||||||
|
public interface CustomContentCallbacks {
|
||||||
|
|
||||||
|
// Custom content is completely shown. {@code fromResume} indicates whether this was caused
|
||||||
|
// by a onResume or by scrolling otherwise.
|
||||||
|
void onShow(boolean fromResume);
|
||||||
|
|
||||||
|
// Custom content is completely hidden
|
||||||
|
void onHide();
|
||||||
|
|
||||||
|
// Custom content scroll progress changed. From 0 (not showing) to 1 (fully showing).
|
||||||
|
void onScrollProgressChanged(float progress);
|
||||||
|
|
||||||
|
// Indicates whether the user is allowed to scroll away from the custom content.
|
||||||
|
boolean isScrollingAllowed();
|
||||||
|
|
||||||
|
}
|
||||||
176
app/src/main/java/com/uiui/os/view/MyGridLayout.java
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
package com.uiui.os.view;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.pm.ApplicationInfo;
|
||||||
|
import android.content.res.TypedArray;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
|
||||||
|
import com.uiui.os.R;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import static android.view.View.MeasureSpec.EXACTLY;
|
||||||
|
import static android.view.View.MeasureSpec.makeMeasureSpec;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义布局组件
|
||||||
|
*
|
||||||
|
* @author zihao
|
||||||
|
*/
|
||||||
|
public class MyGridLayout extends ViewGroup {
|
||||||
|
int margin = 2;// 每个格子的水平和垂直间隔
|
||||||
|
int colums = 4;//列数
|
||||||
|
int rows = 3;//行数
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
private GridAdatper adapter;
|
||||||
|
private String TAG = MyGridLayout.class.getSimpleName();
|
||||||
|
|
||||||
|
@SuppressLint("Recycle")
|
||||||
|
public MyGridLayout(Context context, AttributeSet attrs, int defStyle) {
|
||||||
|
super(context, attrs, defStyle);
|
||||||
|
if (attrs != null) {
|
||||||
|
TypedArray a = getContext().obtainStyledAttributes(attrs,
|
||||||
|
R.styleable.MyGridLayout);
|
||||||
|
margin = a.getInteger(R.styleable.MyGridLayout_itemMargin, 2);
|
||||||
|
colums = a.getInteger(R.styleable.MyGridLayout_numColumns, 4);
|
||||||
|
rows = a.getInteger(R.styleable.MyGridLayout_numRows, 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public MyGridLayout(Context context, AttributeSet attrs) {
|
||||||
|
this(context, attrs, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MyGridLayout(Context context) {
|
||||||
|
this(context, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColums(int c) {
|
||||||
|
this.colums = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRows(int r) {
|
||||||
|
this.rows = r;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(int c, int r) {
|
||||||
|
this.colums = c;
|
||||||
|
this.rows = r;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||||
|
count = getChildCount();
|
||||||
|
if (count == 0) {
|
||||||
|
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
final View child = getChildAt(i);
|
||||||
|
if (child.getVisibility() == GONE) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
child.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
|
||||||
|
}
|
||||||
|
|
||||||
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
||||||
|
int height = b - t;// 布局区域高度
|
||||||
|
int width = r - l;// 布局区域宽度
|
||||||
|
// int rows = count % colums == 0 ? count / colums : count / colums + 1;// 行数
|
||||||
|
if (count == 0)
|
||||||
|
return;
|
||||||
|
int gridW = (width - margin * (colums + 1)) / colums;// 格子宽度
|
||||||
|
int gridH = (height - margin * (rows + 1)) / rows;// 格子高度
|
||||||
|
|
||||||
|
int left;
|
||||||
|
int top = margin + margin / 2;
|
||||||
|
|
||||||
|
for (int i = 0; i < rows; i++) {// 遍历行
|
||||||
|
for (int j = 0; j < colums; j++) {// 遍历每一行的元素
|
||||||
|
View child = this.getChildAt(i * colums + j);
|
||||||
|
if (child == null)
|
||||||
|
return;
|
||||||
|
// if (j == 0) {
|
||||||
|
left = j * gridW + (j + 1) * margin + margin / 2;
|
||||||
|
// } else {
|
||||||
|
// left = j * gridW + (j + 1) * margin;
|
||||||
|
// }
|
||||||
|
// 如果当前布局宽度和测量宽度不一样,就直接用当前布局的宽度重新测量
|
||||||
|
if (gridW != child.getMeasuredWidth()
|
||||||
|
|| gridH != child.getMeasuredHeight()) {
|
||||||
|
child.measure(makeMeasureSpec(gridW, EXACTLY),
|
||||||
|
makeMeasureSpec(gridH, EXACTLY));
|
||||||
|
}
|
||||||
|
child.layout(left, top, left + gridW, top + gridH);
|
||||||
|
// Log.e(TAG, "onLayout: left = " + left);
|
||||||
|
// Log.e(TAG, "onLayout: top = " + top);
|
||||||
|
// Log.e(TAG, "onLayout: right = " + left + gridW);
|
||||||
|
// Log.e(TAG, "onLayout: bottom = " + top + gridH);
|
||||||
|
}
|
||||||
|
top += gridH + margin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface GridAdatper {
|
||||||
|
View getView(int index);
|
||||||
|
|
||||||
|
int getCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置适配器
|
||||||
|
*/
|
||||||
|
public void setGridAdapter(GridAdatper adapter) {
|
||||||
|
this.adapter = adapter;
|
||||||
|
// 动态添加视图
|
||||||
|
int size = adapter.getCount();
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
addView(adapter.getView(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface OnItemClickListener {
|
||||||
|
void onItemClick(View v, int index);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ArrayList<ApplicationInfo> applicationInfos;
|
||||||
|
|
||||||
|
public void setApplicationInfos(ArrayList<ApplicationInfo> infoArrayList) {
|
||||||
|
this.applicationInfos = infoArrayList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置item点击事件
|
||||||
|
*
|
||||||
|
* @param click
|
||||||
|
*/
|
||||||
|
public void setOnItemClickListener(final OnItemClickListener click) {
|
||||||
|
if (this.adapter == null)
|
||||||
|
return;
|
||||||
|
for (int i = 0; i < adapter.getCount(); i++) {
|
||||||
|
final int index = i;
|
||||||
|
View view = getChildAt(i);
|
||||||
|
view.setOnClickListener(new View.OnClickListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
click.onItemClick(v, index);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (applicationInfos.get(index) == null) {
|
||||||
|
view.setClickable(false);
|
||||||
|
} else view.setClickable(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
323
app/src/main/java/com/uiui/os/view/ScaleCircleNavigator.java
Normal file
@@ -0,0 +1,323 @@
|
|||||||
|
package com.uiui.os.view;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.PointF;
|
||||||
|
import android.util.SparseArray;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewConfiguration;
|
||||||
|
import android.view.animation.Interpolator;
|
||||||
|
import android.view.animation.LinearInterpolator;
|
||||||
|
|
||||||
|
import net.lucode.hackware.magicindicator.NavigatorHelper;
|
||||||
|
import net.lucode.hackware.magicindicator.abs.IPagerNavigator;
|
||||||
|
import net.lucode.hackware.magicindicator.buildins.ArgbEvaluatorHolder;
|
||||||
|
import net.lucode.hackware.magicindicator.buildins.UIUtil;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
// _oo0oo_
|
||||||
|
// o8888888o
|
||||||
|
// 88" . "88
|
||||||
|
// (| -_- |)
|
||||||
|
// 0\ = /0
|
||||||
|
// ___/`---'\___
|
||||||
|
// .' \\| |// '.
|
||||||
|
// / \\||| : |||// \
|
||||||
|
// / _||||| -:- |||||- \
|
||||||
|
// | | \\\ - /// | |
|
||||||
|
// | \_| ''\---/'' |_/ |
|
||||||
|
// \ .-\__ '-' ___/-. /
|
||||||
|
// ___'. .' /--.--\ `. .'___
|
||||||
|
// ."" '< `.___\_<|>_/___.' >' "".
|
||||||
|
// | | : `- \`.;`\ _ /`;.`/ - ` : | |
|
||||||
|
// \ \ `_. \_ __\ /__ _/ .-` / /
|
||||||
|
// =====`-.____`.___ \_____/___.-`___.-'=====
|
||||||
|
// `=---='
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// 佛祖保佑 永无BUG
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类似CircleIndicator的效果
|
||||||
|
* Created by hackware on 2016/9/3.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class ScaleCircleNavigator extends View implements IPagerNavigator, NavigatorHelper.OnNavigatorScrollListener {
|
||||||
|
private int mMinRadius;
|
||||||
|
private int mMaxRadius;
|
||||||
|
private int mNormalCircleColor = Color.LTGRAY;
|
||||||
|
private int mSelectedCircleColor = Color.GRAY;
|
||||||
|
private int mCircleSpacing;
|
||||||
|
private int mCircleCount;
|
||||||
|
|
||||||
|
private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||||
|
private List<PointF> mCirclePoints = new ArrayList<PointF>();
|
||||||
|
private SparseArray<Float> mCircleRadiusArray = new SparseArray<Float>();
|
||||||
|
|
||||||
|
// 事件回调
|
||||||
|
private boolean mTouchable;
|
||||||
|
private ScaleCircleNavigator.OnCircleClickListener mCircleClickListener;
|
||||||
|
private float mDownX;
|
||||||
|
private float mDownY;
|
||||||
|
private int mTouchSlop;
|
||||||
|
|
||||||
|
private boolean mFollowTouch = true; // 是否跟随手指滑动
|
||||||
|
private NavigatorHelper mNavigatorHelper = new NavigatorHelper();
|
||||||
|
private Interpolator mStartInterpolator = new LinearInterpolator();
|
||||||
|
|
||||||
|
public ScaleCircleNavigator(Context context) {
|
||||||
|
super(context);
|
||||||
|
init(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init(Context context) {
|
||||||
|
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
|
||||||
|
mMinRadius = UIUtil.dip2px(context, 3);
|
||||||
|
mMaxRadius = UIUtil.dip2px(context, 4);
|
||||||
|
mCircleSpacing = UIUtil.dip2px(context, 8);
|
||||||
|
mNavigatorHelper.setNavigatorScrollListener(this);
|
||||||
|
mNavigatorHelper.setSkimOver(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||||
|
setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
|
||||||
|
}
|
||||||
|
|
||||||
|
private int measureWidth(int widthMeasureSpec) {
|
||||||
|
int mode = MeasureSpec.getMode(widthMeasureSpec);
|
||||||
|
int width = MeasureSpec.getSize(widthMeasureSpec);
|
||||||
|
int result = 0;
|
||||||
|
switch (mode) {
|
||||||
|
case MeasureSpec.EXACTLY:
|
||||||
|
result = width;
|
||||||
|
break;
|
||||||
|
case MeasureSpec.AT_MOST:
|
||||||
|
case MeasureSpec.UNSPECIFIED:
|
||||||
|
if (mCircleCount <= 0) {
|
||||||
|
result = getPaddingLeft() + getPaddingRight();
|
||||||
|
} else {
|
||||||
|
result = (mCircleCount - 1) * mMinRadius * 2 + mMaxRadius * 2 + (mCircleCount - 1) * mCircleSpacing + getPaddingLeft() + getPaddingRight();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int measureHeight(int heightMeasureSpec) {
|
||||||
|
int mode = MeasureSpec.getMode(heightMeasureSpec);
|
||||||
|
int height = MeasureSpec.getSize(heightMeasureSpec);
|
||||||
|
int result = 0;
|
||||||
|
switch (mode) {
|
||||||
|
case MeasureSpec.EXACTLY:
|
||||||
|
result = height;
|
||||||
|
break;
|
||||||
|
case MeasureSpec.AT_MOST:
|
||||||
|
case MeasureSpec.UNSPECIFIED:
|
||||||
|
result = mMaxRadius * 2 + getPaddingTop() + getPaddingBottom();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDraw(Canvas canvas) {
|
||||||
|
for (int i = 0, j = mCirclePoints.size(); i < j; i++) {
|
||||||
|
PointF point = mCirclePoints.get(i);
|
||||||
|
float radius = mCircleRadiusArray.get(i, (float) mMinRadius);
|
||||||
|
mPaint.setColor(ArgbEvaluatorHolder.eval((radius - mMinRadius) / (mMaxRadius - mMinRadius), mNormalCircleColor, mSelectedCircleColor));
|
||||||
|
canvas.drawCircle(point.x, getHeight() / 2.0f, radius, mPaint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void prepareCirclePoints() {
|
||||||
|
mCirclePoints.clear();
|
||||||
|
if (mCircleCount > 0) {
|
||||||
|
int y = Math.round(getHeight() / 2.0f);
|
||||||
|
int centerSpacing = mMinRadius * 2 + mCircleSpacing;
|
||||||
|
int startX = mMaxRadius + getPaddingLeft();
|
||||||
|
for (int i = 0; i < mCircleCount; i++) {
|
||||||
|
PointF pointF = new PointF(startX, y);
|
||||||
|
mCirclePoints.add(pointF);
|
||||||
|
startX += centerSpacing;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onTouchEvent(MotionEvent event) {
|
||||||
|
float x = event.getX();
|
||||||
|
float y = event.getY();
|
||||||
|
switch (event.getAction()) {
|
||||||
|
case MotionEvent.ACTION_DOWN:
|
||||||
|
if (mTouchable) {
|
||||||
|
mDownX = x;
|
||||||
|
mDownY = y;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MotionEvent.ACTION_UP:
|
||||||
|
if (mCircleClickListener != null) {
|
||||||
|
if (Math.abs(x - mDownX) <= mTouchSlop && Math.abs(y - mDownY) <= mTouchSlop) {
|
||||||
|
float max = Float.MAX_VALUE;
|
||||||
|
int index = 0;
|
||||||
|
for (int i = 0; i < mCirclePoints.size(); i++) {
|
||||||
|
PointF pointF = mCirclePoints.get(i);
|
||||||
|
float offset = Math.abs(pointF.x - x);
|
||||||
|
if (offset < max) {
|
||||||
|
max = offset;
|
||||||
|
index = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mCircleClickListener.onClick(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return super.onTouchEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
||||||
|
mNavigatorHelper.onPageScrolled(position, positionOffset, positionOffsetPixels);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPageSelected(int position) {
|
||||||
|
mNavigatorHelper.onPageSelected(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPageScrollStateChanged(int state) {
|
||||||
|
mNavigatorHelper.onPageScrollStateChanged(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||||
|
prepareCirclePoints();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void notifyDataSetChanged() {
|
||||||
|
prepareCirclePoints();
|
||||||
|
requestLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAttachToMagicIndicator() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDetachFromMagicIndicator() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMinRadius(int minRadius) {
|
||||||
|
mMinRadius = minRadius;
|
||||||
|
prepareCirclePoints();
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxRadius(int maxRadius) {
|
||||||
|
mMaxRadius = maxRadius;
|
||||||
|
prepareCirclePoints();
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNormalCircleColor(int normalCircleColor) {
|
||||||
|
mNormalCircleColor = normalCircleColor;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSelectedCircleColor(int selectedCircleColor) {
|
||||||
|
mSelectedCircleColor = selectedCircleColor;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCircleSpacing(int circleSpacing) {
|
||||||
|
mCircleSpacing = circleSpacing;
|
||||||
|
prepareCirclePoints();
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStartInterpolator(Interpolator startInterpolator) {
|
||||||
|
mStartInterpolator = startInterpolator;
|
||||||
|
if (mStartInterpolator == null) {
|
||||||
|
mStartInterpolator = new LinearInterpolator();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCircleCount(int count) {
|
||||||
|
mCircleCount = count; // 此处不调用invalidate,让外部调用notifyDataSetChanged
|
||||||
|
mNavigatorHelper.setTotalCount(mCircleCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTouchable(boolean touchable) {
|
||||||
|
mTouchable = touchable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFollowTouch(boolean followTouch) {
|
||||||
|
mFollowTouch = followTouch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSkimOver(boolean skimOver) {
|
||||||
|
mNavigatorHelper.setSkimOver(skimOver);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCircleClickListener(OnCircleClickListener circleClickListener) {
|
||||||
|
if (!mTouchable) {
|
||||||
|
mTouchable = true;
|
||||||
|
}
|
||||||
|
mCircleClickListener = circleClickListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEnter(int index, int totalCount, float enterPercent, boolean leftToRight) {
|
||||||
|
if (mFollowTouch) {
|
||||||
|
float radius = mMinRadius + (mMaxRadius - mMinRadius) * mStartInterpolator.getInterpolation(enterPercent);
|
||||||
|
mCircleRadiusArray.put(index, radius);
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLeave(int index, int totalCount, float leavePercent, boolean leftToRight) {
|
||||||
|
if (mFollowTouch) {
|
||||||
|
float radius = mMaxRadius + (mMinRadius - mMaxRadius) * mStartInterpolator.getInterpolation(leavePercent);
|
||||||
|
mCircleRadiusArray.put(index, radius);
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSelected(int index, int totalCount) {
|
||||||
|
if (!mFollowTouch) {
|
||||||
|
mCircleRadiusArray.put(index, (float) mMaxRadius);
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDeselected(int index, int totalCount) {
|
||||||
|
if (!mFollowTouch) {
|
||||||
|
mCircleRadiusArray.put(index, (float) mMinRadius);
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface OnCircleClickListener {
|
||||||
|
void onClick(int index);
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
app/src/main/res/drawable-hdpi/actions_about.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
app/src/main/res/drawable-hdpi/actions_account.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
app/src/main/res/drawable-hdpi/actions_booktag.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
app/src/main/res/drawable-hdpi/actions_cent.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
app/src/main/res/drawable-hdpi/actions_comment.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
app/src/main/res/drawable-hdpi/actions_feedback.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
app/src/main/res/drawable-hdpi/actions_item_bg_s.9.png
Normal file
|
After Width: | Height: | Size: 8.6 KiB |
BIN
app/src/main/res/drawable-hdpi/actions_logo.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
app/src/main/res/drawable-hdpi/actions_order.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
app/src/main/res/drawable-hdpi/actions_weibo.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
app/src/main/res/drawable-hdpi/charging.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
app/src/main/res/drawable-hdpi/com_android_appstore.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
app/src/main/res/drawable-hdpi/com_android_browser.png
Normal file
|
After Width: | Height: | Size: 8.4 KiB |
BIN
app/src/main/res/drawable-hdpi/com_android_calculator2.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
app/src/main/res/drawable-hdpi/com_android_calendar.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
app/src/main/res/drawable-hdpi/com_android_camera.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
app/src/main/res/drawable-hdpi/com_android_clean.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
app/src/main/res/drawable-hdpi/com_android_contacts.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
app/src/main/res/drawable-hdpi/com_android_deskclock.png
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
app/src/main/res/drawable-hdpi/com_android_dialer.png
Normal file
|
After Width: | Height: | Size: 4.7 KiB |
BIN
app/src/main/res/drawable-hdpi/com_android_email.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
app/src/main/res/drawable-hdpi/com_android_gallery3d_app.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
app/src/main/res/drawable-hdpi/com_android_mms_ui.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
app/src/main/res/drawable-hdpi/com_android_music.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
BIN
app/src/main/res/drawable-hdpi/com_android_quicksearchbox.png
Normal file
|
After Width: | Height: | Size: 4.5 KiB |
BIN
app/src/main/res/drawable-hdpi/com_android_settings.png
Normal file
|
After Width: | Height: | Size: 6.0 KiB |
BIN
app/src/main/res/drawable-hdpi/com_android_soundrecorder.png
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
BIN
app/src/main/res/drawable-hdpi/com_android_stk_stkmain.png
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
app/src/main/res/drawable-hdpi/com_android_vdieo.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
app/src/main/res/drawable-hdpi/com_mediatek_filemanager.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
app/src/main/res/drawable-hdpi/com_mediatek_fmradio.png
Normal file
|
After Width: | Height: | Size: 6.5 KiB |
BIN
app/src/main/res/drawable-hdpi/scan_qrcode.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
app/src/main/res/drawable-xhdpi/he100.png
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
app/src/main/res/drawable-xhdpi/he101.png
Normal file
|
After Width: | Height: | Size: 6.5 KiB |
BIN
app/src/main/res/drawable-xhdpi/he102.png
Normal file
|
After Width: | Height: | Size: 4.5 KiB |
BIN
app/src/main/res/drawable-xhdpi/he103.png
Normal file
|
After Width: | Height: | Size: 6.0 KiB |
BIN
app/src/main/res/drawable-xhdpi/he104.png
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
BIN
app/src/main/res/drawable-xhdpi/he150.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
app/src/main/res/drawable-xhdpi/he153.png
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
BIN
app/src/main/res/drawable-xhdpi/he154.png
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
BIN
app/src/main/res/drawable-xhdpi/he300.png
Normal file
|
After Width: | Height: | Size: 5.6 KiB |
BIN
app/src/main/res/drawable-xhdpi/he301.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
BIN
app/src/main/res/drawable-xhdpi/he302.png
Normal file
|
After Width: | Height: | Size: 5.6 KiB |
BIN
app/src/main/res/drawable-xhdpi/he303.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
BIN
app/src/main/res/drawable-xhdpi/he304.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
BIN
app/src/main/res/drawable-xhdpi/he305.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
app/src/main/res/drawable-xhdpi/he306.png
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
BIN
app/src/main/res/drawable-xhdpi/he307.png
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
BIN
app/src/main/res/drawable-xhdpi/he308.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
app/src/main/res/drawable-xhdpi/he309.png
Normal file
|
After Width: | Height: | Size: 4.7 KiB |
BIN
app/src/main/res/drawable-xhdpi/he310.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
BIN
app/src/main/res/drawable-xhdpi/he311.png
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
BIN
app/src/main/res/drawable-xhdpi/he312.png
Normal file
|
After Width: | Height: | Size: 6.0 KiB |
BIN
app/src/main/res/drawable-xhdpi/he313.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
BIN
app/src/main/res/drawable-xhdpi/he314.png
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
BIN
app/src/main/res/drawable-xhdpi/he315.png
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
BIN
app/src/main/res/drawable-xhdpi/he316.png
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
BIN
app/src/main/res/drawable-xhdpi/he317.png
Normal file
|
After Width: | Height: | Size: 6.3 KiB |
BIN
app/src/main/res/drawable-xhdpi/he318.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
app/src/main/res/drawable-xhdpi/he350.png
Normal file
|
After Width: | Height: | Size: 5.6 KiB |
BIN
app/src/main/res/drawable-xhdpi/he351.png
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
BIN
app/src/main/res/drawable-xhdpi/he399.png
Normal file
|
After Width: | Height: | Size: 813 B |
BIN
app/src/main/res/drawable-xhdpi/he400.png
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
app/src/main/res/drawable-xhdpi/he401.png
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
BIN
app/src/main/res/drawable-xhdpi/he402.png
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
BIN
app/src/main/res/drawable-xhdpi/he403.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
BIN
app/src/main/res/drawable-xhdpi/he404.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
app/src/main/res/drawable-xhdpi/he405.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
app/src/main/res/drawable-xhdpi/he406.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
BIN
app/src/main/res/drawable-xhdpi/he407.png
Normal file
|
After Width: | Height: | Size: 5.7 KiB |
BIN
app/src/main/res/drawable-xhdpi/he408.png
Normal file
|
After Width: | Height: | Size: 5.7 KiB |
BIN
app/src/main/res/drawable-xhdpi/he409.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |