├── .gitignore
├── .idea
├── compiler.xml
├── copyright
│ └── profiles_settings.xml
├── encodings.xml
├── gradle.xml
├── misc.xml
├── modules.xml
├── runConfigurations.xml
└── vcs.xml
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── ks
│ │ └── controlcenter
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── ks
│ │ │ └── control
│ │ │ ├── AlarmPowerManager.java
│ │ │ ├── AnimationUtil.java
│ │ │ ├── CtrlCenterWindowBigView.java
│ │ │ ├── CtrlCenterWindowService.java
│ │ │ ├── CtrlCenterWindowSmallView.java
│ │ │ ├── FlashLightManager.java
│ │ │ ├── FloatWindowBigView.java
│ │ │ ├── FloatWindowService.java
│ │ │ ├── FloatWindowSmallView.java
│ │ │ ├── HomeKeyEventBroadCastReceiver.java
│ │ │ ├── HomeWatcherReceiver.java
│ │ │ ├── MainActivity.java
│ │ │ ├── MyWindowManager.java
│ │ │ ├── SettingActivity.java
│ │ │ └── WebActivity.java
│ └── res
│ │ ├── animator
│ │ ├── indicator_animator.xml
│ │ ├── indicator_animator_reverse.xml
│ │ └── scale_with_alpha.xml
│ │ ├── drawable
│ │ ├── alertdialog_bg.xml
│ │ ├── alertdialog_edit_bg.xml
│ │ ├── floating_bg.xml
│ │ ├── floating_small_bg.xml
│ │ └── floating_small_btn.xml
│ │ ├── layout
│ │ ├── activity_main.xml
│ │ ├── activity_setting.xml
│ │ ├── activity_web.xml
│ │ ├── floating_ctrl_center_window_big.xml
│ │ ├── floating_ctrl_center_window_small.xml
│ │ ├── floating_window_big.xml
│ │ └── floating_window_small.xml
│ │ ├── mipmap-xhdpi
│ │ ├── ctrl_center_icon_camara.png
│ │ ├── ctrl_center_icon_text.png
│ │ ├── ctrl_center_icon_voice.png
│ │ ├── floating_icon_camara.png
│ │ ├── floating_icon_home.png
│ │ ├── floating_icon_text.png
│ │ ├── floating_icon_voice.png
│ │ ├── ic_find_next_holo_light.png
│ │ └── ic_launcher.png
│ │ ├── values-v21
│ │ └── styles.xml
│ │ ├── values
│ │ ├── arrays.xml
│ │ ├── attrs.xml
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── ids.xml
│ │ ├── public.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ │ └── xml
│ │ └── preferences.xml
│ └── test
│ └── java
│ └── com
│ └── ks
│ └── controlcenter
│ └── ExampleUnitTest.java
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 | .externalNativeBuild
10 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
17 |
18 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | 1.8
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ControlCenter
2 | 安卓仿iPhone控制中心,上划出现控制中心工具栏
3 | Android 控制中心
4 | # 关于应用
5 | Android 控制中心是一款『超轻量级』的便捷工具应用
6 | 纯粹,拒绝『后台工作』,不随意消耗 电量
7 | 节能,拒绝『后台连网』,不任意消耗 流量
8 | 简洁至极,『727K』安装包,仅一张图片大小
9 | # 一触即发
10 | 快速,『9 毫秒』极速启动,内存消耗也极少
11 | 便捷,『一步直达』开关设置、参数调整、应用启动
12 | 手机底部上划/左右边缘触摸/双击Home键,即划出控制面板
13 | # 手电筒
14 | 弹出面板,强光手电一触即发,手电筒瞬间点亮你的黑夜
15 | # 扫一扫
16 | 划出面板,二维码、条形码轻松扫,一点即开
17 | 支持打开网页、下载、搜索
18 | 支持扫描wifi设置并直接关联
19 | 支持文本转换二维码并分享出去
20 | 支持地图显示地理位置、经纬度
21 | 支持解析名片,新建联系人,拨打电话、发送短信
22 | # 快捷开关
23 | 网络、蓝牙、定位、震动模式、飞行模式、竖屏模式、勿扰模式、省电模式等
24 | # 快速调节
25 | 调节屏幕亮度,调节声音大小
26 | 铃声、音视频、系统、通知四种声音同步调整一步到位
27 | 声音同步调整,避免铃声静音而视频却大声播放的尴尬
28 | # 一步直达
29 | 一步拉起支付宝扫码付款
30 | 一步直达系统录音器、闹钟、照相机
31 | # 升级规划
32 | 音乐控制
33 | 自定义功能
34 | 常用联系人
35 | 应用便捷操作
36 | 应用截图
37 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 25
5 | buildToolsVersion "25.0.3"
6 | defaultConfig {
7 | applicationId "com.ks.control"
8 | minSdkVersion 14
9 | targetSdkVersion 25
10 | versionCode 1
11 | versionName "1.0"
12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile fileTree(dir: 'libs', include: ['*.jar'])
24 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
25 | exclude group: 'com.android.support', module: 'support-annotations'
26 | })
27 | compile 'com.android.support:appcompat-v7:25.3.1'
28 | compile 'com.android.support.constraint:constraint-layout:1.0.2'
29 | compile 'com.nineoldandroids:library:2.4.0'
30 | testCompile 'junit:junit:4.12'
31 | }
32 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in E:\Android\android-sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | # Uncomment this to preserve the line number information for
20 | # debugging stack traces.
21 | #-keepattributes SourceFile,LineNumberTable
22 |
23 | # If you keep the line number information, uncomment this to
24 | # hide the original source file name.
25 | #-renamesourcefileattribute SourceFile
26 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/ks/controlcenter/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.ks.controlcenter;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumentation test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.ks.controlcenter", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
38 |
41 |
42 |
45 |
46 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
76 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/app/src/main/java/com/ks/control/AlarmPowerManager.java:
--------------------------------------------------------------------------------
1 | package com.ks.control;
2 |
3 | import android.app.AlarmManager;
4 | import android.app.PendingIntent;
5 | import android.content.Context;
6 | import android.content.Intent;
7 | import android.util.Log;
8 |
9 | import java.io.DataOutputStream;
10 | import java.io.IOException;
11 | import java.lang.reflect.Method;
12 |
13 | /**
14 | * Created by Admin on 2017/6/16 0016 11:21.
15 | * Author: kang
16 | * Email: kangsafe@163.com
17 | */
18 |
19 | public class AlarmPowerManager {
20 |
21 | public static void rebootBroadcast(Context context) {
22 | Intent i = new Intent(Intent.ACTION_REBOOT);
23 | i.putExtra("nowait", 1);
24 | i.putExtra("interval", 1);
25 | i.putExtra("window", 0);
26 | context.sendBroadcast(i);
27 | }
28 |
29 | public static void powerOffAlarm(Context context) {
30 | Intent intent = new Intent(
31 | "com.android.settings.action.REQUEST_POWER_OFF");
32 | PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0,
33 | intent, PendingIntent.FLAG_CANCEL_CURRENT);
34 | AlarmManager am = (AlarmManager) context
35 | .getSystemService(Context.ALARM_SERVICE);
36 | am.set(AlarmManager.RTC_WAKEUP, 0, pendingIntent);
37 | }
38 |
39 | public static void powerOff(Context context) {
40 | Process process;
41 | try {
42 | process = Runtime.getRuntime().exec("su");
43 | DataOutputStream out = new DataOutputStream(
44 | process.getOutputStream());
45 | out.writeBytes("reboot -p\n");
46 | out.writeBytes("exit\n");
47 | out.flush();
48 | } catch (IOException e) {
49 | e.printStackTrace();
50 | }
51 | }
52 |
53 | public static void reBoot() {
54 | try {
55 | Process proc = Runtime.getRuntime().exec("su -c \"/system/bin/reboot\"");
56 | proc.waitFor();
57 |
58 | } catch (Exception e) {
59 | e.printStackTrace();
60 | }
61 |
62 | }
63 |
64 | public static void powerOff() {
65 | try {
66 |
67 | //获得ServiceManager类
68 | Class> ServiceManager = Class
69 | .forName("android.os.ServiceManager");
70 |
71 | //获得ServiceManager的getService方法
72 | Method getService = ServiceManager.getMethod("getService", java.lang.String.class);
73 |
74 | //调用getService获取RemoteService
75 | Object oRemoteService = getService.invoke(null, Context.POWER_SERVICE);
76 |
77 | //获得IPowerManager.Stub类
78 | Class> cStub = Class
79 | .forName("android.os.IPowerManager$Stub");
80 | //获得asInterface方法
81 | Method asInterface = cStub.getMethod("asInterface", android.os.IBinder.class);
82 | //调用asInterface方法获取IPowerManager对象
83 | Object oIPowerManager = asInterface.invoke(null, oRemoteService);
84 | //获得shutdown()方法
85 | Method shutdown = oIPowerManager.getClass().getMethod("shutdown", boolean.class, boolean.class);
86 | //调用shutdown()方法
87 | shutdown.invoke(oIPowerManager, false, true);
88 |
89 | } catch (Exception e) {
90 | Log.e("powerOff", e.toString(), e);
91 | }
92 | }
93 |
94 | public static void bcShutdown(Context context) {
95 | Log.v("TAG", "broadcast->shutdown");
96 | Intent intent = new Intent("android.intent.action.ACTION_REQUEST_SHUTDOWN");
97 | intent.putExtra("android.intent.extra.KEY_CONFIRM", false);
98 | //其中false换成true,会弹出是否关机的确认窗口
99 | intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
100 | context.startActivity(intent);
101 | }
102 |
103 | public static void bcReboot(Context context) {
104 | Log.v("TAG", "broadcast->reboot");
105 | Intent intent2 = new Intent(Intent.ACTION_REBOOT);
106 | intent2.putExtra("nowait", 1);
107 | intent2.putExtra("interval", 1);
108 | intent2.putExtra("window", 0);
109 | context.sendBroadcast(intent2);
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/app/src/main/java/com/ks/control/AnimationUtil.java:
--------------------------------------------------------------------------------
1 | package com.ks.control;
2 |
3 | import android.view.animation.Animation;
4 | import android.view.animation.TranslateAnimation;
5 |
6 | /**
7 | * Created by Admin on 2017/6/14 0014 13:50.
8 | * Author: kang
9 | * Email: kangsafe@163.com
10 | */
11 |
12 | public class AnimationUtil {
13 | private static final String TAG = AnimationUtil.class.getSimpleName();
14 |
15 | /**
16 | * 从控件所在位置移动到控件的底部
17 | *
18 | * @return
19 | */
20 | public static TranslateAnimation moveToViewBottom() {
21 | TranslateAnimation mHiddenAction = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0.0f,
22 | Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF,
23 | 0.0f, Animation.RELATIVE_TO_SELF, 1.0f);
24 | mHiddenAction.setDuration(500);
25 | return mHiddenAction;
26 | }
27 |
28 | /**
29 | * 从控件的底部移动到控件所在位置
30 | *
31 | * @return
32 | */
33 | public static TranslateAnimation moveToViewLocation() {
34 | TranslateAnimation mHiddenAction = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0.0f,
35 | Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF,
36 | 1.0f, Animation.RELATIVE_TO_SELF, 0.0f);
37 | mHiddenAction.setDuration(500);
38 | return mHiddenAction;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/app/src/main/java/com/ks/control/CtrlCenterWindowBigView.java:
--------------------------------------------------------------------------------
1 | package com.ks.control;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.os.Handler;
6 | import android.util.Log;
7 | import android.view.KeyEvent;
8 | import android.view.LayoutInflater;
9 | import android.view.MotionEvent;
10 | import android.view.View;
11 | import android.view.animation.AnimationUtils;
12 | import android.widget.LinearLayout;
13 |
14 | import com.nineoldandroids.animation.ObjectAnimator;
15 |
16 | /**
17 | * Created by Admin on 2017/6/13 0013 09:36.
18 | * Author: kang
19 | * Email: kangsafe@163.com
20 | */
21 | public class CtrlCenterWindowBigView extends LinearLayout {
22 | View big;
23 |
24 | public CtrlCenterWindowBigView(final Context context) {
25 | super(context);
26 | View view = LayoutInflater.from(context).inflate(R.layout.floating_ctrl_center_window_big, this);
27 | big = view.findViewById(R.id.ctrl_center_big_container);
28 | big.setAnimation(AnimationUtil.moveToViewLocation());
29 | //拍照
30 | findViewById(R.id.floating_camara).setOnClickListener(new OnClickListener() {
31 | @Override
32 | public void onClick(View v) {
33 | // Intent intent = new Intent(context, EditDocumentActivity.class);
34 | // intent.putExtra(NoteActivity.FAB_ACTION, R.id.action_markdown_take_photo);
35 | // intent.putExtra(ExtraCode.GroupId, "");
36 | // context.startActivity(intent);
37 | back();
38 | }
39 | });
40 | //文本
41 | findViewById(R.id.floating_text).setOnClickListener(new OnClickListener() {
42 | @Override
43 | public void onClick(View v) {
44 | // Intent intent = new Intent(context, EditDocumentActivity.class);
45 | // intent.putExtra(ExtraCode.GroupId, "");
46 | // context.startActivity(intent);
47 | back();
48 | }
49 | });
50 | //语音
51 | findViewById(R.id.floating_voice).setOnClickListener(new OnClickListener() {
52 | @Override
53 | public void onClick(View v) {
54 | back();
55 | }
56 | });
57 | }
58 |
59 | private void back() {
60 | ObjectAnimator animator = ObjectAnimator.ofFloat(big, "translationY", 0, big.getHeight());
61 | animator.setDuration(500);
62 | animator.start();
63 | animator.setInterpolator(AnimationUtils.loadInterpolator(getContext(), android.R.interpolator.linear));
64 | // big.setAnimation(animator);
65 | // big.setAnimation(AnimationUtil.moveToViewBottom());
66 | // big.setVisibility(GONE);
67 | // ViewHelper.setTranslationY(big, big.getHeight());
68 | new Handler().postDelayed(new Runnable() {
69 | @Override
70 | public void run() {
71 | MyWindowManager.removeCtrlCenterBigWindow(getContext());
72 | MyWindowManager.createCtrlCenterSmallWindow(getContext());
73 | }
74 | }, 500);
75 | }
76 |
77 | @Override
78 | public boolean dispatchKeyEvent(KeyEvent event) {
79 | Log.i("Key", big.getVisibility() + ":" + event.getAction() + ":" + event.getKeyCode());
80 | if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) {
81 | back();
82 | }
83 | return super.dispatchKeyEvent(event);
84 | }
85 |
86 | @Override
87 | public boolean dispatchTouchEvent(MotionEvent event) {
88 | Log.i("Key", "Visiblity:" + big.getVisibility() + ",Action:" + event.getAction() +
89 | ",RawX:" + event.getRawX() + ",RawY:" + event.getRawY() + ",X:" + event.getX() + ",Y:" + event.getY());
90 | // if (event.getAction() == MotionEvent.ACTION_DOWN) {
91 | // Notify touch outside listener if user tapped outside a given view
92 | // Rect viewRect = new Rect();
93 | // big.getGlobalVisibleRect(viewRect);
94 | // if (!viewRect.contains((int) event.getRawX(), (int) event.getRawY())) {
95 | // back();
96 | // }
97 | // }
98 | if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
99 | back();
100 | return true;
101 | }
102 | return super.dispatchTouchEvent(event);
103 | }
104 | //
105 | // public void onAttachedToWindow() {
106 | // getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD);
107 | // super.onAttachedToWindow();
108 | // }
109 |
110 | // public void setOnTouchOutsideViewListener(View view, OnTouchOutsideViewListener onTouchOutsideViewListener) {
111 | // mTouchOutsideView = view;
112 | // mOnTouchOutsideViewListener = onTouchOutsideViewListener;
113 | // }
114 | //
115 | // public OnTouchOutsideViewListener getOnTouchOutsideViewListener() {
116 | // return mOnTouchOutsideViewListener;
117 | // }
118 |
119 | // @Override
120 | // public boolean dispatchTouchEvent(final MotionEvent ev) {
121 | // if (ev.getAction() == MotionEvent.ACTION_DOWN) {
122 | // // Notify touch outside listener if user tapped outside a given view
123 | // if (mOnTouchOutsideViewListener != null && mTouchOutsideView != null
124 | // && mTouchOutsideView.getVisibility() == View.VISIBLE) {
125 | // Rect viewRect = new Rect();
126 | // mTouchOutsideView.getGlobalVisibleRect(viewRect);
127 | // if (!viewRect.contains((int) ev.getRawX(), (int) ev.getRawY())) {
128 | // mOnTouchOutsideViewListener.onTouchOutside(mTouchOutsideView, ev);
129 | // }
130 | // }
131 | // }
132 | // return super.dispatchTouchEvent(ev);
133 | // }
134 |
135 | // /**
136 | // * Interface definition for a callback to be invoked when a touch event has occurred outside a formerly specified
137 | // * view. See {@link #setOnTouchOutsideViewListener(View, OnTouchOutsideViewListener).}
138 | // */
139 | // public interface OnTouchOutsideViewListener {
140 | //
141 | // /**
142 | // * Called when a touch event has occurred outside a given view.
143 | // *
144 | // * @param view The view that has not been touched.
145 | // * @param event The MotionEvent object containing full information about the event.
146 | // */
147 | // void onTouchOutside(View view, MotionEvent event);
148 | // }
149 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/ks/control/CtrlCenterWindowService.java:
--------------------------------------------------------------------------------
1 | package com.ks.control;
2 |
3 | import android.app.ActivityManager;
4 | import android.app.Service;
5 | import android.content.Context;
6 | import android.content.Intent;
7 | import android.content.pm.PackageManager;
8 | import android.content.pm.ResolveInfo;
9 | import android.os.IBinder;
10 |
11 | import java.util.ArrayList;
12 | import java.util.List;
13 |
14 | /**
15 | * Created by Admin on 2017/6/13 0013 09:34.
16 | * Author: kang
17 | * Email: kangsafe@163.com
18 | */
19 |
20 | public class CtrlCenterWindowService extends Service {
21 |
22 | @Override
23 | public IBinder onBind(Intent intent) {
24 | return null;
25 | }
26 |
27 | @Override
28 | public int onStartCommand(Intent intent, int flags, int startId) {
29 | MyWindowManager.createCtrlCenterSmallWindow(getApplicationContext());
30 | return super.onStartCommand(intent, flags, startId);
31 | }
32 |
33 | @Override
34 | public void onDestroy() {
35 | super.onDestroy();
36 | }
37 |
38 | /**
39 | * 判断当前界面是否是桌面
40 | */
41 | private boolean isHome() {
42 | ActivityManager mActivityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
43 | List rti = mActivityManager.getRunningTasks(1);
44 | return getHomes().contains(rti.get(0).topActivity.getPackageName());
45 | }
46 |
47 | /**
48 | * 获得属于桌面的应用的应用包名称
49 | *
50 | * @return 返回包含所有包名的字符串列表
51 | */
52 | private List getHomes() {
53 | List names = new ArrayList();
54 | PackageManager packageManager = this.getPackageManager();
55 | Intent intent = new Intent(Intent.ACTION_MAIN);
56 | intent.addCategory(Intent.CATEGORY_HOME);
57 | List resolveInfo = packageManager.queryIntentActivities(intent,
58 | PackageManager.MATCH_DEFAULT_ONLY);
59 | for (ResolveInfo ri : resolveInfo) {
60 | names.add(ri.activityInfo.packageName);
61 | }
62 | return names;
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/app/src/main/java/com/ks/control/CtrlCenterWindowSmallView.java:
--------------------------------------------------------------------------------
1 | package com.ks.control;
2 |
3 | import android.content.Context;
4 | import android.view.LayoutInflater;
5 | import android.view.MotionEvent;
6 | import android.view.View;
7 | import android.view.WindowManager;
8 | import android.widget.LinearLayout;
9 |
10 | /**
11 | * Created by Admin on 2017/6/13 0013 09:36.
12 | * Author: kang
13 | * Email: kangsafe@163.com
14 | */
15 | public class CtrlCenterWindowSmallView extends LinearLayout {
16 |
17 | /**
18 | * 用于更新小悬浮窗的位置
19 | */
20 | private WindowManager windowManager;
21 |
22 | /**
23 | * 记录当前手指位置在屏幕上的纵坐标值
24 | */
25 | private float yInScreen;
26 |
27 | /**
28 | * 记录手指按下时在屏幕上的纵坐标的值
29 | */
30 | private float yDownInScreen;
31 |
32 | /**
33 | * 小悬浮窗的参数
34 | */
35 | private WindowManager.LayoutParams mParams;
36 |
37 | public CtrlCenterWindowSmallView(final Context context) {
38 | super(context);
39 | windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
40 | View view = LayoutInflater.from(context).inflate(R.layout.floating_ctrl_center_window_small, this);
41 | }
42 |
43 | @Override
44 | public boolean onTouchEvent(MotionEvent event) {
45 | switch (event.getAction()) {
46 | case MotionEvent.ACTION_DOWN:
47 | // 手指按下时记录必要数据,纵坐标的值都需要减去状态栏高度
48 | yDownInScreen = event.getRawY();
49 | break;
50 | case MotionEvent.ACTION_MOVE:
51 | yInScreen = event.getRawY();
52 | updateViewPosition();
53 | break;
54 | case MotionEvent.ACTION_UP:
55 | // 如果手指离开屏幕时,xDownInScreen和xInScreen相等,且yDownInScreen和yInScreen相等,则视为触发了单击事件。
56 | if (yDownInScreen - yInScreen > 5) {
57 | openBigWindow();
58 | }
59 | yDownInScreen = yInScreen;
60 | updateViewPosition();
61 | break;
62 | default:
63 | break;
64 | }
65 | return true;
66 | }
67 |
68 | /**
69 | * 打开大悬浮窗,同时关闭小悬浮窗。
70 | */
71 | private void openBigWindow() {
72 | MyWindowManager.removeCtrlCenterSmallWindow(getContext());
73 | MyWindowManager.createCtrlCenterBigWindow(getContext());
74 | }
75 |
76 | /**
77 | * 更新小悬浮窗在屏幕中的位置。
78 | */
79 | private void updateViewPosition() {
80 | mParams.x = 0;
81 | mParams.y = (int) (yDownInScreen - yInScreen);
82 | windowManager.updateViewLayout(this, mParams);
83 | }
84 |
85 | /**
86 | * 将小悬浮窗的参数传入,用于更新小悬浮窗的位置。
87 | *
88 | * @param params 小悬浮窗的参数
89 | */
90 | public void setParams(WindowManager.LayoutParams params) {
91 | mParams = params;
92 | }
93 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/ks/control/FlashLightManager.java:
--------------------------------------------------------------------------------
1 | package com.ks.control;
2 |
3 | /**
4 | * Created by Admin on 2017/6/16 0016 09:01.
5 | * Author: kang
6 | * Email: kangsafe@163.com
7 | */
8 |
9 | import android.Manifest;
10 | import android.content.Context;
11 | import android.content.pm.FeatureInfo;
12 | import android.content.pm.PackageManager;
13 | import android.graphics.SurfaceTexture;
14 | import android.hardware.Camera;
15 | import android.hardware.camera2.CameraCaptureSession;
16 | import android.hardware.camera2.CameraCharacteristics;
17 | import android.hardware.camera2.CameraDevice;
18 | import android.hardware.camera2.CameraManager;
19 | import android.hardware.camera2.CameraMetadata;
20 | import android.hardware.camera2.CaptureRequest;
21 | import android.hardware.camera2.params.StreamConfigurationMap;
22 | import android.os.Build;
23 | import android.support.v4.app.ActivityCompat;
24 | import android.util.Log;
25 | import android.view.Surface;
26 | import android.widget.Toast;
27 |
28 | import java.util.ArrayList;
29 | import java.util.List;
30 |
31 | /**
32 | * 闪光灯管理工具类
33 | *
34 | * @author linzhiyong
35 | * @time 2016年11月17日07:47:03
36 | * @email wflinzhiyong@163.com
37 | * @desc * 如果配合拍照使用, 则无需调用init()方法, 直接使用turnLightOnCamera(Camera c) turnLightOffCamera(Camera c)
38 | * * 如果只作为手电筒使用, 则需要初始化init()方法, 使用turnOn() turnOff()
39 | */
40 | public class FlashLightManager {
41 |
42 | private static final String TAG = FlashLightManager.class.getName();
43 |
44 | /**
45 | * 上下文对象
46 | */
47 | private Context context;
48 |
49 | /**
50 | * 是否已经开启闪光灯
51 | */
52 | private boolean isOpenFlash = false;
53 |
54 | /**
55 | * Camera相机硬件操作类
56 | */
57 | private Camera camera = null;
58 |
59 | /**
60 | * Camera2相机硬件操作类
61 | */
62 | private CameraManager manager = null;
63 | private CameraDevice cameraDevice;
64 | private CameraCaptureSession captureSession = null;
65 | private CaptureRequest request = null;
66 | private SurfaceTexture surfaceTexture;
67 | private Surface surface;
68 | private String cameraId = null;
69 | private boolean isSupportFlashCamera2 = false;
70 |
71 | private FlashLightManager() {
72 | }
73 |
74 | public FlashLightManager(Context context) {
75 | this.context = context;
76 | }
77 |
78 | /**
79 | * 初始化相机
80 | */
81 | public void init() {
82 | this.manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
83 | if (isLOLLIPOP()) {
84 | initCamera2();
85 | } else {
86 | camera = Camera.open();
87 | }
88 | }
89 |
90 | /**
91 | * 开启闪光灯
92 | */
93 | public void turnOn() {
94 | if (!isSupportFlash()) {
95 | showToast("设备不支持闪光灯!");
96 | return;
97 | }
98 | if (isOpenFlash) {
99 | return;
100 | }
101 |
102 | if (isLOLLIPOP()) {
103 | turnLightOnCamera2();
104 | } else {
105 | turnLightOnCamera(camera);
106 | }
107 | }
108 |
109 | /**
110 | * 关闭闪光灯
111 | */
112 | public void turnOff() {
113 | if (!isSupportFlash()) {
114 | showToast("设备不支持闪光灯!");
115 | return;
116 | }
117 | if (!isOpenFlash) {
118 | return;
119 | }
120 | if (isLOLLIPOP()) {
121 | turnLightOffCamera2();
122 | } else {
123 | turnLightOffCamera(camera);
124 | }
125 | isOpenFlash = false;
126 | }
127 |
128 | /**
129 | * 开启Camera2闪光灯
130 | */
131 | private void turnLightOnCamera2() {
132 | new Object() {
133 | private void _turnLightOnCamera2() {
134 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
135 | if (ActivityCompat.checkSelfPermission(context, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
136 | showToast("应用未开启访问相机权限!");
137 | return;
138 | }
139 | try {
140 | manager.openCamera(cameraId, new CameraDevice.StateCallback() {
141 |
142 | @Override
143 | public void onOpened(CameraDevice camera) {
144 | cameraDevice = camera;
145 | createCaptureSession();
146 | }
147 |
148 | @Override
149 | public void onError(CameraDevice camera, int error) {
150 | }
151 |
152 | @Override
153 | public void onDisconnected(CameraDevice camera) {
154 | }
155 | }, null);
156 | } catch (Exception e) {
157 | Log.e(TAG, e.getMessage(), e);
158 | showToast("开启失败:" + e.getMessage());
159 | }
160 | }
161 | }
162 | }._turnLightOnCamera2();
163 | }
164 |
165 | /**
166 | * 关闭Camera2闪光灯
167 | */
168 | private void turnLightOffCamera2() {
169 | new Object() {
170 | private void _turnLightOffCamera2() {
171 | if (cameraDevice != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
172 | cameraDevice.close();
173 | }
174 | }
175 | }._turnLightOffCamera2();
176 | }
177 |
178 | /**
179 | * 判断设备是否支持闪光灯
180 | *
181 | * @return boolean
182 | */
183 | public boolean isSupportFlash() {
184 | if (isLOLLIPOP()) { // 判断当前Android系统版本是否 >= 21, 分别处理
185 | return isSupportFlashCamera2;
186 | } else {
187 | PackageManager pm = context.getPackageManager();
188 | FeatureInfo[] features = pm.getSystemAvailableFeatures();
189 | for (FeatureInfo f : features) {
190 | // 判断设备是否支持闪光灯
191 | if (PackageManager.FEATURE_CAMERA_FLASH.equals(f.name)) {
192 | return true;
193 | }
194 | }
195 | // 判断是否支持闪光灯,方式二
196 | // Camera.Parameters parameters = camera.getParameters();
197 | // if (parameters == null) {
198 | // return false;
199 | // }
200 | // List flashModes = parameters.getSupportedFlashModes();
201 | // if (flashModes == null) {
202 | // return false;
203 | // }
204 | }
205 | return false;
206 | }
207 |
208 | /**
209 | * 是否已经开启闪光灯
210 | *
211 | * @return
212 | */
213 | public boolean isTurnOnFlash() {
214 | return isOpenFlash;
215 | }
216 |
217 | /**
218 | * 判断Android系统版本是否 >= LOLLIPOP(API21)
219 | *
220 | * @return boolean
221 | */
222 | private boolean isLOLLIPOP() {
223 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
224 | return true;
225 | } else {
226 | return false;
227 | }
228 | }
229 |
230 | /**
231 | * 通过设置Camera打开闪光灯
232 | *
233 | * @param mCamera
234 | */
235 | public void turnLightOnCamera(Camera mCamera) {
236 | Camera.Parameters parameters = mCamera.getParameters();
237 | List flashModes = parameters.getSupportedFlashModes();
238 | String flashMode = parameters.getFlashMode();
239 | if (!Camera.Parameters.FLASH_MODE_TORCH.equals(flashMode)) {
240 | // 开启闪光灯
241 | if (flashModes.contains(Camera.Parameters.FLASH_MODE_TORCH)) {
242 | parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
243 | mCamera.setParameters(parameters);
244 | }
245 | }
246 | isOpenFlash = true;
247 | }
248 |
249 | /**
250 | * 通过设置Camera关闭闪光灯
251 | *
252 | * @param mCamera
253 | */
254 | public void turnLightOffCamera(Camera mCamera) {
255 | Camera.Parameters parameters = mCamera.getParameters();
256 | List flashModes = parameters.getSupportedFlashModes();
257 | String flashMode = parameters.getFlashMode();
258 | if (!Camera.Parameters.FLASH_MODE_OFF.equals(flashMode)) {
259 | // 关闭闪光灯
260 | if (flashModes.contains(Camera.Parameters.FLASH_MODE_OFF)) {
261 | parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
262 | mCamera.setParameters(parameters);
263 | }
264 | }
265 | isOpenFlash = false;
266 | }
267 |
268 | /**
269 | * 初始化Camera2
270 | */
271 | private void initCamera2() {
272 | new Object() {
273 | private void _initCamera2() {
274 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
275 | try {
276 | for (String _cameraId : manager.getCameraIdList()) {
277 | CameraCharacteristics characteristics = manager.getCameraCharacteristics(_cameraId);
278 | // 过滤掉前置摄像头
279 | Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);
280 | if (facing != null && facing == CameraCharacteristics.LENS_FACING_FRONT) {
281 | continue;
282 | }
283 | StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
284 | if (map == null) {
285 | continue;
286 | }
287 | cameraId = _cameraId;
288 | // 判断设备是否支持闪光灯
289 | isSupportFlashCamera2 = characteristics.get(CameraCharacteristics.FLASH_INFO_AVAILABLE);
290 | }
291 | } catch (Exception e) {
292 | Log.e(TAG, e.getMessage(), e);
293 | showToast("初始化失败:" + e.getMessage());
294 | }
295 | }
296 | }
297 | }._initCamera2();
298 | }
299 |
300 | /**
301 | * createCaptureSession
302 | */
303 | private void createCaptureSession() {
304 | new Object() {
305 | private void _createCaptureSession() {
306 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
307 | final CameraCaptureSession.StateCallback stateCallback = new CameraCaptureSession.StateCallback() {
308 |
309 | public void onConfigured(CameraCaptureSession arg0) {
310 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
311 | captureSession = arg0;
312 | CaptureRequest.Builder builder;
313 | try {
314 | builder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
315 | builder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_TORCH);
316 | builder.addTarget(surface);
317 | request = builder.build();
318 | captureSession.capture(request, null, null);
319 | isOpenFlash = true;
320 | } catch (Exception e) {
321 | Log.e(TAG, e.getMessage(), e);
322 | showToast("开启失败:" + e.getMessage());
323 | }
324 | }
325 | }
326 |
327 | public void onConfigureFailed(CameraCaptureSession arg0) {
328 | }
329 | };
330 |
331 | surfaceTexture = new SurfaceTexture(0, false);
332 | surfaceTexture.setDefaultBufferSize(1280, 720);
333 | surface = new Surface(surfaceTexture);
334 | ArrayList localArrayList = new ArrayList(1);
335 | localArrayList.add(surface);
336 | try {
337 | cameraDevice.createCaptureSession(localArrayList, stateCallback, null);
338 | } catch (Exception e) {
339 | Log.e(TAG, e.getMessage(), e);
340 | showToast("开启失败:" + e.getMessage());
341 | }
342 | }
343 | }
344 | }._createCaptureSession();
345 | }
346 |
347 | private void showToast(String content) {
348 | Toast.makeText(context, content, Toast.LENGTH_LONG).show();
349 | }
350 |
351 | }
352 |
--------------------------------------------------------------------------------
/app/src/main/java/com/ks/control/FloatWindowBigView.java:
--------------------------------------------------------------------------------
1 | package com.ks.control;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.widget.Button;
8 | import android.widget.ImageView;
9 | import android.widget.LinearLayout;
10 |
11 | /**
12 | * Created by Admin on 2017/6/13 0013 09:37.
13 | * Author: kang
14 | * Email: kangsafe@163.com
15 | */
16 |
17 | public class FloatWindowBigView extends LinearLayout {
18 |
19 | /**
20 | * 记录大悬浮窗的宽度
21 | */
22 | public static int viewWidth;
23 |
24 | /**
25 | * 记录大悬浮窗的高度
26 | */
27 | public static int viewHeight;
28 | private Context context;
29 |
30 | public FloatWindowBigView(final Context context) {
31 | super(context);
32 | this.context = context;
33 | LayoutInflater.from(context).inflate(R.layout.floating_window_big, this);
34 | View view = findViewById(R.id.big_window_layout);
35 | viewWidth = view.getLayoutParams().width;
36 | viewHeight = view.getLayoutParams().height;
37 | Button close = (Button) findViewById(R.id.close);
38 | final Button back = (Button) findViewById(R.id.back);
39 | ImageView camara = (ImageView) findViewById(R.id.floating_camara);
40 | ImageView text = (ImageView) findViewById(R.id.floating_text);
41 | ImageView home = (ImageView) findViewById(R.id.floating_home);
42 | ImageView voice = (ImageView) findViewById(R.id.floating_voice);
43 | close.setOnClickListener(new OnClickListener() {
44 | @Override
45 | public void onClick(View v) {
46 | back();
47 | Intent intent = new Intent(getContext(), FloatWindowService.class);
48 | context.stopService(intent);
49 | }
50 | });
51 | back.setOnClickListener(new OnClickListener() {
52 | @Override
53 | public void onClick(View v) {
54 | back();
55 | }
56 | });
57 | camara.setOnClickListener(new OnClickListener() {
58 | @Override
59 | public void onClick(View v) {
60 | // Intent intent = new Intent(context, EditDocumentActivity.class);
61 | // intent.putExtra(NoteActivity.FAB_ACTION, R.id.action_markdown_take_photo);
62 | // intent.putExtra(ExtraCode.GroupId, "");
63 | // context.startActivity(intent);
64 | back();
65 | }
66 | });
67 | text.setOnClickListener(new OnClickListener() {
68 | @Override
69 | public void onClick(View v) {
70 | // Intent intent = new Intent(context, EditDocumentActivity.class);
71 | // intent.putExtra(ExtraCode.GroupId, "");
72 | // context.startActivity(intent);
73 | }
74 | });
75 | home.setOnClickListener(new OnClickListener() {
76 | @Override
77 | public void onClick(View v) {
78 | back();
79 | }
80 | });
81 | voice.setOnClickListener(new OnClickListener() {
82 | @Override
83 | public void onClick(View v) {
84 |
85 | }
86 | });
87 | }
88 |
89 | private void back() {
90 | // 点击返回的时候,移除大悬浮窗,创建小悬浮窗
91 | MyWindowManager.removeBigWindow(context);
92 | MyWindowManager.createSmallWindow(context);
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/app/src/main/java/com/ks/control/FloatWindowService.java:
--------------------------------------------------------------------------------
1 | package com.ks.control;
2 |
3 | import android.app.ActivityManager;
4 | import android.app.Service;
5 | import android.content.Context;
6 | import android.content.Intent;
7 | import android.content.pm.PackageManager;
8 | import android.content.pm.ResolveInfo;
9 | import android.os.Handler;
10 | import android.os.IBinder;
11 |
12 | import java.util.ArrayList;
13 | import java.util.List;
14 | import java.util.Timer;
15 | import java.util.TimerTask;
16 |
17 | /**
18 | * Created by Admin on 2017/6/13 0013 09:34.
19 | * Author: kang
20 | * Email: kangsafe@163.com
21 | */
22 |
23 | public class FloatWindowService extends Service {
24 |
25 | /**
26 | * 用于在线程中创建或移除悬浮窗。
27 | */
28 | private Handler handler = new Handler();
29 |
30 | /**
31 | * 定时器,定时进行检测当前应该创建还是移除悬浮窗。
32 | */
33 | private Timer timer;
34 |
35 | @Override
36 | public IBinder onBind(Intent intent) {
37 | return null;
38 | }
39 |
40 | @Override
41 | public int onStartCommand(Intent intent, int flags, int startId) {
42 | // 开启定时器,每隔0.5秒刷新一次
43 | // if (timer == null) {
44 | // timer = new Timer();
45 | // timer.scheduleAtFixedRate(new RefreshTask(), 0, 500);
46 | // }
47 | MyWindowManager.createSmallWindow(getApplicationContext());
48 | return super.onStartCommand(intent, flags, startId);
49 | }
50 |
51 | @Override
52 | public void onDestroy() {
53 | super.onDestroy();
54 | // Service被终止的同时也停止定时器继续运行
55 | if (timer != null) {
56 | timer.cancel();
57 | timer = null;
58 | }
59 | }
60 |
61 | class RefreshTask extends TimerTask {
62 |
63 | @Override
64 | public void run() {
65 | // // 当前界面是桌面,且没有悬浮窗显示,则创建悬浮窗。
66 | // if (isHome() && !MyWindowManager.isWindowShowing()) {
67 | // handler.post(new Runnable() {
68 | // @Override
69 | // public void run() {
70 | // MyWindowManager.createSmallWindow(getApplicationContext());
71 | // }
72 | // });
73 | // }
74 | // // 当前界面不是桌面,且有悬浮窗显示,则移除悬浮窗。
75 | // else if (!isHome() && MyWindowManager.isWindowShowing()) {
76 | // handler.post(new Runnable() {
77 | // @Override
78 | // public void run() {
79 | // MyWindowManager.removeSmallWindow(getApplicationContext());
80 | // MyWindowManager.removeBigWindow(getApplicationContext());
81 | // }
82 | // });
83 | // }
84 | // // 当前界面是桌面,且有悬浮窗显示,则更新内存数据。
85 | // else if (isHome() && MyWindowManager.isWindowShowing()) {
86 | // handler.post(new Runnable() {
87 | // @Override
88 | // public void run() {
89 | // MyWindowManager.updateUsedPercent(getApplicationContext());
90 | // }
91 | // });
92 | // }
93 | }
94 |
95 | }
96 |
97 | /**
98 | * 判断当前界面是否是桌面
99 | */
100 | private boolean isHome() {
101 | ActivityManager mActivityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
102 | List rti = mActivityManager.getRunningTasks(1);
103 | return getHomes().contains(rti.get(0).topActivity.getPackageName());
104 | }
105 |
106 | /**
107 | * 获得属于桌面的应用的应用包名称
108 | *
109 | * @return 返回包含所有包名的字符串列表
110 | */
111 | private List getHomes() {
112 | List names = new ArrayList();
113 | PackageManager packageManager = this.getPackageManager();
114 | Intent intent = new Intent(Intent.ACTION_MAIN);
115 | intent.addCategory(Intent.CATEGORY_HOME);
116 | List resolveInfo = packageManager.queryIntentActivities(intent,
117 | PackageManager.MATCH_DEFAULT_ONLY);
118 | for (ResolveInfo ri : resolveInfo) {
119 | names.add(ri.activityInfo.packageName);
120 | }
121 | return names;
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/app/src/main/java/com/ks/control/FloatWindowSmallView.java:
--------------------------------------------------------------------------------
1 | package com.ks.control;
2 |
3 | import android.animation.AnimatorSet;
4 | import android.animation.ObjectAnimator;
5 | import android.app.AlertDialog;
6 | import android.content.Context;
7 | import android.content.DialogInterface;
8 | import android.view.KeyEvent;
9 | import android.view.LayoutInflater;
10 | import android.view.MotionEvent;
11 | import android.view.View;
12 | import android.view.WindowManager;
13 | import android.widget.ImageView;
14 | import android.widget.LinearLayout;
15 | import android.widget.Toast;
16 |
17 |
18 | import java.lang.reflect.Field;
19 | import java.util.ArrayList;
20 | import java.util.List;
21 |
22 | /**
23 | * Created by Admin on 2017/6/13 0013 09:36.
24 | * Author: kang
25 | * Email: kangsafe@163.com
26 | */
27 | public class FloatWindowSmallView extends LinearLayout implements View.OnClickListener {
28 |
29 | /**
30 | * 记录小悬浮窗的宽度
31 | */
32 | public static int viewWidth;
33 |
34 | /**
35 | * 记录小悬浮窗的高度
36 | */
37 | public static int viewHeight;
38 |
39 | /**
40 | * 记录系统状态栏的高度
41 | */
42 | private static int statusBarHeight;
43 | /**
44 | * 记录系统状态栏的高度
45 | */
46 | private static int statusBarWidth;
47 |
48 | /**
49 | * 用于更新小悬浮窗的位置
50 | */
51 | private WindowManager windowManager;
52 |
53 | /**
54 | * 小悬浮窗的参数
55 | */
56 | private WindowManager.LayoutParams mParams;
57 |
58 | /**
59 | * 记录当前手指位置在屏幕上的横坐标值
60 | */
61 | private float xInScreen;
62 |
63 | /**
64 | * 记录当前手指位置在屏幕上的纵坐标值
65 | */
66 | private float yInScreen;
67 |
68 | /**
69 | * 记录手指按下时在屏幕上的横坐标的值
70 | */
71 | private float xDownInScreen;
72 |
73 | /**
74 | * 记录手指按下时在屏幕上的纵坐标的值
75 | */
76 | private float yDownInScreen;
77 |
78 | /**
79 | * 记录手指按下时在小悬浮窗的View上的横坐标的值
80 | */
81 | private float xInView;
82 |
83 | /**
84 | * 记录手指按下时在小悬浮窗的View上的纵坐标的值
85 | */
86 | private float yInView;
87 |
88 |
89 | private int[] res = {};//{R.id.iv_open, R.id.iv_camera, R.id.iv_music, R.id.iv_place, R.id.iv_sleep, R.id.iv_thought, R.id.iv_with};
90 | private List imageViewList = new ArrayList();
91 | private boolean isOpen = false;//菜单是否打开状态
92 | private final int r = 400;//扇形半径
93 | private float angle;//按钮之间的夹角
94 | private final long intervalTime = 100; //菜单展开的时间间隔
95 |
96 | public FloatWindowSmallView(Context context) {
97 | super(context);
98 | windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
99 | LayoutInflater.from(context).inflate(R.layout.floating_window_small, this);
100 | View view = findViewById(R.id.small_window_layout);
101 | viewWidth = view.getLayoutParams().width;
102 | viewHeight = view.getLayoutParams().height;
103 | // TextView percentView = (TextView) findViewById(R.id.percent);
104 | // percentView.setText(MyWindowManager.getUsedPercentValue(context));
105 | // initImageView();
106 | // 计算按钮之间的夹角
107 | // angle = (float) Math.PI / (2 * (res.length - 1));
108 | statusBarWidth = windowManager.getDefaultDisplay().getWidth();
109 | }
110 |
111 | /**
112 | * 初始化View
113 | */
114 | private void initImageView() {
115 | ImageView imageView = null;
116 | for (int i = 0; i < res.length; i++) {
117 | imageView = (ImageView) findViewById(res[i]);
118 | imageView.setOnClickListener(this);
119 | imageViewList.add(imageView);
120 | }
121 | }
122 |
123 | /**
124 | * 点击事件
125 | */
126 | @Override
127 | public void onClick(View view) {
128 | switch (view.getId()) {
129 | // case R.id.iv_open:
130 | // if (isOpen) {
131 | // closeAnim();
132 | // } else {
133 | // startAnim();
134 | // }
135 | // break;
136 | default:
137 | // Toast.makeText(MyApplication.getContext(), "" + view.getId(), Toast.LENGTH_SHORT).show();
138 | break;
139 | }
140 | }
141 |
142 | /**
143 | * 展开菜单
144 | */
145 | private void startAnim() {
146 | ObjectAnimator animatorX = null;
147 | ObjectAnimator animatorY = null;
148 | float translationX;//横坐标偏移距离
149 | float translationY;//纵坐标偏移距离
150 | //左上角
151 | if (mParams.x == 0 && mParams.y == 0) {
152 | for (int i = 0; i < res.length; i++) {
153 | translationX = (float) (r * Math.sin(i * 90 / res.length));
154 | translationY = (float) (r * Math.cos(i * 90 / res.length));
155 | animatorX = ObjectAnimator.ofFloat(imageViewList.get(i), "translationX", 0F, translationX);
156 | animatorY = ObjectAnimator.ofFloat(imageViewList.get(i), "translationY", 0F, translationY);
157 | AnimatorSet animSet = new AnimatorSet();
158 | animSet.playTogether(animatorX, animatorY);
159 | animSet.setDuration(i * intervalTime);
160 | animSet.start();
161 | }
162 | }
163 | //上边
164 | if (mParams.x > r && mParams.x < statusBarWidth - r && mParams.y == 0) {
165 | for (int i = 0; i < res.length; i++) {
166 | translationX = mParams.x + (float) (r * Math.sin(i * 180 / res.length));
167 | translationY = (float) (r * Math.cos(i * 180 / res.length));
168 | animatorX = ObjectAnimator.ofFloat(imageViewList.get(i), "translationX", 0F, translationX);
169 | animatorY = ObjectAnimator.ofFloat(imageViewList.get(i), "translationY", 0F, translationY);
170 | AnimatorSet animSet = new AnimatorSet();
171 | animSet.playTogether(animatorX, animatorY);
172 | animSet.setDuration(i * intervalTime);
173 | animSet.start();
174 | }
175 | }
176 | //右上角
177 | if (mParams.x == statusBarWidth && mParams.y == 0) {
178 | for (int i = 0; i < res.length; i++) {
179 | translationX = statusBarWidth - (float) (r * Math.sin(i * 90 / res.length));
180 | translationY = (float) (r * Math.cos(i * 90 / res.length));
181 | animatorX = ObjectAnimator.ofFloat(imageViewList.get(i), "translationX", 0F, translationX);
182 | animatorY = ObjectAnimator.ofFloat(imageViewList.get(i), "translationY", 0F, translationY);
183 | AnimatorSet animSet = new AnimatorSet();
184 | animSet.playTogether(animatorX, animatorY);
185 | animSet.setDuration(i * intervalTime);
186 | animSet.start();
187 | }
188 | }
189 | //左边
190 | if (mParams.x == 0 && mParams.y > r && mParams.y < statusBarHeight - r) {
191 | for (int i = 0; i < res.length; i++) {
192 | translationX = (float) (r * Math.sin(i * 180 / res.length));
193 | translationY = mParams.y + (float) (r * Math.cos(i * 180 / res.length));
194 | animatorX = ObjectAnimator.ofFloat(imageViewList.get(i), "translationX", 0F, translationX);
195 | animatorY = ObjectAnimator.ofFloat(imageViewList.get(i), "translationY", 0F, translationY);
196 | AnimatorSet animSet = new AnimatorSet();
197 | animSet.playTogether(animatorX, animatorY);
198 | animSet.setDuration(i * intervalTime);
199 | animSet.start();
200 | }
201 | }
202 | //右边
203 | if (mParams.x == statusBarWidth && mParams.y > r && mParams.y < statusBarHeight - r) {
204 | for (int i = 0; i < res.length; i++) {
205 | translationX = statusBarWidth - (float) (r * Math.sin(i * 180 / res.length));
206 | translationY = mParams.y + (float) (r * Math.cos(i * 180 / res.length));
207 | animatorX = ObjectAnimator.ofFloat(imageViewList.get(i), "translationX", 0F, translationX);
208 | animatorY = ObjectAnimator.ofFloat(imageViewList.get(i), "translationY", 0F, translationY);
209 | AnimatorSet animSet = new AnimatorSet();
210 | animSet.playTogether(animatorX, animatorY);
211 | animSet.setDuration(i * intervalTime);
212 | animSet.start();
213 | }
214 | }
215 | //左下角
216 | if (mParams.x == 0 && mParams.y == statusBarHeight) {
217 | for (int i = 0; i < res.length; i++) {
218 | translationX = (float) (r * Math.sin(i * 90 / res.length));
219 | translationY = mParams.y - (float) (r * Math.cos(i * 90 / res.length));
220 | animatorX = ObjectAnimator.ofFloat(imageViewList.get(i), "translationX", 0F, translationX);
221 | animatorY = ObjectAnimator.ofFloat(imageViewList.get(i), "translationY", 0F, translationY);
222 | AnimatorSet animSet = new AnimatorSet();
223 | animSet.playTogether(animatorX, animatorY);
224 | animSet.setDuration(i * intervalTime);
225 | animSet.start();
226 | }
227 | }
228 | //下边
229 | if (mParams.x > r && mParams.x < statusBarWidth - r && mParams.y == statusBarHeight) {
230 | for (int i = 0; i < res.length; i++) {
231 | translationX = mParams.x + (float) (r * Math.sin(i * 180 / res.length));
232 | translationY = statusBarHeight - (float) (r * Math.cos(i * 180 / res.length));
233 | animatorX = ObjectAnimator.ofFloat(imageViewList.get(i), "translationX", 0F, translationX);
234 | animatorY = ObjectAnimator.ofFloat(imageViewList.get(i), "translationY", 0F, translationY);
235 | AnimatorSet animSet = new AnimatorSet();
236 | animSet.playTogether(animatorX, animatorY);
237 | animSet.setDuration(i * intervalTime);
238 | animSet.start();
239 | }
240 | }
241 | //右下角
242 | if (mParams.x == statusBarWidth && mParams.y == statusBarHeight) {
243 | for (int i = 0; i < res.length; i++) {
244 | translationX = mParams.x - (float) (r * Math.sin(i * 90 / res.length));
245 | translationY = statusBarHeight - (float) (r * Math.cos(i * 90 / res.length));
246 | animatorX = ObjectAnimator.ofFloat(imageViewList.get(i), "translationX", 0F, translationX);
247 | animatorY = ObjectAnimator.ofFloat(imageViewList.get(i), "translationY", 0F, translationY);
248 | AnimatorSet animSet = new AnimatorSet();
249 | animSet.playTogether(animatorX, animatorY);
250 | animSet.setDuration(i * intervalTime);
251 | animSet.start();
252 | }
253 | }
254 | // for (int i = 1; i < res.length; i++) {
255 | // translationX = (float) (r * Math.sin(i * angle));
256 | // translationY = (float) (r * Math.cos(i * angle));
257 | // animatorX = ObjectAnimator.ofFloat(imageViewList.get(i), "translationX", 0F, translationX);
258 | // animatorY = ObjectAnimator.ofFloat(imageViewList.get(i), "translationY", 0F, translationY);
259 | // AnimatorSet animSet = new AnimatorSet();
260 | // animSet.playTogether(animatorX, animatorY);
261 | // animSet.setDuration(i * intervalTime);
262 | // animSet.start();
263 | // }
264 | isOpen = true;
265 | }
266 |
267 | /**
268 | * 关闭菜单
269 | */
270 | private void closeAnim() {
271 | ObjectAnimator animatorX = null;
272 | ObjectAnimator animatorY = null;
273 | float translationX;//横坐标偏移距离
274 | float translationY;//纵坐标偏移距离
275 | for (int i = res.length - 1; i > 0; i--) {
276 | translationX = (float) (r * Math.sin(i * angle));
277 | translationY = (float) (r * Math.cos(i * angle));
278 | animatorX = ObjectAnimator.ofFloat(imageViewList.get(i), "translationX", translationX, 0F);
279 | animatorY = ObjectAnimator.ofFloat(imageViewList.get(i), "translationY", translationY, 0F);
280 | AnimatorSet animSet = new AnimatorSet();
281 | animSet.playTogether(animatorX, animatorY);
282 | animSet.setDuration((res.length - i) * intervalTime);
283 | animSet.start();
284 | }
285 | isOpen = false;
286 | }
287 |
288 | /**
289 | * 监听是否按下返回键
290 | */
291 | public boolean onKeyDown(int keyCode, KeyEvent event) {
292 | //如果按下返回键,执行退出操作
293 | if (keyCode == KeyEvent.KEYCODE_BACK) {
294 | showDialog();
295 | }
296 | return super.onKeyDown(keyCode, event);
297 | }
298 |
299 | /**
300 | * 退出弹框
301 | */
302 | private void showDialog() {
303 | new AlertDialog.Builder(getContext())
304 | .setTitle("退出")
305 | .setMessage("要退出么?")
306 | .setNegativeButton("退出", new DialogInterface.OnClickListener() {
307 | @Override
308 | public void onClick(DialogInterface arg0, int arg1) {
309 | // finish();
310 | }
311 | })
312 | .setPositiveButton("返回", new DialogInterface.OnClickListener() {
313 | @Override
314 | public void onClick(DialogInterface arg0, int arg1) {
315 |
316 | }
317 | }).show();
318 | }
319 |
320 | @Override
321 | public boolean onTouchEvent(MotionEvent event) {
322 | switch (event.getAction()) {
323 | case MotionEvent.ACTION_DOWN:
324 | // 手指按下时记录必要数据,纵坐标的值都需要减去状态栏高度
325 | xInView = event.getX();
326 | yInView = event.getY();
327 | xDownInScreen = event.getRawX();
328 | yDownInScreen = event.getRawY() - getStatusBarHeight();
329 | xInScreen = event.getRawX();
330 | yInScreen = event.getRawY() - getStatusBarHeight();
331 | break;
332 | case MotionEvent.ACTION_MOVE:
333 | xInScreen = event.getRawX();
334 | yInScreen = event.getRawY() - getStatusBarHeight();
335 | // 手指移动的时候更新小悬浮窗的位置
336 | updateViewPosition();
337 | break;
338 | case MotionEvent.ACTION_UP:
339 | // 如果手指离开屏幕时,xDownInScreen和xInScreen相等,且yDownInScreen和yInScreen相等,则视为触发了单击事件。
340 | if (Math.abs(xDownInScreen - xInScreen) < 5 && Math.abs(yDownInScreen - yInScreen) < 5) {
341 | openBigWindow();
342 | } else {
343 | if ((xInScreen - xInView) > statusBarWidth / 2) {
344 | mParams.x = statusBarWidth;
345 | mParams.y = (int) (yInScreen - yInView);
346 | } else {
347 | mParams.x = 0;
348 | mParams.y = (int) (yInScreen - yInView);
349 | }
350 | windowManager.updateViewLayout(this, mParams);
351 | }
352 | break;
353 | default:
354 | break;
355 | }
356 | return true;
357 | }
358 |
359 | /**
360 | * 将小悬浮窗的参数传入,用于更新小悬浮窗的位置。
361 | *
362 | * @param params 小悬浮窗的参数
363 | */
364 | public void setParams(WindowManager.LayoutParams params) {
365 | mParams = params;
366 | }
367 |
368 | /**
369 | * 更新小悬浮窗在屏幕中的位置。
370 | */
371 | private void updateViewPosition() {
372 | // if (xInScreen > getStatusBarWidth() / 2) {
373 | // mParams.x = getStatusBarWidth();
374 | // mParams.y = (int) (yInScreen - yInView);
375 | // } else {
376 | // mParams.x = 0;
377 | // mParams.y = (int) (yInScreen - yInView);
378 | // }
379 | mParams.x = (int) (xInScreen - xInView);
380 | mParams.y = (int) (yInScreen - yInView);
381 | windowManager.updateViewLayout(this, mParams);
382 | }
383 |
384 | /**
385 | * 打开大悬浮窗,同时关闭小悬浮窗。
386 | */
387 | private void openBigWindow() {
388 | MyWindowManager.createBigWindow(getContext());
389 | MyWindowManager.removeSmallWindow(getContext());
390 | }
391 |
392 | /**
393 | * 用于获取状态栏的高度。
394 | *
395 | * @return 返回状态栏高度的像素值。
396 | */
397 | private int getStatusBarHeight() {
398 | if (statusBarHeight == 0) {
399 | try {
400 | Class> c = Class.forName("com.android.internal.R$dimen");
401 | Object o = c.newInstance();
402 | Field field = c.getField("status_bar_height");
403 | int x = (Integer) field.get(o);
404 | statusBarHeight = getResources().getDimensionPixelSize(x);
405 | } catch (Exception e) {
406 | e.printStackTrace();
407 | }
408 | }
409 | return statusBarHeight;
410 | }
411 |
412 | // private void initFloatingActionsMenu(View view) {
413 | // // 添加 右下角的白色+号按钮
414 | // final ImageView fabIcon = new ImageView(getContext());
415 | // fabIcon.setImageDrawable(view.getContext().getResources().getDrawable(R.drawable.ic_action_more));
416 | // final FloatingActionButton fabButton = new FloatingActionButton.Builder(getActivity())
417 | // .setContentView(fabIcon)
418 | // .setPosition(FloatingActionButton.POSITION_BOTTOM_LEFT)
419 | // .build();
420 | //
421 | // SubActionButton.Builder rLSubBuilder = new SubActionButton.Builder(getActivity());
422 | //
423 | // ImageView imageViewQuit = new ImageView(getContext());
424 | // ImageView imageViewTool = new ImageView(getContext());
425 | // ImageView imageViewPalette = new ImageView(getContext());
426 | // ImageView imageViewCamera = new ImageView(getContext());
427 | // imageViewQuit.setImageDrawable(view.getContext().getResources().getDrawable(R.drawable.icon_fab_take_photo));
428 | // imageViewTool.setImageDrawable(view.getContext().getResources().getDrawable(R.drawable.icon_fab_new_note));
429 | // imageViewPalette.setImageDrawable(view.getContext().getResources().getDrawable(R.drawable.icon_fab_markdown));
430 | // imageViewCamera.setImageDrawable(view.getContext().getResources().getDrawable(R.drawable.icon_fab_finger_paint));
431 | //
432 | // SubActionButton buttonQuit = rLSubBuilder.setContentView(imageViewQuit).build();
433 | // SubActionButton buttonPalette = rLSubBuilder.setContentView(imageViewPalette).build();
434 | // SubActionButton buttonTool = rLSubBuilder.setContentView(imageViewTool).build();
435 | // SubActionButton buttonCamera = rLSubBuilder.setContentView(imageViewCamera).build();
436 | //
437 | // // Build the menu with default options: light theme, 90 degrees, 72dp
438 | // // radius.
439 | // // Set 4 default SubActionButtons
440 | // // FloatingActionMenu通过attachTo(fabButton)附着到FloatingActionButton
441 | // final FloatingActionMenu buttonToolMenu = new FloatingActionMenu.Builder(getActivity())
442 | // .addSubActionView(buttonPalette)
443 | // .addSubActionView(buttonCamera)
444 | // .addSubActionView(buttonTool)
445 | // .addSubActionView(buttonQuit)
446 | // .setStartAngle(0)
447 | // .setEndAngle(-90)
448 | // .attachTo(fabButton)
449 | // .build();
450 | //
451 | // // Listen menu open and close events to animate the button content view
452 | // buttonToolMenu.setStateChangeListener(new FloatingActionMenu.MenuStateChangeListener() {
453 | // @Override
454 | // public void onMenuOpened(FloatingActionMenu menu) {
455 | // // 增加按钮中的+号图标顺时针旋转45度
456 | // // Rotate the icon of fabButton 45 degrees clockwise
457 | // fabIcon.setRotation(0);
458 | // PropertyValuesHolder pvhR = PropertyValuesHolder.ofFloat(View.ROTATION, 45);
459 | // ObjectAnimator animation = ObjectAnimator.ofPropertyValuesHolder(fabIcon, pvhR);
460 | // animation.start();
461 | // }
462 | //
463 | // @Override
464 | // public void onMenuClosed(FloatingActionMenu menu) {
465 | // // 增加按钮中的+号图标逆时针旋转45度
466 | // // Rotate the icon of fabButton 45 degrees
467 | // // counter-clockwise
468 | // fabIcon.setRotation(45);
469 | // PropertyValuesHolder pvhR = PropertyValuesHolder.ofFloat(View.ROTATION, 0);
470 | // ObjectAnimator animation = ObjectAnimator.ofPropertyValuesHolder(fabIcon, pvhR);
471 | // animation.start();
472 | // }
473 | // });
474 | //
475 | // RxView.clicks(buttonQuit)
476 | // .throttleFirst(1, TimeUnit.SECONDS)
477 | // .compose(this.bindUntilEvent(FragmentEvent.DESTROY))
478 | // .subscribe(v -> {
479 | // Voip.getInstance().hangUpCall(callId);
480 | // finishActivity();
481 | // });
482 | //
483 | // RxView.clicks(buttonPalette)
484 | // .throttleFirst(1, TimeUnit.SECONDS)
485 | // .compose(this.bindUntilEvent(FragmentEvent.DESTROY))
486 | // .subscribe(v -> {
487 | // buttonToolMenu.close(true);
488 | //// buttonToolMenu.collapse();
489 | // dialogPalette.show();
490 | // });
491 | //
492 | // RxView.clicks(buttonCamera)
493 | // .throttleFirst(1, TimeUnit.SECONDS)
494 | // .compose(this.bindUntilEvent(FragmentEvent.DESTROY))
495 | // .subscribe(v -> {
496 | // buttonToolMenu.close(true);
497 | //// buttonToolMenu.collapse();
498 | // dialogSelectImage.show();
499 | // });
500 | // }
501 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/ks/control/HomeKeyEventBroadCastReceiver.java:
--------------------------------------------------------------------------------
1 | package com.ks.control;
2 |
3 | import android.content.BroadcastReceiver;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.util.Log;
7 |
8 | /**
9 | * Created by Administrator on 2017/6/15.
10 | */
11 |
12 | public class HomeKeyEventBroadCastReceiver extends BroadcastReceiver {
13 |
14 | static final String SYSTEM_REASON = "reason";
15 | static final String SYSTEM_HOME_KEY = "homekey";//home key
16 | static final String SYSTEM_RECENT_APPS = "recentapps";//long home key
17 |
18 | @Override
19 | public void onReceive(Context context, Intent intent) {
20 | String action = intent.getAction();
21 | Log.i("KeyEvent", intent.getAction());
22 | if (action.equals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) {
23 | String reason = intent.getStringExtra(SYSTEM_REASON);
24 | if (reason != null) {
25 | if (reason.equals(SYSTEM_HOME_KEY)) {
26 | // home key处理点
27 | } else if (reason.equals(SYSTEM_RECENT_APPS)) {
28 | // long home key处理点 }
29 | }
30 | }
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/app/src/main/java/com/ks/control/HomeWatcherReceiver.java:
--------------------------------------------------------------------------------
1 | package com.ks.control;
2 |
3 | import android.content.BroadcastReceiver;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.hardware.Camera;
7 | import android.os.Handler;
8 | import android.util.Log;
9 |
10 | /**
11 | * Created by Administrator on 2017/6/15.
12 | */
13 |
14 | public class HomeWatcherReceiver extends BroadcastReceiver {
15 | private static final String LOG_TAG = "HomeReceiver";
16 | private static final String SYSTEM_DIALOG_REASON_KEY = "reason";
17 | private static final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
18 | private static final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
19 | private static final String SYSTEM_DIALOG_REASON_LOCK = "lock";
20 | private static final String SYSTEM_DIALOG_REASON_ASSIST = "assist";
21 | private static final String SYSTEM_DIALOG_REASON_VOICE = "voiceinteraction";
22 | private long lastTime = 0;
23 | private int num = 1;
24 | private Handler handler;
25 | private boolean status = false;
26 | private FlashLightManager flashLightManager;
27 |
28 | @Override
29 | public void onReceive(final Context context, Intent intent) {
30 | if (flashLightManager == null) {
31 | flashLightManager = new FlashLightManager(context);
32 | flashLightManager.init();
33 | }
34 | String action = intent.getAction();
35 | Log.i(LOG_TAG, "onReceive: action: " + action);
36 | if (action.equals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) {
37 | // android.intent.action.CLOSE_SYSTEM_DIALOGS
38 | String reason = intent.getStringExtra(SYSTEM_DIALOG_REASON_KEY);
39 | Log.i(LOG_TAG, "reason: " + reason);
40 |
41 | if (SYSTEM_DIALOG_REASON_HOME_KEY.equals(reason)) {
42 | // 短按Home键
43 | Log.i(LOG_TAG, "homekey" + System.currentTimeMillis() + ":" + lastTime);
44 | //双击
45 | if ((System.currentTimeMillis() - lastTime) < 500) {
46 | num++;
47 | Log.i(LOG_TAG, "homekey点击次数" + num);
48 | } else {
49 | lastTime = System.currentTimeMillis();
50 | Log.i(LOG_TAG, "homekey开始点击");
51 | num = 1;
52 | if (handler == null) {
53 | handler = new Handler();
54 | handler.postDelayed(new Runnable() {
55 | @Override
56 | public void run() {
57 | if (num == 1) {
58 | Log.i(LOG_TAG, "单击");
59 | MyWindowManager.removeCtrlCenterBigWindow(context);
60 | } else if (num >= 2) {
61 | Log.i(LOG_TAG, "双击");
62 | MyWindowManager.createCtrlCenterBigWindow(context);
63 | } else {
64 | Log.i(LOG_TAG, "三连击");
65 | }
66 | lastTime = System.currentTimeMillis();
67 | num = 1;
68 | handler = null;
69 | }
70 | }, 500);
71 | }
72 | }
73 | } else if (SYSTEM_DIALOG_REASON_RECENT_APPS.equals(reason)) {
74 | // 长按Home键 或者 activity切换键
75 | Log.i(LOG_TAG, "long press home key or activity switch");
76 | doLongPress();
77 | } else if (SYSTEM_DIALOG_REASON_LOCK.equals(reason)) {
78 | // 锁屏
79 | Log.i(LOG_TAG, "lock");
80 | } else if (SYSTEM_DIALOG_REASON_ASSIST.equals(reason)) {
81 | // samsung 长按Home键
82 | Log.i(LOG_TAG, "assist");
83 | doLongPress();
84 | } else if (SYSTEM_DIALOG_REASON_VOICE.equals(reason)) {
85 | //google nuex 6p 长按Home键
86 | doLongPress();
87 | }
88 | }
89 | }
90 |
91 | private void doLongPress() {
92 | if (!status) {
93 | status = true;
94 | flashLightManager.turnOn();
95 | } else {
96 | status = false;
97 | flashLightManager.turnOff();
98 | }
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/app/src/main/java/com/ks/control/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.ks.control;
2 |
3 | import android.content.Context;
4 | import android.content.DialogInterface;
5 | import android.content.Intent;
6 | import android.content.IntentFilter;
7 | import android.os.Bundle;
8 | import android.support.v7.app.AlertDialog;
9 | import android.support.v7.app.AppCompatActivity;
10 | import android.util.Log;
11 | import android.view.View;
12 | import android.widget.Button;
13 |
14 | public class MainActivity extends AppCompatActivity {
15 | Button startBtn;
16 | Button powerOffBtn;
17 |
18 | @Override
19 | protected void onCreate(Bundle savedInstanceState) {
20 | super.onCreate(savedInstanceState);
21 | setContentView(R.layout.activity_main);
22 | startBtn = (Button) findViewById(R.id.vstart);
23 | startBtn.setOnClickListener(new View.OnClickListener() {
24 | @Override
25 | public void onClick(View view) {
26 | MyWindowManager.createCtrlCenterSmallWindow(getApplicationContext());
27 | }
28 | });
29 | powerOffBtn = (Button) findViewById(R.id.vpoweroff);
30 | powerOffBtn.setOnClickListener(new View.OnClickListener() {
31 | @Override
32 | public void onClick(View v) {
33 | AlarmPowerManager.bcShutdown(getApplicationContext());
34 | }
35 | });
36 | findViewById(R.id.vpanel).setOnClickListener(new View.OnClickListener() {
37 | @Override
38 | public void onClick(View v) {
39 | showTips("操作方式与问题", "任意时刻底部上划即弹出面板,屏幕外亦可" +
40 | "你也可以设置左、右边缘轻触启动面板;" +
41 | "如未弹出,请尝试调大触摸感知区域;" +
42 | "确认系统『设置-应用-权限管理』已开启『悬浮窗』等权限", "我知道了",
43 | new DialogInterface.OnClickListener() {
44 | @Override
45 | public void onClick(DialogInterface dialog, int which) {
46 | dialog.dismiss();
47 | }
48 | });
49 | }
50 | });
51 | findViewById(R.id.vprotect).setOnClickListener(new View.OnClickListener() {
52 | @Override
53 | public void onClick(View v) {
54 | showTips("保护应用不被系统停止", "本引用仅有700K左右,内存消耗也极少;" +
55 | "不会后台持续工作,不随意消耗用户电量;不会后台连接网路,不任意消耗用户流量;" +
56 | "未使用黑科技保活,你来决定让它随时服务。", "查看保护方法", new DialogInterface.OnClickListener() {
57 | @Override
58 | public void onClick(DialogInterface dialog, int which) {
59 | dialog.dismiss();
60 | Intent intent = new Intent(getApplicationContext(), WebActivity.class);
61 | intent.putExtra("url", "https://control.litesuits.com/");
62 | getApplicationContext().startActivity(intent);
63 | }
64 | });
65 | }
66 | });
67 | findViewById(R.id.vsetting).setOnClickListener(new View.OnClickListener() {
68 | @Override
69 | public void onClick(View v) {
70 | getApplicationContext().startActivity(new Intent(getApplicationContext(), SettingActivity.class));
71 | }
72 | });
73 | }
74 |
75 | HomeKeyEventBroadCastReceiver homeKeyEventBroadCastReceiver;
76 |
77 | @Override
78 | protected void onStart() {
79 | super.onStart();
80 | // homeKeyEventBroadCastReceiver = new HomeKeyEventBroadCastReceiver();
81 | // registerReceiver(homeKeyEventBroadCastReceiver, new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
82 | }
83 |
84 | @Override
85 | protected void onStop() {
86 | super.onStop();
87 | }
88 |
89 | private static HomeWatcherReceiver mHomeKeyReceiver = null;
90 |
91 | private static void registerHomeKeyReceiver(Context context) {
92 | Log.i("LOG_TAG", "registerHomeKeyReceiver");
93 | mHomeKeyReceiver = new HomeWatcherReceiver();
94 | final IntentFilter homeFilter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
95 |
96 | context.registerReceiver(mHomeKeyReceiver, homeFilter);
97 | }
98 |
99 | private static void unregisterHomeKeyReceiver(Context context) {
100 | Log.i("LOG_TAG", "unregisterHomeKeyReceiver");
101 | if (null != mHomeKeyReceiver) {
102 | context.unregisterReceiver(mHomeKeyReceiver);
103 | }
104 | }
105 |
106 | AlertDialog dialog;
107 |
108 | private void showTips(String title, String msg, String ptitle, DialogInterface.OnClickListener listener) {
109 | if (dialog == null) {
110 | dialog = new AlertDialog.Builder(this).create();
111 | }
112 | dialog.setTitle(title);
113 | dialog.setMessage(msg);
114 | dialog.setButton(AlertDialog.BUTTON_POSITIVE, ptitle, listener);
115 | dialog.show();
116 | }
117 |
118 | @Override
119 | protected void onResume() {
120 | super.onResume();
121 | // registerHomeKeyReceiver(this);
122 | }
123 |
124 | @Override
125 | protected void onPause() {
126 | // unregisterHomeKeyReceiver(this);
127 | super.onPause();
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/app/src/main/java/com/ks/control/MyWindowManager.java:
--------------------------------------------------------------------------------
1 | package com.ks.control;
2 |
3 | import android.app.ActivityManager;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.graphics.PixelFormat;
7 | import android.view.Gravity;
8 | import android.view.WindowManager;
9 |
10 | import java.io.BufferedReader;
11 | import java.io.FileReader;
12 | import java.io.IOException;
13 | import java.util.List;
14 |
15 | import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
16 |
17 | /**
18 | * Created by Admin on 2017/6/13 0013 09:38.
19 | * Author: kang
20 | * Email: kangsafe@163.com
21 | */
22 |
23 | public class MyWindowManager {
24 |
25 | /**
26 | * 小悬浮窗View的实例
27 | */
28 | private static FloatWindowSmallView smallWindow;
29 | /**
30 | * 大悬浮窗View的实例
31 | */
32 | private static FloatWindowBigView bigWindow;
33 |
34 | /**
35 | * 小控制中心
36 | */
37 | private static CtrlCenterWindowSmallView ctrlCenterWindowSmallView;
38 | /**
39 | * 大控制中心
40 | */
41 | private static CtrlCenterWindowBigView ctrlCenterWindowBigView;
42 |
43 | /**
44 | * 小悬浮窗View的参数
45 | */
46 | private static WindowManager.LayoutParams smallWindowParams;
47 | /**
48 | * 大悬浮窗View的参数
49 | */
50 | private static WindowManager.LayoutParams bigWindowParams;
51 |
52 | /**
53 | * 小控制中心View的参数
54 | */
55 | private static WindowManager.LayoutParams ctrlCenterWindowSmallParams;
56 | /**
57 | * 大控制中心View参数
58 | */
59 | private static WindowManager.LayoutParams ctrlCenterWindowBigParams;
60 |
61 | /**
62 | * 用于控制在屏幕上添加或移除悬浮窗
63 | */
64 | private static WindowManager mWindowManager;
65 |
66 | /**
67 | * 用于获取手机可用内存
68 | */
69 | private static ActivityManager mActivityManager;
70 |
71 | /**
72 | * 用来判断服务是否运行.
73 | *
74 | * @param mContext
75 | * @param className 判断的服务名字
76 | * @return true 在运行 false 不在运行
77 | */
78 | public static boolean isServiceRunning(Context mContext, String className) {
79 | boolean isRunning = false;
80 | ActivityManager activityManager = (ActivityManager)
81 | mContext.getSystemService(Context.ACTIVITY_SERVICE);
82 | List serviceList
83 | = activityManager.getRunningServices(30);
84 | if (!(serviceList.size() > 0)) {
85 | return false;
86 | }
87 | for (int i = 0; i < serviceList.size(); i++) {
88 | if (serviceList.get(i).service.getClassName().equals(className) == true) {
89 | isRunning = true;
90 | break;
91 | }
92 | }
93 | return isRunning;
94 | }
95 |
96 | public static boolean isServiceRunning(Context mContext, Class> cla) {
97 | return isServiceRunning(mContext, cla.getName());
98 | }
99 |
100 | /**
101 | * 启动悬浮服务
102 | */
103 | public static void startFloatingServiceByConfig() {
104 | try {
105 | // if (SPHelper.getBoolean(SPConst.FLOATING, false)) {
106 | // MyWindowManager.startFloatingService();
107 | // }
108 | } catch (Exception e) {
109 | e.printStackTrace();
110 | }
111 | }
112 |
113 | /**
114 | * 启动悬浮服务
115 | */
116 | public static void startFloatingService() {
117 | try {
118 | // if (!isServiceRunning(MyApplication.getContext(), "com.zd.note.floating.FloatWindowService")) {
119 | // Intent intent = new Intent(MyApplication.getContext(), FloatWindowService.class);
120 | // MyApplication.getContext().startService(intent);
121 | // SPHelper.putBoolean(SPConst.FLOATING, true);
122 | // }
123 | } catch (Exception e) {
124 | e.printStackTrace();
125 | }
126 | }
127 |
128 | /**
129 | * 停止悬浮服务
130 | */
131 | public static void stopFloatingService() {
132 | try {
133 | // if (isServiceRunning(MyApplication.getContext(), "com.zd.note.floating.FloatWindowService")) {
134 | // Intent intent = new Intent(MyApplication.getContext(), FloatWindowService.class);
135 | // MyApplication.getContext().stopService(intent);
136 | // }
137 | // SPHelper.putBoolean(SPConst.FLOATING, false);
138 | // removeSmallWindow(MyApplication.getContext());
139 | } catch (Exception e) {
140 | e.printStackTrace();
141 | }
142 | }
143 |
144 | /**
145 | * 启动控制中心服务
146 | */
147 | public static void startCtrlCenterWindowServiceByConfig() {
148 | try {
149 | // if (SPHelper.getBoolean(SPConst.CTRLCENTER, false)) {
150 | // startCtrlCenterWindowService();
151 | // }
152 | } catch (Exception e) {
153 | e.printStackTrace();
154 | }
155 | }
156 |
157 | /**
158 | * 启动控制中心服务
159 | */
160 | public static void startCtrlCenterWindowService() {
161 | try {
162 | // if (!isServiceRunning(MyApplication.getContext(), "com.zd.note.floating.CtrlCenterWindowService")) {
163 | // Intent intent = new Intent(MyApplication.getContext(), CtrlCenterWindowService.class);
164 | // MyApplication.getContext().startService(intent);
165 | // SPHelper.putBoolean(SPConst.CTRLCENTER, true);
166 | // }
167 | } catch (Exception e) {
168 | e.printStackTrace();
169 | }
170 | }
171 |
172 | /**
173 | * 启动控制中心
174 | */
175 | public static void stopCtrlCenterWindowService() {
176 | try {
177 | // if (isServiceRunning(MyApplication.getContext(), "com.zd.note.floating.CtrlCenterWindowService")) {
178 | // Intent intent = new Intent(MyApplication.getContext(), CtrlCenterWindowService.class);
179 | // MyApplication.getContext().stopService(intent);
180 | // }
181 | // SPHelper.putBoolean(SPConst.CTRLCENTER, false);
182 | // removeCtrlCenterSmallWindow(MyApplication.getContext());
183 | } catch (Exception e) {
184 | e.printStackTrace();
185 | }
186 | }
187 |
188 | /**
189 | * 创建一个小悬浮窗。初始位置为屏幕的右部中间位置。
190 | *
191 | * @param context 必须为应用程序的Context.
192 | */
193 | public static void createSmallWindow(Context context) {
194 | WindowManager windowManager = getWindowManager(context);
195 | int screenWidth = windowManager.getDefaultDisplay().getWidth();
196 | int screenHeight = windowManager.getDefaultDisplay().getHeight();
197 | if (smallWindow == null) {
198 | smallWindow = new FloatWindowSmallView(context);
199 | if (smallWindowParams == null) {
200 | smallWindowParams = new WindowManager.LayoutParams();
201 | smallWindowParams.type = WindowManager.LayoutParams.TYPE_PHONE;
202 | smallWindowParams.format = PixelFormat.RGBA_8888;
203 | smallWindowParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
204 | | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
205 | smallWindowParams.gravity = Gravity.LEFT | Gravity.TOP;
206 | smallWindowParams.width = FloatWindowSmallView.viewWidth;
207 | smallWindowParams.height = FloatWindowSmallView.viewHeight;
208 | smallWindowParams.x = screenWidth;
209 | smallWindowParams.y = screenHeight / 2;
210 | }
211 | smallWindow.setParams(smallWindowParams);
212 | windowManager.addView(smallWindow, smallWindowParams);
213 | }
214 | }
215 |
216 | /**
217 | * 创建一个小悬浮窗。初始位置为屏幕的右部中间位置。
218 | *
219 | * @param context 必须为应用程序的Context.
220 | */
221 | public static void createCtrlCenterSmallWindow(Context context) {
222 | WindowManager windowManager = getWindowManager(context);
223 | if (ctrlCenterWindowSmallView == null) {
224 | ctrlCenterWindowSmallView = new CtrlCenterWindowSmallView(context);
225 | if (ctrlCenterWindowSmallParams == null) {
226 | ctrlCenterWindowSmallParams = new WindowManager.LayoutParams();
227 | ctrlCenterWindowSmallParams.type = WindowManager.LayoutParams.TYPE_PHONE;
228 | ctrlCenterWindowSmallParams.format = PixelFormat.TRANSLUCENT;
229 | ctrlCenterWindowSmallParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
230 | | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
231 | ctrlCenterWindowSmallParams.gravity = Gravity.BOTTOM;
232 | ctrlCenterWindowSmallParams.width = WindowManager.LayoutParams.MATCH_PARENT;
233 | ctrlCenterWindowSmallParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
234 | ctrlCenterWindowSmallParams.x = 0;
235 | ctrlCenterWindowSmallParams.y = 0;
236 | }
237 | ctrlCenterWindowSmallView.setParams(ctrlCenterWindowSmallParams);
238 | windowManager.addView(ctrlCenterWindowSmallView, ctrlCenterWindowSmallParams);
239 | }
240 | }
241 |
242 | /**
243 | * 创建一个小悬浮窗。初始位置为屏幕的右部中间位置。
244 | *
245 | * @param context 必须为应用程序的Context.
246 | */
247 | public static void createCtrlCenterBigWindow(Context context) {
248 | WindowManager windowManager = getWindowManager(context);
249 | if (ctrlCenterWindowBigView == null) {
250 | ctrlCenterWindowBigView = new CtrlCenterWindowBigView(context);
251 | if (ctrlCenterWindowBigParams == null) {
252 | ctrlCenterWindowBigParams = new WindowManager.LayoutParams();
253 | ctrlCenterWindowBigParams.type = WindowManager.LayoutParams.TYPE_PHONE;
254 | ctrlCenterWindowBigParams.format = PixelFormat.TRANSLUCENT;
255 | ctrlCenterWindowBigParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL|FLAG_WATCH_OUTSIDE_TOUCH;
256 | ctrlCenterWindowBigParams.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
257 | ctrlCenterWindowBigParams.width = (int) (windowManager.getDefaultDisplay().getWidth() * 0.95);//WindowManager.LayoutParams.MATCH_PARENT;
258 | ctrlCenterWindowBigParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
259 | ctrlCenterWindowBigParams.x = 0;
260 | ctrlCenterWindowBigParams.y = 50;
261 | }
262 | windowManager.addView(ctrlCenterWindowBigView, ctrlCenterWindowBigParams);
263 | }
264 | }
265 |
266 |
267 | /**
268 | * 将小悬浮窗从屏幕上移除。
269 | *
270 | * @param context 必须为应用程序的Context.
271 | */
272 | public static void removeSmallWindow(Context context) {
273 | if (smallWindow != null) {
274 | WindowManager windowManager = getWindowManager(context);
275 | windowManager.removeView(smallWindow);
276 | smallWindow = null;
277 | }
278 | }
279 |
280 | /**
281 | * 将小悬浮窗从屏幕上移除。
282 | *
283 | * @param context 必须为应用程序的Context.
284 | */
285 | public static void removeCtrlCenterSmallWindow(Context context) {
286 | if (ctrlCenterWindowSmallView != null) {
287 | WindowManager windowManager = getWindowManager(context);
288 | windowManager.removeView(ctrlCenterWindowSmallView);
289 | ctrlCenterWindowSmallView = null;
290 | }
291 | }
292 |
293 | /**
294 | * 将小悬浮窗从屏幕上移除。
295 | *
296 | * @param context 必须为应用程序的Context.
297 | */
298 | public static void removeCtrlCenterBigWindow(Context context) {
299 | if (ctrlCenterWindowBigView != null) {
300 | WindowManager windowManager = getWindowManager(context);
301 | windowManager.removeView(ctrlCenterWindowBigView);
302 | ctrlCenterWindowBigView = null;
303 | }
304 | }
305 |
306 | /**
307 | * 创建一个大悬浮窗。位置为屏幕正中间。
308 | *
309 | * @param context 必须为应用程序的Context.
310 | */
311 | public static void createBigWindow(Context context) {
312 | WindowManager windowManager = getWindowManager(context);
313 | int screenWidth = windowManager.getDefaultDisplay().getWidth();
314 | int screenHeight = windowManager.getDefaultDisplay().getHeight();
315 | if (bigWindow == null) {
316 | bigWindow = new FloatWindowBigView(context);
317 | if (bigWindowParams == null) {
318 | bigWindowParams = new WindowManager.LayoutParams();
319 | bigWindowParams.x = screenWidth / 2 - FloatWindowBigView.viewWidth / 2;
320 | bigWindowParams.y = screenHeight / 2 - FloatWindowBigView.viewHeight / 2;
321 | bigWindowParams.type = WindowManager.LayoutParams.TYPE_PHONE;
322 | bigWindowParams.format = PixelFormat.RGBA_8888;
323 | bigWindowParams.gravity = Gravity.LEFT | Gravity.TOP;
324 | bigWindowParams.width = FloatWindowBigView.viewWidth;
325 | bigWindowParams.height = FloatWindowBigView.viewHeight;
326 | }
327 | windowManager.addView(bigWindow, bigWindowParams);
328 | }
329 | }
330 |
331 | /**
332 | * 将大悬浮窗从屏幕上移除。
333 | *
334 | * @param context 必须为应用程序的Context.
335 | */
336 | public static void removeBigWindow(Context context) {
337 | if (bigWindow != null) {
338 | WindowManager windowManager = getWindowManager(context);
339 | windowManager.removeView(bigWindow);
340 | bigWindow = null;
341 | }
342 | }
343 |
344 | /**
345 | * 更新小悬浮窗的TextView上的数据,显示内存使用的百分比。
346 | *
347 | * @param context 可传入应用程序上下文。
348 | */
349 | public static void updateUsedPercent(Context context) {
350 | if (smallWindow != null) {
351 | // TextView percentView = (TextView) smallWindow.findViewById(R.id.percent);
352 | // percentView.setText(getUsedPercentValue(context));
353 | }
354 | }
355 |
356 | /**
357 | * 是否有悬浮窗(包括小悬浮窗和大悬浮窗)显示在屏幕上。
358 | *
359 | * @return 有悬浮窗显示在桌面上返回true,没有的话返回false。
360 | */
361 | public static boolean isWindowShowing() {
362 | return smallWindow != null || bigWindow != null;
363 | }
364 |
365 | /**
366 | * 如果WindowManager还未创建,则创建一个新的WindowManager返回。否则返回当前已创建的WindowManager。
367 | *
368 | * @param context 必须为应用程序的Context.
369 | * @return WindowManager的实例,用于控制在屏幕上添加或移除悬浮窗。
370 | */
371 | private static WindowManager getWindowManager(Context context) {
372 | if (mWindowManager == null) {
373 | mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
374 | }
375 | return mWindowManager;
376 | }
377 |
378 | /**
379 | * 如果ActivityManager还未创建,则创建一个新的ActivityManager返回。否则返回当前已创建的ActivityManager。
380 | *
381 | * @param context 可传入应用程序上下文。
382 | * @return ActivityManager的实例,用于获取手机可用内存。
383 | */
384 | private static ActivityManager getActivityManager(Context context) {
385 | if (mActivityManager == null) {
386 | mActivityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
387 | }
388 | return mActivityManager;
389 | }
390 |
391 | /**
392 | * 计算已使用内存的百分比,并返回。
393 | *
394 | * @param context 可传入应用程序上下文。
395 | * @return 已使用内存的百分比,以字符串形式返回。
396 | */
397 | public static String getUsedPercentValue(Context context) {
398 | String dir = "/proc/meminfo";
399 | try {
400 | FileReader fr = new FileReader(dir);
401 | BufferedReader br = new BufferedReader(fr, 2048);
402 | String memoryLine = br.readLine();
403 | String subMemoryLine = memoryLine.substring(memoryLine.indexOf("MemTotal:"));
404 | br.close();
405 | long totalMemorySize = Integer.parseInt(subMemoryLine.replaceAll("\\D+", ""));
406 | long availableSize = getAvailableMemory(context) / 1024;
407 | int percent = (int) ((totalMemorySize - availableSize) / (float) totalMemorySize * 100);
408 | return percent + "%";
409 | } catch (IOException e) {
410 | e.printStackTrace();
411 | }
412 | return "悬浮窗";
413 | }
414 |
415 | /**
416 | * 获取当前可用内存,返回数据以字节为单位。
417 | *
418 | * @param context 可传入应用程序上下文。
419 | * @return 当前可用内存。
420 | */
421 | private static long getAvailableMemory(Context context) {
422 | ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo();
423 | getActivityManager(context).getMemoryInfo(mi);
424 | return mi.availMem;
425 | }
426 |
427 | }
428 |
--------------------------------------------------------------------------------
/app/src/main/java/com/ks/control/SettingActivity.java:
--------------------------------------------------------------------------------
1 | package com.ks.control;
2 |
3 | import android.content.SharedPreferences;
4 | import android.os.Bundle;
5 | import android.support.v7.app.AppCompatActivity;
6 | import android.widget.CheckBox;
7 | import android.widget.CompoundButton;
8 | import android.widget.SeekBar;
9 | import android.widget.TextView;
10 |
11 | public class SettingActivity extends AppCompatActivity {
12 | SharedPreferences sp;
13 | CheckBox ckb0;
14 | CheckBox ckb1;
15 | CheckBox ckb2;
16 | int num = 0;
17 | SeekBar seekBar;
18 | private String title = "屏幕『底部%1$S设备像素』为感知区域";
19 | private TextView tv;
20 | int h = 3;
21 | CheckBox seekdefault;
22 |
23 | @Override
24 | protected void onCreate(Bundle savedInstanceState) {
25 | super.onCreate(savedInstanceState);
26 | setContentView(R.layout.activity_setting);
27 | sp = getSharedPreferences("setting", MODE_PRIVATE);
28 |
29 | ckb0 = (CheckBox) findViewById(R.id.ckb0);
30 | ckb1 = (CheckBox) findViewById(R.id.ckb1);
31 | ckb2 = (CheckBox) findViewById(R.id.ckb2);
32 | ckb0.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
33 | @Override
34 | public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
35 | if (b) {
36 | num = 0;
37 | }
38 | setCheckBox();
39 | }
40 | });
41 | ckb1.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
42 | @Override
43 | public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
44 | if (b) {
45 | num = 1;
46 | }
47 | setCheckBox();
48 | }
49 | });
50 | ckb2.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
51 | @Override
52 | public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
53 | if (b) {
54 | num = 2;
55 | }
56 | setCheckBox();
57 | }
58 | });
59 |
60 | tv = (TextView) findViewById(R.id.seektitle);
61 | seekBar = (SeekBar) findViewById(R.id.seek);
62 | seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
63 | @Override
64 | public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
65 | h = i;
66 | setTouchHeight();
67 | }
68 |
69 | @Override
70 | public void onStartTrackingTouch(SeekBar seekBar) {
71 |
72 | }
73 |
74 | @Override
75 | public void onStopTrackingTouch(SeekBar seekBar) {
76 |
77 | }
78 | });
79 | seekdefault = (CheckBox) findViewById(R.id.seekdefault);
80 | seekdefault.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
81 | @Override
82 | public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
83 | if (b) {
84 | h = 0;
85 | setTouchHeight();
86 | seekBar.setProgress(0);
87 | }
88 | }
89 | });
90 | h = sp.getInt("height", 0);
91 | setTouchHeight();
92 | num = sp.getInt("position", 0);
93 | setCheckBox();
94 | }
95 |
96 | private void setCheckBox() {
97 | if (num == 0) {
98 | ckb0.setChecked(true);
99 | ckb1.setChecked(false);
100 | ckb2.setChecked(false);
101 | } else if (num == 1) {
102 | ckb0.setChecked(false);
103 | ckb1.setChecked(true);
104 | ckb2.setChecked(false);
105 | } else {
106 | ckb0.setChecked(false);
107 | ckb1.setChecked(false);
108 | ckb2.setChecked(true);
109 | }
110 | SharedPreferences.Editor editor = sp.edit();
111 | editor.putInt("position", num);
112 | editor.commit();
113 | }
114 |
115 | private void setTouchHeight() {
116 | tv.setText(String.format(title, h + 3));
117 | SharedPreferences.Editor editor = sp.edit();
118 | editor.putInt("height", h);
119 | editor.commit();
120 | if (h != 0) {
121 | seekdefault.setChecked(false);
122 | } else {
123 | seekdefault.setChecked(true);
124 | }
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/app/src/main/java/com/ks/control/WebActivity.java:
--------------------------------------------------------------------------------
1 | package com.ks.control;
2 |
3 | import android.support.v7.app.AppCompatActivity;
4 | import android.os.Bundle;
5 | import android.view.Window;
6 | import android.webkit.WebSettings;
7 | import android.webkit.WebView;
8 |
9 | public class WebActivity extends AppCompatActivity {
10 | String url;
11 |
12 | @Override
13 | protected void onCreate(Bundle savedInstanceState) {
14 | super.onCreate(savedInstanceState);
15 | //设置无标题
16 | requestWindowFeature(Window.FEATURE_NO_TITLE);
17 | setContentView(R.layout.activity_web);
18 | url = getIntent().getStringExtra("url");
19 | WebView web = (WebView) findViewById(R.id.vweb);
20 | WebSettings webSettings = web.getSettings();
21 | webSettings.setJavaScriptEnabled(true);
22 | web.loadUrl(url);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/res/animator/indicator_animator.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/animator/indicator_animator_reverse.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/animator/scale_with_alpha.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/alertdialog_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/alertdialog_edit_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/floating_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/floating_small_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 |
8 |
9 |
10 |
11 | -
16 |
17 |
18 |
19 |
20 | -
25 |
26 |
27 |
28 |
29 | -
34 |
35 |
36 |
37 |
38 | -
43 |
44 |
45 |
46 |
47 |
48 |
49 | -
54 |
55 |
56 |
57 |
58 |
59 |
60 | -
65 |
66 |
67 |
68 |
69 | -
74 |
75 |
76 |
77 |
78 | -
83 |
84 |
85 |
86 |
87 | -
92 |
93 |
94 |
95 |
96 |
97 |
98 | -
103 |
104 |
107 |
111 |
112 |
113 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/floating_small_btn.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 | -
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | -
18 |
19 |
20 | -
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | -
31 |
32 |
33 | -
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
10 |
11 |
15 |
16 |
20 |
21 |
28 |
29 |
35 |
36 |
43 |
44 |
45 |
49 |
50 |
53 |
54 |
62 |
63 |
70 |
71 |
72 |
76 |
77 |
81 |
82 |
87 |
88 |
96 |
97 |
106 |
107 |
113 |
114 |
122 |
123 |
132 |
133 |
134 |
141 |
142 |
143 |
147 |
148 |
154 |
155 |
158 |
159 |
167 |
168 |
171 |
172 |
173 |
177 |
178 |
181 |
182 |
190 |
191 |
194 |
195 |
196 |
200 |
201 |
204 |
205 |
213 |
214 |
217 |
218 |
219 |
223 |
224 |
227 |
228 |
236 |
237 |
240 |
241 |
242 |
246 |
247 |
250 |
251 |
259 |
260 |
263 |
264 |
265 |
269 |
270 |
273 |
274 |
282 |
283 |
286 |
287 |
288 |
289 |
293 |
294 |
300 |
301 |
307 |
308 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_setting.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
13 |
14 |
18 |
19 |
22 |
23 |
31 |
32 |
37 |
38 |
39 |
45 |
46 |
49 |
50 |
58 |
59 |
64 |
65 |
66 |
72 |
73 |
76 |
77 |
84 |
85 |
90 |
91 |
92 |
93 |
97 |
98 |
105 |
106 |
112 |
113 |
119 |
120 |
126 |
127 |
134 |
135 |
140 |
141 |
147 |
148 |
149 |
153 |
154 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_web.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/floating_ctrl_center_window_big.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
17 |
18 |
24 |
25 |
30 |
31 |
37 |
38 |
39 |
45 |
46 |
51 |
52 |
58 |
59 |
60 |
61 |
67 |
68 |
73 |
74 |
80 |
81 |
82 |
88 |
89 |
94 |
95 |
101 |
102 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/floating_ctrl_center_window_small.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/floating_window_big.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
17 |
18 |
25 |
26 |
32 |
33 |
39 |
40 |
45 |
46 |
52 |
53 |
54 |
61 |
62 |
67 |
68 |
74 |
75 |
76 |
77 |
84 |
85 |
90 |
91 |
97 |
98 |
99 |
105 |
106 |
111 |
112 |
118 |
119 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/floating_window_small.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ctrl_center_icon_camara.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kangsafe/ControlCenter/83e66f036d420ca05b3ea743d82ca7c3eadd3a4f/app/src/main/res/mipmap-xhdpi/ctrl_center_icon_camara.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ctrl_center_icon_text.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kangsafe/ControlCenter/83e66f036d420ca05b3ea743d82ca7c3eadd3a4f/app/src/main/res/mipmap-xhdpi/ctrl_center_icon_text.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ctrl_center_icon_voice.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kangsafe/ControlCenter/83e66f036d420ca05b3ea743d82ca7c3eadd3a4f/app/src/main/res/mipmap-xhdpi/ctrl_center_icon_voice.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/floating_icon_camara.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kangsafe/ControlCenter/83e66f036d420ca05b3ea743d82ca7c3eadd3a4f/app/src/main/res/mipmap-xhdpi/floating_icon_camara.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/floating_icon_home.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kangsafe/ControlCenter/83e66f036d420ca05b3ea743d82ca7c3eadd3a4f/app/src/main/res/mipmap-xhdpi/floating_icon_home.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/floating_icon_text.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kangsafe/ControlCenter/83e66f036d420ca05b3ea743d82ca7c3eadd3a4f/app/src/main/res/mipmap-xhdpi/floating_icon_text.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/floating_icon_voice.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kangsafe/ControlCenter/83e66f036d420ca05b3ea743d82ca7c3eadd3a4f/app/src/main/res/mipmap-xhdpi/floating_icon_voice.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_find_next_holo_light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kangsafe/ControlCenter/83e66f036d420ca05b3ea743d82ca7c3eadd3a4f/app/src/main/res/mipmap-xhdpi/ic_find_next_holo_light.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kangsafe/ControlCenter/83e66f036d420ca05b3ea743d82ca7c3eadd3a4f/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/values-v21/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/values/arrays.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | - -
5 | - AR
6 | - AU
7 | - BR
8 | - BG
9 | - CA
10 | - CH
11 | - CN
12 | - CZ
13 | - DE
14 | - DK
15 | - ES
16 | - FI
17 | - FR
18 | - GB
19 | - GR
20 | - HU
21 | - ID
22 | - IT
23 | - JP
24 | - KR
25 | - NL
26 | - PL
27 | - PT
28 | - RO
29 | - RU
30 | - SE
31 | - SK
32 | - SI
33 | - TR
34 | - TW
35 | - US
36 |
37 |
38 | - @string/preferences_front_light_on
39 | - @string/preferences_front_light_auto
40 | - @string/preferences_front_light_off
41 |
42 |
43 | - ON
44 | - AUTO
45 | - OFF
46 |
47 |
48 |
--------------------------------------------------------------------------------
/app/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #ffffff
4 | #9947b214
5 | #99ff3930
6 | #32000000
7 | #66ffffff
8 | #ff8a9299
9 | #ffffffff
10 | #aaffffff
11 | #ffffffff
12 | #ffe1e3e6
13 | #ccf1f1f1
14 | #ff333333
15 | #ff000000
16 | #ffffffff
17 | #fff1f1f1
18 | #ffa5a5a5
19 | #ffff9800
20 | #ff01579b
21 | #f1dddddd
22 | #88000000
23 | #ffdddddd
24 | #dddddddd
25 | #c0ffbd21
26 | #ff61aed3
27 | #ff00838f
28 | #ffffffff
29 | #ffc0c0c0
30 | #c099cc00
31 | #ffffffff
32 | #b0000000
33 | #ffffffff
34 | #ff001a33
35 | #ff8a9199
36 | #ff666666
37 | #ffa5a5a5
38 | #ffcccccc
39 | #ff000000
40 | #00000000
41 | #ffcc0000
42 | #60000000
43 | #ffff3930
44 | #ff47b214
45 | #ffffffff
46 |
47 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 56.0dip
4 | 16.0dip
5 | 16.0dip
6 | 16.0dip
7 | 10.0dip
8 | 16.0sp
9 | 55.0dip
10 | 80.0dip
11 | 10.0dip
12 | 53.0dip
13 | 80.0dip
14 | 33.0dip
15 | 50.0dip
16 | 75.0dip
17 | 42.0dip
18 | 4.0dip
19 | 50.0dip
20 | 65.0dip
21 | 4.0dip
22 | 2.0dip
23 | 20.0dip
24 | 10.0dip
25 | 20.0dip
26 | 20.0dip
27 | 10.0dip
28 | 70.0dip
29 | 14.0sp
30 | 10.0dip
31 | 50.0dip
32 | 55.0dip
33 | 20.0dip
34 | 15.0dip
35 | 2.0dip
36 | 10.0dip
37 | 10.0dip
38 | 17.0sp
39 | 15.0sp
40 | 13.0sp
41 | 11.0sp
42 | 20.0sp
43 | 24.0sp
44 | 5.0dip
45 | 10.0dip
46 |
47 |
--------------------------------------------------------------------------------
/app/src/main/res/values/ids.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | - false
12 | - false
13 | - false
14 | - false
15 | - false
16 | - false
17 | - false
18 | - false
19 | - false
20 | - false
21 | - false
22 | - false
23 | - false
24 | - false
25 | - false
26 | - false
27 | - false
28 | - false
29 | - false
30 | - false
31 | - false
32 | - false
33 | - false
34 | - false
35 | - false
36 | - false
37 | - false
38 | - false
39 | - false
40 | - false
41 | - false
42 | - false
43 | - false
44 | - false
45 | - false
46 | - false
47 | - false
48 | - false
49 | - false
50 | - false
51 | - false
52 | - false
53 | - false
54 | - false
55 | - false
56 | - false
57 | - false
58 | - false
59 | - false
60 | - false
61 | - false
62 | - false
63 | - false
64 | - false
65 | - false
66 | - false
67 | - false
68 | - false
69 | - false
70 | - false
71 | - false
72 | - false
73 | - false
74 | - false
75 | - false
76 | - false
77 | - false
78 | - false
79 | - false
80 | - false
81 | - false
82 | - false
83 | - false
84 | - false
85 | - false
86 | - false
87 | - false
88 | - false
89 | - false
90 | - false
91 | - false
92 | - false
93 | - false
94 | - false
95 | - false
96 | - false
97 | - false
98 | - false
99 | - false
100 | - false
101 | - false
102 | - false
103 | - false
104 | - false
105 | - false
106 | - false
107 | - false
108 | - false
109 | - false
110 | - false
111 | - false
112 | - false
113 | - false
114 | - false
115 | - false
116 | - false
117 | - false
118 | - false
119 | - false
120 | - false
121 | - false
122 | - false
123 | - false
124 | - false
125 | - false
126 | - false
127 | - false
128 | - false
129 | - false
130 | - false
131 | - false
132 | - false
133 | - false
134 | - false
135 | - false
136 | - false
137 | - false
138 | - false
139 | - false
140 | - false
141 | - false
142 | - false
143 | - false
144 | - false
145 | - false
146 | - false
147 | - false
148 | - false
149 | - false
150 | - false
151 | - false
152 | - false
153 | - false
154 | - false
155 | - false
156 | - false
157 | - false
158 |
159 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 控制中心
4 | Applications
5 | Bookmarks
6 | Add to calendar
7 | Add contact
8 | Book Search
9 | Cancel
10 | Custom search
11 | Dial number
12 | Send email
13 | Get directions
14 | Send MMS
15 | OK
16 | Open browser
17 | Product search
18 | Search contents
19 | Application
20 | Bookmark
21 | Share via email
22 | Share via SMS
23 | Clipboard
24 | Contact
25 | Show map
26 | Send SMS
27 | Web search
28 | Connect to Network
29 | Contact info
30 | Email address
31 | Geographic coordinates
32 | Phone number
33 | SMS address
34 | Plain text
35 | Clear
36 | Clear history
37 | Barcode Scanner history
38 | Empty
39 | No barcode scans have been recorded
40 | Send history
41 | History
42 | Use MECARD
43 | Use vCard
44 | Help
45 | History
46 | Settings
47 | Share
48 | Bulk mode: barcode scanned and saved
49 | Sorry, the Android camera encountered a problem. You may need to restart the device.
50 | Format:
51 | Metadata:
52 | Hi
53 | Place a barcode inside the viewfinder rectangle to scan it.
54 | Time:
55 | Type:
56 | Could not encode a barcode from the data provided.
57 | Error
58 | Google
59 | Google
60 | Sorry, the requested application could not be launched. The barcode contents may be invalid.
61 | Invalid value
62 | Redirect
63 | Sorry, this book is not searchable.
64 | Sorry, the search encountered a problem.
65 | No page returned
66 | Page
67 | Results
68 | Searching book…
69 | Snippet not available
70 | You can share data by displaying a barcode on your screen and scanning it with another phone.
71 | Or type some text and press Enter
72 | Are you sure?
73 | Sorry, the SD card is not accessible.
74 | When a barcode is found…
75 | Use auto focus
76 | Open web pages automatically
77 | Scan and save many barcodes continuously
78 | Bulk scan mode
79 | Copy to clipboard
80 | Substitutions: %s = contents, %f = format, %t = type
81 | Custom search URL
82 | 1D Industrial
83 | 1D Product
84 | Aztec
85 | Data Matrix
86 | PDF417 (β)
87 | QR Codes
88 | Device Bug Workarounds
89 | No barcode scene mode
90 | Use only standard focus mode
91 | No continuous focus
92 | No exposure
93 | No metering
94 | Automatic
95 | Off
96 | On
97 | Improves scanning in low light on some phones, but may cause glare. Does not work on all phones.
98 | Use front light
99 | General settings
100 | Store your scans in History
101 | Add to History
102 | Scan for white barcodes on black background. Not available on some devices.
103 | Invert scan
104 | Settings
105 | No automatic rotation
106 | Beep
107 | Store multiple scans of the same barcode in History
108 | Remember duplicates
109 | Result settings
110 | When scanning for barcodes, decode…
111 | Search country
112 | Try to retrieve more information about the barcode contents
113 | Retrieve more info
114 | Vibrate
115 | Found contact info
116 | Found calendar event
117 | Found email address
118 | Found geographic coordinates
119 | Found book
120 | Found product
121 | Found SMS address
122 | Found phone number
123 | Found plain text
124 | Found URL
125 | Found WLAN Configuration
126 | Google Book Search
127 | Requesting connection to network…
128 | 刷新试试
129 | 当前网络不可用,请检查网络状态哟。
130 | "任意时刻底部上划即弹出面板,屏幕外亦可;
131 | 你也可以设置左、右边缘轻触启动面板;
132 | 如未弹出,请尝试调大触摸感知区域;
133 | 确认系统『设置-应用-权限管理』已开启『悬浮窗』等权限。"
134 | 操作方式与问题
135 | "本应用仅有700K左右,内存消耗也极少;
136 | 不会后台持续工作,不随意消耗用户电量;
137 | 不会后台连接网络,不任意消耗用户流量;
138 | 未使用黑科技保活,你来决定让它随时服务。"
139 | 查看保护方法
140 | 保护应用不被系统停止
141 | 网络不可用
142 | 暂不升级
143 | 正在加载...
144 | 立即升级
145 | 升级Android控制中心,获得更好体验
146 | 新版本 %1$s『仅%2$s』
147 | 升级新版本『仅%1$s』
148 | 正在初始化...
149 | 飞行模式
150 | 省电模式
151 | 蓝牙
152 | 关
153 | 勿扰模式
154 | 定位服务
155 | 移动网络
156 | 开
157 | 竖屏模式
158 | 系统设置
159 | 震动模式
160 | 无线网络
161 | 点击组件可以 删除 或 自定义功能
162 | 更多操作
163 | 自定义功能
164 | 自定义面板、组件、功能(魔方计划)
165 | 自定义状态文案
166 | 恭喜,自定义已生效
167 | 很好!放到合适的按键上
168 | 哇哦,没设进去哦!
169 | 松手即可替换
170 | 真棒,自定义成功!
171 | 长按图标拖拽到下面
172 | 分享取消
173 | 发送被拒绝
174 | 分享成功
175 | 发送返回
176 | 不支持错误
177 | 此服务暂不可用,请稍后再试
178 | 客户端处理失败,稍后重试
179 | 闪光灯不可用
180 | 当前网络不可用,请检查网络设置
181 | 服务器正忙,请稍后再试
182 | 未安装支付宝
183 | 操作失败,稍后重试: %1$s
184 | 系统无法启动该项目
185 | 系统不支持该项设置
186 | 系统不支持设置 %1$s
187 | 闹钟
188 | 扫码付款
189 | 自动
190 | 照相机
191 | 扫一扫
192 | 控制中心
193 | 恢复默认
194 | 手电筒
195 | 静音
196 | 录音器
197 | 屏幕『底部向上划』打开控制面板
198 | 屏幕『左边缘轻触或滑动』打开控制面板
199 | 屏幕『右边缘轻触或滑动』打开控制面板
200 | 无
201 | 手机底部上划,即弹出操作面板,希望你喜欢它!
202 | Android 简洁控制中心
203 | 添加组件
204 | 添加成功
205 | 更换背景
206 | 移除面板
207 | 移除成功
208 | 永久移除当前控制面板,确认这么做吗?
209 | 在权限管理中将『显示悬浮窗』开启,才能弹出控制面板,特请恩准。
210 | 应用需要悬浮窗权限
211 | 朕去开启
212 | 退出应用
213 | 移除组件
214 | 确定将此组件恢能到原始状态吗?
215 | 地址
216 | 生日
217 | 内容
218 | 邮箱
219 | 加密类型
220 | 姓名
221 | 备注
222 | 号码
223 | 公司
224 | 电话
225 | 密码
226 | 名称
227 | 职称
228 | 个人主页
229 | 文本解析
230 | 扫码内容(长按可复制)
231 | 关于Android控制中心 V%1$s
232 | 我有建议
233 | 吐槽问题
234 | 长按Home键 点亮宇宙
235 | 双击Home键 弹出面板
236 | iOS10 样式
237 | 核心用户计划
238 | 保护应用
239 | 通知栏显示
240 | https://control.litesuits.com?share_from=app
241 | 控制面板
242 | 给个好评
243 | 分享给朋友
244 | "分享到朋友圈后,
245 | 自定义功能解锁,
246 |
247 | 可随心所欲定制:
248 | 面板数量
249 | 定制组件
250 | 定制功能"
251 | 分享获取小红花
252 | 分享控制中心
253 | 『800K』轻量级控制面板,设置开关,声光调节,手电筒,扫一扫,付款,朋友圈,闹钟相机一步直达。官网 https://control.litesuits.com
254 | 让安卓控制中心比iPhone更好:800K安装,闪速启动,手电筒,扫码,付款,朋友圈一步直达
255 | 启动时弹出面板
256 | 开启面板方式
257 | 震感触摸
258 | 取消后,常驻通知将从状态栏消失,应用进入后台,可能被终止而无法随时启动面板
259 | 仍要取消
260 | 取消前台通知
261 | 取消
262 | 我知道了
263 | 加载中,请稍等...
264 | 操作失败
265 | 操作成功
266 | 确定
267 | 感知区域设置
268 | 屏幕『底部 %1$s 设备像素』为感知区域
269 | 屏幕『左侧 %1$s 设备像素』为感知区域
270 | 屏幕『右侧 %1$s 设备像素』为感知区域
271 | 底部 向上划
272 | 左边缘 轻触或滑动
273 | 右边缘 轻触或滑动
274 |
275 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
15 |
29 |
30 |
34 |
38 |
41 |
48 |
54 |
60 |
64 |
68 |
69 |
73 |
77 |
80 |
84 |
87 |
91 |
95 |
99 |
103 |
107 |
111 |
115 |
118 |
121 |
124 |
127 |
132 |
135 |
139 |
143 |
149 |
154 |
158 |
159 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/preferences.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/app/src/test/java/com/ks/controlcenter/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.ks.controlcenter;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:2.3.3'
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
21 | task clean(type: Delete) {
22 | delete rootProject.buildDir
23 | }
24 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | org.gradle.jvmargs=-Xmx1536m
13 |
14 | # When configured, Gradle will run in incubating parallel mode.
15 | # This option should only be used with decoupled projects. More details, visit
16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
17 | # org.gradle.parallel=true
18 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kangsafe/ControlCenter/83e66f036d420ca05b3ea743d82ca7c3eadd3a4f/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Jun 14 21:01:34 CST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------