This commit is contained in:
coco
2026-07-03 15:56:07 +08:00
commit caef23209c
5767 changed files with 1004268 additions and 0 deletions
+48
View File
@@ -0,0 +1,48 @@
# root files
# built application files
*.apk
*.ap_
# files for the dex VM
*.dex
# Java class files
*.class
# generated files
bin/
gen/
out/
# Local configuration file (sdk path, etc)
*.properties
proguard-project.txt
# Eclipse project files
.classpath
.project
.settings
# Proguard folder generated by Eclipse
proguard/
# Intellij project files
*.iml
*.ipr
*.iws
.idea/
.DS_Store
gen/com/litesuits/common/BuildConfig.java
lint.xml
project.properties
.gradle
/local.properties
/.idea
/build
+201
View File
@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+119
View File
@@ -0,0 +1,119 @@
LiteCommon项目简介
---
Android Common Utils or Helper.
Such as Log, Averager, Base64, Check, FlashLight, KeyguardLock, LogReader, Network, SilentInstaller, TimeAverager, TimeCounter, Toastor, WakeLock, ScreenReceiver, SmsReceiver, PhoneReceiver, NotificationService, AndroidUtil, AppUtil, BitmapUtil, ByteUtil, ClassUtil, DialogUtil, FieldUtil, FileUtil, HexUtil, MD5Util, NotificationUtil, NumberUtil, PackageUtil, RandomUtil, ShellUtil, TelephoneUtil, VibrateUtil, IOUtils, FileUtils, AsyncExecutor, etc.
##使用方法
build.gradle文件中添加:
dependencies {
...
compile 'com.luffykou:android-common-utils:1.1.3'
}
##详细介绍
LiteCommon是一系列通用类、辅助类、工具类的集合,有以下特点:
- **1. 通用性强**:只有常用、通用才集入。
- **2. 体积超小**:不到50K!加入增强IO包混淆后70K!
- **3. 纯 纯 纯**:类间独立,单挑大梁,极少耦合,就是单纯!
其中包括bitmap处理,文件操作,加密存储器,shell命令,静默安装,计数器,均值器,吐司,日志,校验,提示,网络监测等基础功能,以及一些Base64、MD5、Hex、Byte、Number、Dialog、Filed、Class、Package、Telephone、Random等工具类。
1. async包:异步与并发
-----
- **AsyncExecutor**: 一个简单的可以自定义线程池并发执行器
2. log包:日志
-----
- **Log** 一个和android系统日志类同名(方便快速替换)的Log工具类,不同的是这个Log具有一键开关功能,方便快速开发打开调试模式。
3. assit包:辅助
-----
- **Averager** 均值器, 添加一些列数字或时间戳,获取其均值。
- **Base64** Base64 兼容到android1.0版本的Base64编解码器。
- **Check** 检测类, 检测各种对象是否为null或empty。
- **FlashLight** 闪光灯, 开启、关闭闪光灯。
- **KeyguardLock** 锁屏管理, 锁屏、禁用锁屏,判断是否锁屏
- **LogReader** 日志捕获器, 将某个程序、级别的日志记录到sd卡中,方便远程调试。
- **Network** 网络探测器, 判断网络是否打开、连接、可用,以及当前网络状态。
- **SilentInstaller** 安装器, 静默安装、卸载(仅在root过的手机上)。
- **TimeAverager** 计时均值器, 统计耗时的同时,多次调用可得出其花费时间均值。
- **TimeCounter** 计时器, 顾名思义,统计耗时用的。
- **Toastor** 吐司, 解决多次连续弹出提示问题,可只弹出最后一次,也可连续弹出轻量级提示。
- **WakeLock** 屏幕管理, 点亮、关闭屏幕,判断屏幕是否点亮
4. data包:数据处理
-----
- **DataKeeper** 加密存储器,持久化工具,可加密,更简单、安全的存储(持久化)、获取数字、布尔值、甚至对象。
- **chipher包** 放置加解密辅助类。
5. io包:文件与IO
-----
- **Charsets** 字节编码类
- **FilenameUtils** 通用的文件名字、路径操作工具类
- **FileUtils** 通用文件操作工具类
- **IOUtils** 通用IO流操作工具类
- **StringCodingUtils**:字符串编码工具类
- **stream包** IO流操作辅助类
-
6. receiver包:通用广播接收器
-----
- **ScreenReceiver**: 屏幕接收器,可收到屏幕点亮、关闭的广播,并通过回调通知给调用者
- **PhoneReceiver** 电话监听,来电、去电、通话、挂断的监听以及来去电话号码的获取。
- **SmsReceiver** 短信接收器,可获取短信内容,发送者号码,短信中心号码等。
7. utils包:常用工具类
-----
- **AndroidUtil** android信息, 获取android手机品牌、商家、版本号等信息
- **AppUtil** app工具, 检测是否前台运行
- **BitmapUtil** 位图操作, 拍照,裁剪,圆角,byte、string互转,压缩,放缩,保存等
- **ByteUtil** byte工具类
- **ClassUtil** 类工具, 新建实例,判断类的类型等
- **DialogUtil** 对话框工具类, 统一全局对话框
- **FieldUtil**: 属性工具类,获取属性值、获取属性泛型类型等
- **FileUtil** 文件工具类
- **HexUtil** 16进制工具类,16进制和byte、char像话转化
- **MD5Util** MD5工具类
- **NotificationUtil**:通知工具类,便捷显示到顶部栏
- **NumberUtil**: 数字工具类,各种数字安全转化
- **PackageUtil**: 应用程序类,打开、安装,卸载,启动应用以及获取应用信息
- **RandomUtil** 随机工具类,产生随机string或数字,随机洗牌等
- **ShellUtil** shell 命令工具类
- **TelephoneUtil** 电话工具类,手机号、运营商、IMEI、IMSI等信息
- **VibrateUtil**: 震动工具类,调用系统震动功能
8. service包:通用服务
-----
- **NotificationService**:通知监听,各类通知服务的监听,获取通知的简述、标题、内容等信息,可以获取诸如QQ、微信、淘宝、浏览器等所有的在通知栏提示的消息。
关于作者(About Author
-----
我的博客 [http://vmatianyu.cn](http://vmatianyu.cn/)
我的开源站点 [http://litesuits.com](http://litesuits.com/)
点击加入QQ群:
[42960650](http://jq.qq.com/?_wv=1027&k=cxjcDa)
[47357508](http://jq.qq.com/?_wv=1027&k=Z7l0Av)
我的论坛帖子
-----
[LiteHttp:极简且智能的 android HTTP 框架库 (专注于网络)](http://www.eoeandroid.com/thread-326584-1-1.html)
[LiteOrm:极简且智能的 android ORM 框架库 (专注数据库)](http://www.eoeandroid.com/thread-538203-1-1.html)
[LiteAsync:强势的 android 异步 框架库 (专注异步与并发)](http://www.eoeandroid.com/thread-538212-1-1.html)
[LiteCommon:丰富通用的android工具类库(专注于基础组件)](http://www.eoeandroid.com/thread-557246-1-1.html)
我的博客帖子
-----
[关于java的线程并发和锁的总结](http://www.vmatianyu.cn/summary-of-the-java-thread-concurrency-and-locking.html)
[android开发技术经验总结60条](http://www.vmatianyu.cn/summarization-of-technical-experience.html)
[聚划算android客户端1期教训总结](http://www.vmatianyu.cn/poly-effective-client-1-issues-lessons.html)
[移动互联网产品设计小结](http://www.vmatianyu.cn/summary-of-mobile-internet-product-design.html)
+2
View File
@@ -0,0 +1,2 @@
/build
*.iml
+46
View File
@@ -0,0 +1,46 @@
apply plugin: 'com.android.library'
android {
compileSdkVersion 27
defaultConfig {
minSdkVersion 19
targetSdkVersion 27
versionCode 13
versionName "1.1.3"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
lintOptions {
abortOnError false
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
}
tasks.withType(Javadoc) {
options.addStringOption('Xdoclint:none', '-quiet')
options.addStringOption('encoding', 'UTF-8')
}
def libVersion = '1.2.0'
task makeJar(type: Jar) {
// 指定生成的jar名
def rootDir = project.getRootDir();
def parentDir = project.getRootDir().getParentFile().getAbsolutePath();
delete 'build/libs/*.*'
archiveName 'android-common-' + libVersion + '.jar'
destinationDir = file('build/libs')
// 从哪里打包class文件
from('build/intermediates/classes/release/')
// 打包到jar后的目录结构
// 去掉不需要打包的目录和文件
exclude('test/', 'BuildConfig.class', 'R.class', 'R\$*.class', 'META-INF/')
}
+17
View File
@@ -0,0 +1,17 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /Users/luffy/Library/Android/sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
@@ -0,0 +1,18 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.litesuits.common">
<uses-permission android:name="android.permission.INTERNET" />
<application>
<service
android:name=".service.NotificationService"
android:label="@string/app_name"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
</application>
</manifest>
@@ -0,0 +1,125 @@
package com.litesuits.android.async;
import android.os.Handler;
import android.os.Looper;
import com.litesuits.android.log.Log;
import java.util.concurrent.*;
/**
* 异步执行
*
* @author MaTianyu
*/
public class AsyncExecutor {
private static final String TAG = AsyncExecutor.class.getSimpleName();
private static ExecutorService threadPool;
public static Handler handler = new Handler(Looper.getMainLooper());
public AsyncExecutor() {
this(null);
}
public AsyncExecutor(ExecutorService threadPool) {
if (AsyncExecutor.threadPool != null) {
shutdownNow();
}
if (threadPool == null) {
AsyncExecutor.threadPool = Executors.newCachedThreadPool();
} else {
AsyncExecutor.threadPool = threadPool;
}
}
public static synchronized void shutdownNow() {
if (threadPool != null && !threadPool.isShutdown()) threadPool.shutdownNow();
threadPool = null;
}
/**
* 将任务投入线程池执行
*
* @param worker
* @return
*/
public <T> FutureTask<T> execute(final Worker<T> worker) {
Callable<T> call = new Callable<T>() {
@Override
public T call() throws Exception {
return postResult(worker, worker.doInBackground());
}
};
FutureTask<T> task = new FutureTask<T>(call) {
@Override
protected void done() {
try {
get();
} catch (InterruptedException e) {
Log.e(TAG, e);
worker.abort();
postCancel(worker);
e.printStackTrace();
} catch (ExecutionException e) {
Log.e(TAG, e.getMessage());
e.printStackTrace();
throw new RuntimeException("An error occured while executing doInBackground()", e.getCause());
} catch (CancellationException e) {
worker.abort();
postCancel(worker);
Log.e(TAG, e);
e.printStackTrace();
}
}
};
threadPool.execute(task);
return task;
}
/**
* 将子线程结果传递到UI线程
*
* @param worker
* @param result
* @return
*/
private <T> T postResult(final Worker<T> worker, final T result) {
handler.post(new Runnable() {
@Override
public void run() {
worker.onPostExecute(result);
}
});
return result;
}
/**
* 将子线程结果传递到UI线程
*
* @param worker
* @return
*/
private void postCancel(final Worker worker) {
handler.post(new Runnable() {
@Override
public void run() {
worker.onCanceled();
}
});
}
public <T> FutureTask<T> execute(Callable<T> call) {
FutureTask<T> task = new FutureTask<T>(call);
threadPool.execute(task);
return task;
}
public static abstract class Worker<T> {
protected abstract T doInBackground();
protected void onPostExecute(T data) {}
protected void onCanceled() {}
protected void abort() {}
}
}
@@ -0,0 +1,150 @@
/*
* Copyright (C) 2013 litesuits.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.litesuits.android.log;
/**
* the logger
*
* @author MaTianyu
* 2014-1-1下午4:05:39
*/
public final class Log {
/**
* isPrint: print switch, true will print. false not print
*/
public static boolean isPrint = true;
private static String defaultTag = "Log";
private Log() {}
public static void setTag(String tag) {
defaultTag = tag;
}
public static int i(Object o) {
return isPrint && o != null ? android.util.Log.i(defaultTag, o.toString()) : -1;
}
public static int i(String m) {
return isPrint && m != null ? android.util.Log.i(defaultTag, m) : -1;
}
/**
* ******************** Log **************************
*/
public static int v(String tag, String msg) {
return isPrint && msg != null ? android.util.Log.v(tag, msg) : -1;
}
public static int d(String tag, String msg) {
return isPrint && msg != null ? android.util.Log.d(tag, msg) : -1;
}
public static int i(String tag, String msg) {
return isPrint && msg != null ? android.util.Log.i(tag, msg) : -1;
}
public static int w(String tag, String msg) {
return isPrint && msg != null ? android.util.Log.w(tag, msg) : -1;
}
public static int e(String tag, String msg) {
return isPrint && msg != null ? android.util.Log.e(tag, msg) : -1;
}
/**
* ******************** Log with object list **************************
*/
public static int v(String tag, Object... msg) {
return isPrint ? android.util.Log.v(tag, getLogMessage(msg)) : -1;
}
public static int d(String tag, Object... msg) {
return isPrint ? android.util.Log.d(tag, getLogMessage(msg)) : -1;
}
public static int i(String tag, Object... msg) {
return isPrint ? android.util.Log.i(tag, getLogMessage(msg)) : -1;
}
public static int w(String tag, Object... msg) {
return isPrint ? android.util.Log.w(tag, getLogMessage(msg)) : -1;
}
public static int e(String tag, Object... msg) {
return isPrint ? android.util.Log.e(tag, getLogMessage(msg)) : -1;
}
private static String getLogMessage(Object... msg) {
if (msg != null && msg.length > 0) {
StringBuilder sb = new StringBuilder();
for (Object s : msg) {
if (s != null) {
sb.append(s.toString());
}
}
return sb.toString();
}
return "";
}
/**
* ******************** Log with Throwable **************************
*/
public static int v(String tag, String msg, Throwable tr) {
return isPrint && msg != null ? android.util.Log.v(tag, msg, tr) : -1;
}
public static int d(String tag, String msg, Throwable tr) {
return isPrint && msg != null ? android.util.Log.d(tag, msg, tr) : -1;
}
public static int i(String tag, String msg, Throwable tr) {
return isPrint && msg != null ? android.util.Log.i(tag, msg, tr) : -1;
}
public static int w(String tag, String msg, Throwable tr) {
return isPrint && msg != null ? android.util.Log.w(tag, msg, tr) : -1;
}
public static int e(String tag, String msg, Throwable tr) {
return isPrint && msg != null ? android.util.Log.e(tag, msg, tr) : -1;
}
/**
* ******************** TAG use Object Tag **************************
*/
public static int v(Object tag, String msg) {
return isPrint ? android.util.Log.v(tag.getClass().getSimpleName(), msg) : -1;
}
public static int d(Object tag, String msg) {
return isPrint ? android.util.Log.d(tag.getClass().getSimpleName(), msg) : -1;
}
public static int i(Object tag, String msg) {
return isPrint ? android.util.Log.i(tag.getClass().getSimpleName(), msg) : -1;
}
public static int w(Object tag, String msg) {
return isPrint ? android.util.Log.w(tag.getClass().getSimpleName(), msg) : -1;
}
public static int e(Object tag, String msg) {
return isPrint ? android.util.Log.e(tag.getClass().getSimpleName(), msg) : -1;
}
}
@@ -0,0 +1,150 @@
/*
* Copyright (C) 2013 litesuits.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.litesuits.android.log;
import java.io.*;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 打印日志
*
* @author mty
* @time 2011-11-2下午06:23:29
*/
public class LogReader extends Thread {
public static final String TAG = "LogReader";
public static final String LOG_FILE_PATH = "/bonglog.txt";
public static final String LOG_ROOT_PATH = "/sdcard";
public static boolean open = true;
private static LogReader instance = null;
private static Process mLogcatProc = null;
private BufferedReader mReader = null;
private String packageName = "*";
public static void startCatchLog(String packageName) {
if (!open) return;
if (instance == null) {
instance = new LogReader();
instance.packageName = packageName;
instance.start();
}
}
public static void stopCatchLog() {
if (!open) return;
if (mLogcatProc != null) {
mLogcatProc.destroy();
mLogcatProc = null;
}
}
@Override
public void run() {
Log.i(TAG, "log reader(catcher) is running..---------------------------");
BufferedWriter bw = null;
try {
mLogcatProc = Runtime.getRuntime().exec("logcat " + packageName + ":I");
mReader = new BufferedReader(new InputStreamReader(mLogcatProc.getInputStream()));
// 打印系统信息。
logSystemInfo();
String line;
File file = new File(LOG_ROOT_PATH + LOG_FILE_PATH);
if (file.exists() && isFileSizeOutof10M(file)) {
file.delete();
}
if (file.exists()) {
System.out.println("log file size is :"
+ FormatFileSize(file.length()));
}
FileWriter fw = new FileWriter(file, true);
bw = new BufferedWriter(fw);
while ((line = mReader.readLine()) != null) {
bw.append(line);
bw.newLine();
bw.flush();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
Log.i(TAG, "Log reader(catcher) and bufferwriter has closed. ------------------");
try {
if (mReader != null) {
mReader.close();
mReader = null;
}
if (bw != null) {
bw.close();
}
} catch (IOException e) {
e.printStackTrace();
}
instance = null;
}
}
public static String FormatFileSize(long fileS) {// 转换文件大小
DecimalFormat df = new DecimalFormat("#.00");
String fileSizeString = "";
if (fileS < 1024) {
fileSizeString = df.format((double) fileS) + "B";
} else if (fileS < 1048576) {
fileSizeString = df.format((double) fileS / 1024) + "K";
} else if (fileS < 1073741824) {
fileSizeString = df.format((double) fileS / 1048576) + "M";
} else {
fileSizeString = df.format((double) fileS / 1073741824) + "G";
}
return fileSizeString;
}
/**
* 判断文件是否大于10M。
*
* @param file
* @return
* @throws Exception
*/
public static boolean isFileSizeOutof10M(File file) throws Exception {
if (file == null) return false;
return file.length() >= 10485760;
}
public static void logSystemInfo() {
Date date = new Date(System.currentTimeMillis());
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time = dateFormat.format(date);
android.util.Log.w("system", "New Start $$$$$$$$$$$$$$########### " + time + "############$$$$$$$$$$$$$$$");
android.util.Log.w("system", "android.os.Build.BOARD:" + android.os.Build.BOARD);
android.util.Log.w("system", "android.os.Build.DEVICE:" + android.os.Build.DEVICE);
android.util.Log.w("system", "android.os.Build.MANUFACTURER:"
+ android.os.Build.MANUFACTURER);
android.util.Log.w("system", "android.os.Build.MODEL:" + android.os.Build.MODEL);
android.util.Log.w("system", "android.os.Build.PRODUCT:" + android.os.Build.PRODUCT);
android.util.Log.w("system", "android.os.Build.VERSION.CODENAME:"
+ android.os.Build.VERSION.CODENAME);
android.util.Log.w("system", "android.os.Build.VERSION.RELEASE:"
+ android.os.Build.VERSION.RELEASE);
//android.util.Log.w("system", "android.os.Build.VERSION.SDK:"
// + android.os.Build.VERSION.SDK);
}
}
@@ -0,0 +1,127 @@
package com.litesuits.android.view;
import android.content.Context;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
/**
* @author MaTianyu
* @date 2014-08-15
*/
public class TipsView extends LinearLayout {
protected View realView;
protected ViewGroup parentView;
protected Context context;
protected boolean isThisInLayout = false;
public TipsView(Context context) {
this(context, (AttributeSet) null);
}
public TipsView(Context context, AttributeSet attrs) {
this(context, attrs, null, null);
}
public TipsView(Context context, View realView, View tipView) {
this(context, null, realView, tipView);
}
public TipsView(Context context, View realView) {
this(context, null, realView, null);
}
public TipsView(Context context, AttributeSet attrs, View realView, View tipView) {
super(context, attrs);
this.context = context;
initSelf();
setRealView(realView);
setTipView(tipView);
}
public void initSelf() {
setOrientation(HORIZONTAL);
setGravity(Gravity.CENTER);
}
public TipsView setTipView(View tipView) {
if (tipView != null) {
removeAllViews();
addView(tipView);
}
return this;
}
public TipsView setTipView(int resID) {
removeAllViews();
LayoutInflater.from(context).inflate(resID, this, true);
return this;
}
public View getRealView() {
return realView;
}
public TipsView setRealView(View realView) {
if (realView != null) {
showRealView();
this.realView = realView;
parentView = (ViewGroup) realView.getParent();
setLayoutParams(realView.getLayoutParams());
}
return this;
}
public void showRealView() {
if (realView != null && parentView != null) {
if (isThisInLayout) {
for (int i = 0, size = parentView.getChildCount(); i < size; i++) {
if (parentView.getChildAt(i) == this) {
parentView.removeView(this);
//realView.setId(getId());
//setId(0);
parentView.addView(realView, i);
isThisInLayout = false;
break;
}
}
}
}
}
public void showTipsView() {
if (realView != null && parentView != null) {
if (!isThisInLayout) {
for (int i = 0, size = parentView.getChildCount(); i < size; i++) {
if (parentView.getChildAt(i) == realView) {
parentView.removeView(realView);
//setId(realView.getId());
//realView.setId(0);
parentView.addView(this, i);
isThisInLayout = true;
break;
}
}
}
}
}
public void gone() {
setVisibility(GONE);
}
public void visible() {
setVisibility(VISIBLE);
}
public void inVisible() {
setVisibility(INVISIBLE);
}
}
@@ -0,0 +1,70 @@
package com.litesuits.common.assist;
import com.litesuits.android.log.Log;
import java.util.ArrayList;
/**
* 用以统计平均数
*
* @author MaTianyu
* 2013-12-11下午3:31:03
*/
public class Averager {
private static final String TAG = "Averager";
private ArrayList<Number> numList = new ArrayList<Number>();
/**
* 添加一个数字
*
* @param num
*/
public synchronized void add(Number num) {
numList.add(num);
}
/**
* 清除全部
*/
public void clear() {
numList.clear();
}
/**
* 返回参与均值计算的数字个数
*
* @return
*/
public Number size() {
return numList.size();
}
/**
* 获取平均数
*
* @return
*/
public Number getAverage() {
if (numList.size() == 0) {
return 0;
} else {
Float sum = 0f;
for (int i = 0, size = numList.size(); i < size; i++) {
sum = sum.floatValue() + numList.get(i).floatValue();
}
return sum / numList.size();
}
}
/**
* 打印数字列
*
* @return
*/
public String print() {
String str = "PrintList(" + size() + "): " + numList;
Log.i(TAG, str);
return str;
}
}
@@ -0,0 +1,741 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.litesuits.common.assist;
import java.io.UnsupportedEncodingException;
/**
* Utilities for encoding and decoding the Base64 representation of
* binary data. See RFCs <a
* href="http://www.ietf.org/rfc/rfc2045.txt">2045</a> and <a
* href="http://www.ietf.org/rfc/rfc3548.txt">3548</a>.
*/
public class Base64 {
/**
* Default values for encoder/decoder flags.
*/
public static final int DEFAULT = 0;
/**
* Encoder flag bit to omit the padding '=' characters at the end
* of the output (if any).
*/
public static final int NO_PADDING = 1;
/**
* Encoder flag bit to omit all line terminators (i.e., the output
* will be on one long line).
*/
public static final int NO_WRAP = 2;
/**
* Encoder flag bit to indicate lines should be terminated with a
* CRLF pair instead of just an LF. Has no effect if {@code
* NO_WRAP} is specified as well.
*/
public static final int CRLF = 4;
/**
* Encoder/decoder flag bit to indicate using the "URL and
* filename safe" variant of Base64 (see RFC 3548 section 4) where
* {@code -} and {@code _} are used in place of {@code +} and
* {@code /}.
*/
public static final int URL_SAFE = 8;
/**
* Flag to pass to {@link android.util.Base64OutputStream} to indicate that it
* should not close the output stream it is wrapping when it
* itself is closed.
*/
public static final int NO_CLOSE = 16;
// --------------------------------------------------------
// shared code
// --------------------------------------------------------
/* package */ static abstract class Coder {
public byte[] output;
public int op;
/**
* Encode/decode another block of input data. this.output is
* provided by the caller, and must be big enough to hold all
* the coded data. On exit, this.opwill be set to the length
* of the coded data.
*
* @param finish true if this is the final call to process for
* this object. Will finalize the coder state and
* include any final bytes in the output.
*
* @return true if the input so far is good; false if some
* error has been detected in the input stream..
*/
public abstract boolean process(byte[] input, int offset, int len, boolean finish);
/**
* @return the maximum number of bytes a call to process()
* could produce for the given number of input bytes. This may
* be an overestimate.
*/
public abstract int maxOutputSize(int len);
}
// --------------------------------------------------------
// decoding
// --------------------------------------------------------
/**
* Decode the Base64-encoded data in input and return the data in
* a new byte array.
*
* <p>The padding '=' characters at the end are considered optional, but
* if any are present, there must be the correct number of them.
*
* @param str the input String to decode, which is converted to
* bytes using the default charset
* @param flags controls certain features of the decoded output.
* Pass {@code DEFAULT} to decode standard Base64.
*
* @throws IllegalArgumentException if the input contains
* incorrect padding
*/
public static byte[] decode(String str, int flags) {
return decode(str.getBytes(), flags);
}
/**
* Decode the Base64-encoded data in input and return the data in
* a new byte array.
*
* <p>The padding '=' characters at the end are considered optional, but
* if any are present, there must be the correct number of them.
*
* @param input the input array to decode
* @param flags controls certain features of the decoded output.
* Pass {@code DEFAULT} to decode standard Base64.
*
* @throws IllegalArgumentException if the input contains
* incorrect padding
*/
public static byte[] decode(byte[] input, int flags) {
return decode(input, 0, input.length, flags);
}
/**
* Decode the Base64-encoded data in input and return the data in
* a new byte array.
*
* <p>The padding '=' characters at the end are considered optional, but
* if any are present, there must be the correct number of them.
*
* @param input the data to decode
* @param offset the position within the input array at which to start
* @param len the number of bytes of input to decode
* @param flags controls certain features of the decoded output.
* Pass {@code DEFAULT} to decode standard Base64.
*
* @throws IllegalArgumentException if the input contains
* incorrect padding
*/
public static byte[] decode(byte[] input, int offset, int len, int flags) {
// Allocate space for the most data the input could represent.
// (It could contain less if it contains whitespace, etc.)
Decoder decoder = new Decoder(flags, new byte[len*3/4]);
if (!decoder.process(input, offset, len, true)) {
throw new IllegalArgumentException("bad base-64");
}
// Maybe we got lucky and allocated exactly enough output space.
if (decoder.op == decoder.output.length) {
return decoder.output;
}
// Need to shorten the array, so allocate a new one of the
// right size and copy.
byte[] temp = new byte[decoder.op];
System.arraycopy(decoder.output, 0, temp, 0, decoder.op);
return temp;
}
/* package */ static class Decoder extends Coder {
/**
* Lookup table for turning bytes into their position in the
* Base64 alphabet.
*/
private static final int DECODE[] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1,
-1, 0, 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, -1, -1, -1, -1, -1,
-1, 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, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
};
/**
* Decode lookup table for the "web safe" variant (RFC 3548
* sec. 4) where - and _ replace + and /.
*/
private static final int DECODE_WEBSAFE[] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1,
-1, 0, 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, -1, -1, -1, -1, 63,
-1, 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, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
};
/** Non-data values in the DECODE arrays. */
private static final int SKIP = -1;
private static final int EQUALS = -2;
/**
* States 0-3 are reading through the next input tuple.
* State 4 is having read one '=' and expecting exactly
* one more.
* State 5 is expecting no more data or padding characters
* in the input.
* State 6 is the error state; an error has been detected
* in the input and no future input can "fix" it.
*/
private int state; // state number (0 to 6)
private int value;
final private int[] alphabet;
public Decoder(int flags, byte[] output) {
this.output = output;
alphabet = ((flags & URL_SAFE) == 0) ? DECODE : DECODE_WEBSAFE;
state = 0;
value = 0;
}
/**
* @return an overestimate for the number of bytes {@code
* len} bytes could decode to.
*/
public int maxOutputSize(int len) {
return len * 3/4 + 10;
}
/**
* Decode another block of input data.
*
* @return true if the state machine is still healthy. false if
* bad base-64 data has been detected in the input stream.
*/
public boolean process(byte[] input, int offset, int len, boolean finish) {
if (this.state == 6) return false;
int p = offset;
len += offset;
// Using local variables makes the decoder about 12%
// faster than if we manipulate the member variables in
// the loop. (Even alphabet makes a measurable
// difference, which is somewhat surprising to me since
// the member variable is final.)
int state = this.state;
int value = this.value;
int op = 0;
final byte[] output = this.output;
final int[] alphabet = this.alphabet;
while (p < len) {
// Try the fast path: we're starting a new tuple and the
// next four bytes of the input stream are all data
// bytes. This corresponds to going through states
// 0-1-2-3-0. We expect to use this method for most of
// the data.
//
// If any of the next four bytes of input are non-data
// (whitespace, etc.), value will end up negative. (All
// the non-data values in decode are small negative
// numbers, so shifting any of them up and or'ing them
// together will result in a value with its top bit set.)
//
// You can remove this whole block and the output should
// be the same, just slower.
if (state == 0) {
while (p+4 <= len &&
(value = ((alphabet[input[p] & 0xff] << 18) |
(alphabet[input[p+1] & 0xff] << 12) |
(alphabet[input[p+2] & 0xff] << 6) |
(alphabet[input[p+3] & 0xff]))) >= 0) {
output[op+2] = (byte) value;
output[op+1] = (byte) (value >> 8);
output[op] = (byte) (value >> 16);
op += 3;
p += 4;
}
if (p >= len) break;
}
// The fast path isn't available -- either we've read a
// partial tuple, or the next four input bytes aren't all
// data, or whatever. Fall back to the slower state
// machine implementation.
int d = alphabet[input[p++] & 0xff];
switch (state) {
case 0:
if (d >= 0) {
value = d;
++state;
} else if (d != SKIP) {
this.state = 6;
return false;
}
break;
case 1:
if (d >= 0) {
value = (value << 6) | d;
++state;
} else if (d != SKIP) {
this.state = 6;
return false;
}
break;
case 2:
if (d >= 0) {
value = (value << 6) | d;
++state;
} else if (d == EQUALS) {
// Emit the last (partial) output tuple;
// expect exactly one more padding character.
output[op++] = (byte) (value >> 4);
state = 4;
} else if (d != SKIP) {
this.state = 6;
return false;
}
break;
case 3:
if (d >= 0) {
// Emit the output triple and return to state 0.
value = (value << 6) | d;
output[op+2] = (byte) value;
output[op+1] = (byte) (value >> 8);
output[op] = (byte) (value >> 16);
op += 3;
state = 0;
} else if (d == EQUALS) {
// Emit the last (partial) output tuple;
// expect no further data or padding characters.
output[op+1] = (byte) (value >> 2);
output[op] = (byte) (value >> 10);
op += 2;
state = 5;
} else if (d != SKIP) {
this.state = 6;
return false;
}
break;
case 4:
if (d == EQUALS) {
++state;
} else if (d != SKIP) {
this.state = 6;
return false;
}
break;
case 5:
if (d != SKIP) {
this.state = 6;
return false;
}
break;
}
}
if (!finish) {
// We're out of input, but a future call could provide
// more.
this.state = state;
this.value = value;
this.op = op;
return true;
}
// Done reading input. Now figure out where we are left in
// the state machine and finish up.
switch (state) {
case 0:
// Output length is a multiple of three. Fine.
break;
case 1:
// Read one extra input byte, which isn't enough to
// make another output byte. Illegal.
this.state = 6;
return false;
case 2:
// Read two extra input bytes, enough to emit 1 more
// output byte. Fine.
output[op++] = (byte) (value >> 4);
break;
case 3:
// Read three extra input bytes, enough to emit 2 more
// output bytes. Fine.
output[op++] = (byte) (value >> 10);
output[op++] = (byte) (value >> 2);
break;
case 4:
// Read one padding '=' when we expected 2. Illegal.
this.state = 6;
return false;
case 5:
// Read all the padding '='s we expected and no more.
// Fine.
break;
}
this.state = state;
this.op = op;
return true;
}
}
// --------------------------------------------------------
// encoding
// --------------------------------------------------------
/**
* Base64-encode the given data and return a newly allocated
* String with the result.
*
* @param input the data to encode
* @param flags controls certain features of the encoded output.
* Passing {@code DEFAULT} results in output that
* adheres to RFC 2045.
*/
public static String encodeToString(byte[] input, int flags) {
try {
return new String(encode(input, flags), "US-ASCII");
} catch (UnsupportedEncodingException e) {
// US-ASCII is guaranteed to be available.
throw new AssertionError(e);
}
}
/**
* Base64-encode the given data and return a newly allocated
* String with the result.
*
* @param input the data to encode
* @param offset the position within the input array at which to
* start
* @param len the number of bytes of input to encode
* @param flags controls certain features of the encoded output.
* Passing {@code DEFAULT} results in output that
* adheres to RFC 2045.
*/
public static String encodeToString(byte[] input, int offset, int len, int flags) {
try {
return new String(encode(input, offset, len, flags), "US-ASCII");
} catch (UnsupportedEncodingException e) {
// US-ASCII is guaranteed to be available.
throw new AssertionError(e);
}
}
/**
* Base64-encode the given data and return a newly allocated
* byte[] with the result.
*
* @param input the data to encode
* @param flags controls certain features of the encoded output.
* Passing {@code DEFAULT} results in output that
* adheres to RFC 2045.
*/
public static byte[] encode(byte[] input, int flags) {
return encode(input, 0, input.length, flags);
}
/**
* Base64-encode the given data and return a newly allocated
* byte[] with the result.
*
* @param input the data to encode
* @param offset the position within the input array at which to
* start
* @param len the number of bytes of input to encode
* @param flags controls certain features of the encoded output.
* Passing {@code DEFAULT} results in output that
* adheres to RFC 2045.
*/
public static byte[] encode(byte[] input, int offset, int len, int flags) {
Encoder encoder = new Encoder(flags, null);
// Compute the exact length of the array we will produce.
int output_len = len / 3 * 4;
// Account for the tail of the data and the padding bytes, if any.
if (encoder.do_padding) {
if (len % 3 > 0) {
output_len += 4;
}
} else {
switch (len % 3) {
case 0: break;
case 1: output_len += 2; break;
case 2: output_len += 3; break;
}
}
// Account for the newlines, if any.
if (encoder.do_newline && len > 0) {
output_len += (((len-1) / (3 * Encoder.LINE_GROUPS)) + 1) *
(encoder.do_cr ? 2 : 1);
}
encoder.output = new byte[output_len];
encoder.process(input, offset, len, true);
assert encoder.op == output_len;
return encoder.output;
}
/* package */ static class Encoder extends Coder {
/**
* Emit a new line every this many output tuples. Corresponds to
* a 76-character line length (the maximum allowable according to
* <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>).
*/
public static final int LINE_GROUPS = 19;
/**
* Lookup table for turning Base64 alphabet positions (6 bits)
* into output bytes.
*/
private static final byte ENCODE[] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/',
};
/**
* Lookup table for turning Base64 alphabet positions (6 bits)
* into output bytes.
*/
private static final byte ENCODE_WEBSAFE[] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_',
};
final private byte[] tail;
/* package */ int tailLen;
private int count;
final public boolean do_padding;
final public boolean do_newline;
final public boolean do_cr;
final private byte[] alphabet;
public Encoder(int flags, byte[] output) {
this.output = output;
do_padding = (flags & NO_PADDING) == 0;
do_newline = (flags & NO_WRAP) == 0;
do_cr = (flags & CRLF) != 0;
alphabet = ((flags & URL_SAFE) == 0) ? ENCODE : ENCODE_WEBSAFE;
tail = new byte[2];
tailLen = 0;
count = do_newline ? LINE_GROUPS : -1;
}
/**
* @return an overestimate for the number of bytes {@code
* len} bytes could encode to.
*/
public int maxOutputSize(int len) {
return len * 8/5 + 10;
}
public boolean process(byte[] input, int offset, int len, boolean finish) {
// Using local variables makes the encoder about 9% faster.
final byte[] alphabet = this.alphabet;
final byte[] output = this.output;
int op = 0;
int count = this.count;
int p = offset;
len += offset;
int v = -1;
// First we need to concatenate the tail of the previous call
// with any input bytes available now and see if we can empty
// the tail.
switch (tailLen) {
case 0:
// There was no tail.
break;
case 1:
if (p+2 <= len) {
// A 1-byte tail with at least 2 bytes of
// input available now.
v = ((tail[0] & 0xff) << 16) |
((input[p++] & 0xff) << 8) |
(input[p++] & 0xff);
tailLen = 0;
};
break;
case 2:
if (p+1 <= len) {
// A 2-byte tail with at least 1 byte of input.
v = ((tail[0] & 0xff) << 16) |
((tail[1] & 0xff) << 8) |
(input[p++] & 0xff);
tailLen = 0;
}
break;
}
if (v != -1) {
output[op++] = alphabet[(v >> 18) & 0x3f];
output[op++] = alphabet[(v >> 12) & 0x3f];
output[op++] = alphabet[(v >> 6) & 0x3f];
output[op++] = alphabet[v & 0x3f];
if (--count == 0) {
if (do_cr) output[op++] = '\r';
output[op++] = '\n';
count = LINE_GROUPS;
}
}
// At this point either there is no tail, or there are fewer
// than 3 bytes of input available.
// The main loop, turning 3 input bytes into 4 output bytes on
// each iteration.
while (p+3 <= len) {
v = ((input[p] & 0xff) << 16) |
((input[p+1] & 0xff) << 8) |
(input[p+2] & 0xff);
output[op] = alphabet[(v >> 18) & 0x3f];
output[op+1] = alphabet[(v >> 12) & 0x3f];
output[op+2] = alphabet[(v >> 6) & 0x3f];
output[op+3] = alphabet[v & 0x3f];
p += 3;
op += 4;
if (--count == 0) {
if (do_cr) output[op++] = '\r';
output[op++] = '\n';
count = LINE_GROUPS;
}
}
if (finish) {
// Finish up the tail of the input. Note that we need to
// consume any bytes in tail before any bytes
// remaining in input; there should be at most two bytes
// total.
if (p-tailLen == len-1) {
int t = 0;
v = ((tailLen > 0 ? tail[t++] : input[p++]) & 0xff) << 4;
tailLen -= t;
output[op++] = alphabet[(v >> 6) & 0x3f];
output[op++] = alphabet[v & 0x3f];
if (do_padding) {
output[op++] = '=';
output[op++] = '=';
}
if (do_newline) {
if (do_cr) output[op++] = '\r';
output[op++] = '\n';
}
} else if (p-tailLen == len-2) {
int t = 0;
v = (((tailLen > 1 ? tail[t++] : input[p++]) & 0xff) << 10) |
(((tailLen > 0 ? tail[t++] : input[p++]) & 0xff) << 2);
tailLen -= t;
output[op++] = alphabet[(v >> 12) & 0x3f];
output[op++] = alphabet[(v >> 6) & 0x3f];
output[op++] = alphabet[v & 0x3f];
if (do_padding) {
output[op++] = '=';
}
if (do_newline) {
if (do_cr) output[op++] = '\r';
output[op++] = '\n';
}
} else if (do_newline && op > 0 && count != LINE_GROUPS) {
if (do_cr) output[op++] = '\r';
output[op++] = '\n';
}
assert tailLen == 0;
assert p == len;
} else {
// Save the leftovers in tail to be consumed on the next
// call to encodeInternal.
if (p == len-1) {
tail[tailLen++] = input[p];
} else if (p == len-2) {
tail[tailLen++] = input[p];
tail[tailLen++] = input[p+1];
}
}
this.op = op;
this.count = count;
return true;
}
}
private Base64() { } // don't instantiate
}
@@ -0,0 +1,33 @@
package com.litesuits.common.assist;
import java.util.Collection;
import java.util.Map;
/**
* 辅助判断
*
* @author mty
* @date 2013-6-10下午5:50:57
*/
public class Check {
public static boolean isEmpty(CharSequence str) {
return isNull(str) || str.length() == 0;
}
public static boolean isEmpty(Object[] os) {
return isNull(os) || os.length == 0;
}
public static boolean isEmpty(Collection<?> l) {
return isNull(l) || l.isEmpty();
}
public static boolean isEmpty(Map<?, ?> m) {
return isNull(m) || m.isEmpty();
}
public static boolean isNull(Object o) {
return o == null;
}
}
@@ -0,0 +1,64 @@
package com.litesuits.common.assist;
import android.hardware.Camera;
import android.os.Build;
import android.os.Handler;
/**
* <!-- 手电筒 -->
* Call requires API level 5
* <uses-permission android:name="android.permission.FLASHLIGHT"/>
* <uses-permission android:name="android.permission.CAMERA"/>
*
* @author MaTianyu
* @date 2014-11-04
*/
public class FlashLight {
private Camera camera;
private Handler handler = new Handler();
/**
* 超过3分钟自动关闭,防止损伤硬件
*/
private static final int OFF_TIME = 3 * 60 * 1000;
public boolean turnOnFlashLight() {
if (camera == null) {
camera = Camera.open();
camera.startPreview();
Camera.Parameters parameter = camera.getParameters();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ECLAIR) {
parameter.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
} else {
parameter.set("flash-mode", "torch");
}
camera.setParameters(parameter);
handler.removeCallbacksAndMessages(null);
handler.postDelayed(new Runnable() {
@Override
public void run() {
turnOffFlashLight();
}
}, OFF_TIME);
}
return true;
}
public boolean turnOffFlashLight() {
if (camera != null) {
handler.removeCallbacksAndMessages(null);
Camera.Parameters parameter = camera.getParameters();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ECLAIR) {
parameter.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
} else {
parameter.set("flash-mode", "off");
}
camera.setParameters(parameter);
camera.stopPreview();
camera.release();
camera = null;
}
return true;
}
}
@@ -0,0 +1,85 @@
package com.litesuits.common.assist;
import android.app.KeyguardManager;
import android.content.Context;
import android.os.Build;
import com.litesuits.android.log.Log;
/**
* <!-- 解锁 -->
* require <uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>
*
* @author MaTianyu
* @date 2014-12-12
*/
public class KeyguardLock {
KeyguardManager keyguardManager;
KeyguardManager.KeyguardLock keyguardLock;
public KeyguardLock(Context context, String tag) {
//获取系统服务
keyguardManager = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
//初始化键盘锁,可以锁定或解开键盘锁
keyguardLock = keyguardManager.newKeyguardLock(tag);
}
/**
* Call requires API level 16
*/
public boolean isKeyguardLocked() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
Log.e("Log : ", "can not call isKeyguardLocked if SDK_INT < 16 ");
return false;
} else {
return keyguardManager.isKeyguardLocked();
}
}
/**
* Call requires API level 16
*/
public boolean isKeyguardSecure() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
Log.e("Log : ", "can not call isKeyguardSecure if SDK_INT < 16 ");
return false;
} else {
return keyguardManager.isKeyguardSecure();
}
}
public boolean inKeyguardRestrictedInputMode() {
return keyguardManager.inKeyguardRestrictedInputMode();
}
public void disableKeyguard() {
keyguardLock.disableKeyguard();
}
public void reenableKeyguard() {
keyguardLock.reenableKeyguard();
}
public void release() {
if (keyguardLock != null) {
//禁用显示键盘锁定
keyguardLock.reenableKeyguard();
}
}
public KeyguardManager getKeyguardManager() {
return keyguardManager;
}
public void setKeyguardManager(KeyguardManager keyguardManager) {
this.keyguardManager = keyguardManager;
}
public KeyguardManager.KeyguardLock getKeyguardLock() {
return keyguardLock;
}
public void setKeyguardLock(KeyguardManager.KeyguardLock keyguardLock) {
this.keyguardLock = keyguardLock;
}
}
@@ -0,0 +1,316 @@
package com.litesuits.common.assist;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.telephony.TelephonyManager;
import com.litesuits.android.log.Log;
import java.lang.reflect.Method;
/**
* assist us in sensing state of the networks.
*
* need <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
*
* 半夜了,研究了一下Android的Network方面,发现网上有些文章理解的是不对的。
* 以下方法是我研究得出的结论和方法,如有误也感谢指出。
*
* @author MaTianyu
* 2014-1-8上午 00:33:11
*/
public class Network {
private static final String TAG = Network.class.getSimpleName();
public enum NetType {
None(1),
Mobile(2),
Wifi(4),
Other(8);
NetType(int value) {
this.value = value;
}
public int value;
}
public enum NetWorkType {
UnKnown(-1),
Wifi(1),
Net2G(2),
Net3G(3),
Net4G(4);
NetWorkType(int value) {
this.value = value;
}
public int value;
}
//
//public enum NetSubType {
// None(1),
// Mobile(2),
// Wifi(4),
// Other(8);
//
// NetType(int value) {
// this.value = value;
// }
//
// public int value;
//}
/**
* 获取ConnectivityManager
*/
public static ConnectivityManager getConnectivityManager(Context context) {
return (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
}
/**
* 获取ConnectivityManager
*/
public static TelephonyManager getTelephonyManager(Context context) {
return (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
}
/**
* 判断网络连接是否有效(此时可传输数据)。
*
* @return boolean 不管wifi,还是mobile net,只有当前在连接状态(可有效传输数据)才返回true,反之false。
*/
public static boolean isConnected(Context context) {
NetworkInfo net = getConnectivityManager(context).getActiveNetworkInfo();
return net != null && net.isConnected();
}
/**
* 判断有无网络正在连接中(查找网络、校验、获取IP等)。
*
* @return boolean 不管wifi,还是mobile net,只有当前在连接状态(可有效传输数据)才返回true,反之false。
*/
public static boolean isConnectedOrConnecting(Context context) {
NetworkInfo[] nets = getConnectivityManager(context).getAllNetworkInfo();
if (nets != null) {
for (NetworkInfo net : nets) {
if (net.isConnectedOrConnecting()) { return true; }
}
}
return false;
}
public static NetType getConnectedType(Context context) {
NetworkInfo net = getConnectivityManager(context).getActiveNetworkInfo();
if (net != null) {
switch (net.getType()) {
case ConnectivityManager.TYPE_WIFI:
return NetType.Wifi;
case ConnectivityManager.TYPE_MOBILE:
return NetType.Mobile;
default:
return NetType.Other;
}
}
return NetType.None;
}
/**
* 是否存在有效的WIFI连接
*/
public static boolean isWifiConnected(Context context) {
NetworkInfo net = getConnectivityManager(context).getActiveNetworkInfo();
return net != null && net.getType() == ConnectivityManager.TYPE_WIFI && net.isConnected();
}
/**
* 是否存在有效的移动连接
*
* @return boolean
*/
public static boolean isMobileConnected(Context context) {
NetworkInfo net = getConnectivityManager(context).getActiveNetworkInfo();
return net != null && net.getType() == ConnectivityManager.TYPE_MOBILE && net.isConnected();
}
/**
* 检测网络是否为可用状态
*/
public static boolean isAvailable(Context context) {
return isWifiAvailable(context) || (isMobileAvailable(context) && isMobileEnabled(context));
}
/**
* 判断是否有可用状态的Wifi,以下情况返回false:
* 1. 设备wifi开关关掉;
* 2. 已经打开飞行模式;
* 3. 设备所在区域没有信号覆盖;
* 4. 设备在漫游区域,且关闭了网络漫游。
*
* @return boolean wifi为可用状态(不一定成功连接,即Connected)即返回ture
*/
public static boolean isWifiAvailable(Context context) {
NetworkInfo[] nets = getConnectivityManager(context).getAllNetworkInfo();
if (nets != null) {
for (NetworkInfo net : nets) {
if (net.getType() == ConnectivityManager.TYPE_WIFI) { return net.isAvailable(); }
}
}
return false;
}
/**
* 判断有无可用状态的移动网络,注意关掉设备移动网络直接不影响此函数。
* 也就是即使关掉移动网络,那么移动网络也可能是可用的(彩信等服务),即返回true。
* 以下情况它是不可用的,将返回false:
* 1. 设备打开飞行模式;
* 2. 设备所在区域没有信号覆盖;
* 3. 设备在漫游区域,且关闭了网络漫游。
*
* @return boolean
*/
public static boolean isMobileAvailable(Context context) {
NetworkInfo[] nets = getConnectivityManager(context).getAllNetworkInfo();
if (nets != null) {
for (NetworkInfo net : nets) {
if (net.getType() == ConnectivityManager.TYPE_MOBILE) { return net.isAvailable(); }
}
}
return false;
}
/**
* 设备是否打开移动网络开关
*
* @return boolean 打开移动网络返回true,反之false
*/
public static boolean isMobileEnabled(Context context) {
try {
Method getMobileDataEnabledMethod = ConnectivityManager.class.getDeclaredMethod("getMobileDataEnabled");
getMobileDataEnabledMethod.setAccessible(true);
return (Boolean) getMobileDataEnabledMethod.invoke(getConnectivityManager(context));
} catch (Exception e) {
e.printStackTrace();
}
// 反射失败,默认开启
return true;
}
/**
* 打印当前各种网络状态
*
* @return boolean
*/
public static boolean printNetworkInfo(Context context) {
ConnectivityManager connectivity = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivity != null) {
NetworkInfo in = connectivity.getActiveNetworkInfo();
Log.i(TAG, "-------------$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$-------------");
Log.i(TAG, "getActiveNetworkInfo: " + in);
NetworkInfo[] info = connectivity.getAllNetworkInfo();
if (info != null) {
for (int i = 0; i < info.length; i++) {
// if (info[i].getType() == ConnectivityManager.TYPE_WIFI) {
Log.i(TAG, "NetworkInfo[" + i + "]isAvailable : " + info[i].isAvailable());
Log.i(TAG, "NetworkInfo[" + i + "]isConnected : " + info[i].isConnected());
Log.i(TAG, "NetworkInfo[" + i + "]isConnectedOrConnecting : " + info[i].isConnectedOrConnecting());
Log.i(TAG, "NetworkInfo[" + i + "]: " + info[i]);
// }
}
Log.i(TAG, "\n");
} else {
Log.i(TAG, "getAllNetworkInfo is null");
}
}
return false;
}
/**
* get connected network type by {@link ConnectivityManager}
*
* such as WIFI, MOBILE, ETHERNET, BLUETOOTH, etc.
*
* @return {@link ConnectivityManager#TYPE_WIFI}, {@link ConnectivityManager#TYPE_MOBILE},
* {@link ConnectivityManager#TYPE_ETHERNET}...
*/
public static int getConnectedTypeINT(Context context) {
NetworkInfo net = getConnectivityManager(context).getActiveNetworkInfo();
if (net != null) {
if (Log.isPrint) {
Log.i(TAG, "NetworkInfo: " + net.toString());
}
return net.getType();
}
return -1;
}
/**
* get network type by {@link TelephonyManager}
*
* such as 2G, 3G, 4G, etc.
*
* @return {@link TelephonyManager#NETWORK_TYPE_CDMA}, {@link TelephonyManager#NETWORK_TYPE_GPRS},
* {@link TelephonyManager#NETWORK_TYPE_LTE}...
*/
public static int getTelNetworkTypeINT(Context context) {
return getTelephonyManager(context).getNetworkType();
}
/**
* GPRS 2G(2.5) General Packet Radia Service 114kbps
* EDGE 2G(2.75G) Enhanced Data Rate for GSM Evolution 384kbps
* UMTS 3G WCDMA 联通3G Universal Mobile Telecommunication System 完整的3G移动通信技术标准
* CDMA 2G 电信 Code Division Multiple Access 码分多址
* EVDO_0 3G (EVDO 全程 CDMA2000 1xEV-DO) Evolution - Data Only (Data Optimized) 153.6kps - 2.4mbps 属于3G
* EVDO_A 3G 1.8mbps - 3.1mbps 属于3G过渡,3.5G
* 1xRTT 2G CDMA2000 1xRTT (RTT - 无线电传输技术) 144kbps 2G的过渡,
* HSDPA 3.5G 高速下行分组接入 3.5G WCDMA High Speed Downlink Packet Access 14.4mbps
* HSUPA 3.5G High Speed Uplink Packet Access 高速上行链路分组接入 1.4 - 5.8 mbps
* HSPA 3G (分HSDPA,HSUPA) High Speed Packet Access
* IDEN 2G Integrated Dispatch Enhanced Networks 集成数字增强型网络 (属于2G,来自维基百科)
* EVDO_B 3G EV-DO Rev.B 14.7Mbps 下行 3.5G
* LTE 4G Long Term Evolution FDD-LTE 和 TDD-LTE , 3G过渡,升级版 LTE Advanced 才是4G
* EHRPD 3G CDMA2000向LTE 4G的中间产物 Evolved High Rate Packet Data HRPD的升级
* HSPAP 3G HSPAP 比 HSDPA 快些
*
* @return {@link NetWorkType}
*/
public static NetWorkType getNetworkType(Context context) {
int type = getConnectedTypeINT(context);
switch (type) {
case ConnectivityManager.TYPE_WIFI:
return NetWorkType.Wifi;
case ConnectivityManager.TYPE_MOBILE:
case ConnectivityManager.TYPE_MOBILE_DUN:
case ConnectivityManager.TYPE_MOBILE_HIPRI:
case ConnectivityManager.TYPE_MOBILE_MMS:
case ConnectivityManager.TYPE_MOBILE_SUPL:
int teleType = getTelephonyManager(context).getNetworkType();
switch (teleType) {
case TelephonyManager.NETWORK_TYPE_GPRS:
case TelephonyManager.NETWORK_TYPE_EDGE:
case TelephonyManager.NETWORK_TYPE_CDMA:
case TelephonyManager.NETWORK_TYPE_1xRTT:
case TelephonyManager.NETWORK_TYPE_IDEN:
return NetWorkType.Net2G;
case TelephonyManager.NETWORK_TYPE_UMTS:
case TelephonyManager.NETWORK_TYPE_EVDO_0:
case TelephonyManager.NETWORK_TYPE_EVDO_A:
case TelephonyManager.NETWORK_TYPE_HSDPA:
case TelephonyManager.NETWORK_TYPE_HSUPA:
case TelephonyManager.NETWORK_TYPE_HSPA:
case TelephonyManager.NETWORK_TYPE_EVDO_B:
case TelephonyManager.NETWORK_TYPE_EHRPD:
case TelephonyManager.NETWORK_TYPE_HSPAP:
return NetWorkType.Net3G;
case TelephonyManager.NETWORK_TYPE_LTE:
return NetWorkType.Net4G;
default:
return NetWorkType.UnKnown;
}
default:
return NetWorkType.UnKnown;
}
}
}
@@ -0,0 +1,558 @@
package com.litesuits.common.assist;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.util.Log;
import com.litesuits.common.utils.ShellUtil;
import java.io.File;
/**
* modify form Trinea
*
* @author trinea
* @date 2014-12-10
*/
public class SilentInstaller {
/**
* Installation return code<br/>
* install success.
*/
public static final int INSTALL_SUCCEEDED = 1;
/**
* Installation return code<br/>
* the package is already installed.
*/
public static final int INSTALL_FAILED_ALREADY_EXISTS = -1;
/**
* Installation return code<br/>
* the package archive file is invalid.
*/
public static final int INSTALL_FAILED_INVALID_APK = -2;
/**
* Installation return code<br/>
* the URI passed in is invalid.
*/
public static final int INSTALL_FAILED_INVALID_URI = -3;
/**
* Installation return code<br/>
* the package manager service found that the device didn't have enough storage space to install the app.
*/
public static final int INSTALL_FAILED_INSUFFICIENT_STORAGE = -4;
/**
* Installation return code<br/>
* a package is already installed with the same name.
*/
public static final int INSTALL_FAILED_DUPLICATE_PACKAGE = -5;
/**
* Installation return code<br/>
* the requested shared user does not exist.
*/
public static final int INSTALL_FAILED_NO_SHARED_USER = -6;
/**
* Installation return code<br/>
* a previously installed package of the same name has a different signature than the new package (and the old
* package's data was not removed).
*/
public static final int INSTALL_FAILED_UPDATE_INCOMPATIBLE = -7;
/**
* Installation return code<br/>
* the new package is requested a shared user which is already installed on the device and does not have matching
* signature.
*/
public static final int INSTALL_FAILED_SHARED_USER_INCOMPATIBLE = -8;
/**
* Installation return code<br/>
* the new package uses a shared library that is not available.
*/
public static final int INSTALL_FAILED_MISSING_SHARED_LIBRARY = -9;
/**
* Installation return code<br/>
* the new package uses a shared library that is not available.
*/
public static final int INSTALL_FAILED_REPLACE_COULDNT_DELETE = -10;
/**
* Installation return code<br/>
* the new package failed while optimizing and validating its dex files, either because there was not enough storage
* or the validation failed.
*/
public static final int INSTALL_FAILED_DEXOPT = -11;
/**
* Installation return code<br/>
* the new package failed because the current SDK version is older than that required by the package.
*/
public static final int INSTALL_FAILED_OLDER_SDK = -12;
/**
* Installation return code<br/>
* the new package failed because it contains a content provider with the same authority as a provider already
* installed in the system.
*/
public static final int INSTALL_FAILED_CONFLICTING_PROVIDER = -13;
/**
* Installation return code<br/>
* the new package failed because the current SDK version is newer than that required by the package.
*/
public static final int INSTALL_FAILED_NEWER_SDK = -14;
/**
* Installation return code<br/>
* the new package failed because it has specified that it is a test-only package and the caller has not supplied
* the {@link #INSTALL_ALLOW_TEST} flag.
*/
public static final int INSTALL_FAILED_TEST_ONLY = -15;
/**
* Installation return code<br/>
* the package being installed contains native code, but none that is compatible with the the device's CPU_ABI.
*/
public static final int INSTALL_FAILED_CPU_ABI_INCOMPATIBLE = -16;
/**
* Installation return code<br/>
* the new package uses a feature that is not available.
*/
public static final int INSTALL_FAILED_MISSING_FEATURE = -17;
/**
* Installation return code<br/>
* a secure container mount point couldn't be accessed on external media.
*/
public static final int INSTALL_FAILED_CONTAINER_ERROR = -18;
/**
* Installation return code<br/>
* the new package couldn't be installed in the specified install location.
*/
public static final int INSTALL_FAILED_INVALID_INSTALL_LOCATION = -19;
/**
* Installation return code<br/>
* the new package couldn't be installed in the specified install location because the media is not available.
*/
public static final int INSTALL_FAILED_MEDIA_UNAVAILABLE = -20;
/**
* Installation return code<br/>
* the new package couldn't be installed because the verification timed out.
*/
public static final int INSTALL_FAILED_VERIFICATION_TIMEOUT = -21;
/**
* Installation return code<br/>
* the new package couldn't be installed because the verification did not succeed.
*/
public static final int INSTALL_FAILED_VERIFICATION_FAILURE = -22;
/**
* Installation return code<br/>
* the package changed from what the calling program expected.
*/
public static final int INSTALL_FAILED_PACKAGE_CHANGED = -23;
/**
* Installation return code<br/>
* the new package is assigned a different UID than it previously held.
*/
public static final int INSTALL_FAILED_UID_CHANGED = -24;
/**
* Installation return code<br/>
* if the parser was given a path that is not a file, or does not end with the expected '.apk' extension.
*/
public static final int INSTALL_PARSE_FAILED_NOT_APK = -100;
/**
* Installation return code<br/>
* if the parser was unable to retrieve the AndroidManifest.xml file.
*/
public static final int INSTALL_PARSE_FAILED_BAD_MANIFEST = -101;
/**
* Installation return code<br/>
* if the parser encountered an unexpected exception.
*/
public static final int INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION = -102;
/**
* Installation return code<br/>
* if the parser did not find any certificates in the .apk.
*/
public static final int INSTALL_PARSE_FAILED_NO_CERTIFICATES = -103;
/**
* Installation return code<br/>
* if the parser found inconsistent certificates on the files in the .apk.
*/
public static final int INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES = -104;
/**
* Installation return code<br/>
* if the parser encountered a CertificateEncodingException in one of the files in the .apk.
*/
public static final int INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING = -105;
/**
* Installation return code<br/>
* if the parser encountered a bad or missing package name in the manifest.
*/
public static final int INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME = -106;
/**
* Installation return code<br/>
* if the parser encountered a bad shared user id name in the manifest.
*/
public static final int INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID = -107;
/**
* Installation return code<br/>
* if the parser encountered some structural problem in the manifest.
*/
public static final int INSTALL_PARSE_FAILED_MANIFEST_MALFORMED = -108;
/**
* Installation return code<br/>
* if the parser did not find any actionable tags (instrumentation or application) in the manifest.
*/
public static final int INSTALL_PARSE_FAILED_MANIFEST_EMPTY = -109;
/**
* Installation return code<br/>
* if the system failed to install the package because of system issues.
*/
public static final int INSTALL_FAILED_INTERNAL_ERROR = -110;
/**
* Installation return code<br/>
* other reason
*/
public static final int INSTALL_FAILED_OTHER = -1000000;
/**
* Uninstall return code<br/>
* uninstall success.
*/
public static final int DELETE_SUCCEEDED = 1;
/**
* Uninstall return code<br/>
* uninstall fail if the system failed to delete the package for an unspecified reason.
*/
public static final int DELETE_FAILED_INTERNAL_ERROR = -1;
/**
* Uninstall return code<br/>
* uninstall fail if the system failed to delete the package because it is the active DevicePolicy manager.
*/
public static final int DELETE_FAILED_DEVICE_POLICY_MANAGER = -2;
/**
* Uninstall return code<br/>
* uninstall fail if pcakge name is invalid
*/
public static final int DELETE_FAILED_INVALID_PACKAGE = -3;
/**
* Uninstall return code<br/>
* uninstall fail if permission denied
*/
public static final int DELETE_FAILED_PERMISSION_DENIED = -4;
private static final String TAG = SilentInstaller.class.getSimpleName();
/**
* App installation location flags of android system
*/
public static final int APP_INSTALL_AUTO = 0;
public static final int APP_INSTALL_INTERNAL = 1;
public static final int APP_INSTALL_EXTERNAL = 2;
/**
* uninstall package and clear data of app silent by root
*
* @param context
* @param packageName package name of app
* @return
* @see #uninstallSilent(Context, String, boolean)
*/
public int uninstallSilent(Context context, String packageName) {
return uninstallSilent(context, packageName, false);
}
/**
* uninstall package silent by root
* <ul>
* <strong>Attentions:</strong>
* <li>Don't call this on the ui thread, it may costs some times.</li>
* <li>You should add <strong>android.permission.DELETE_PACKAGES</strong> in manifest, so no need to request root
* permission, if you are system app.</li>
* </ul>
*
* @param context file path of package
* @param packageName package name of app
* @param isKeepData whether keep the data and cache directories around after package removal
* @return <ul>
* <li>{@link #DELETE_SUCCEEDED} means uninstall success</li>
* <li>{@link #DELETE_FAILED_INTERNAL_ERROR} means internal error</li>
* <li>{@link #DELETE_FAILED_INVALID_PACKAGE} means package name error</li>
* <li>{@link #DELETE_FAILED_PERMISSION_DENIED} means permission denied</li>
*/
public int uninstallSilent(Context context, String packageName, boolean isKeepData) {
if (packageName == null || packageName.length() == 0) {
return DELETE_FAILED_INVALID_PACKAGE;
}
/**
* if context is system app, don't need root permission, but should add <uses-permission
* android:name="android.permission.DELETE_PACKAGES" /> in mainfest
**/
StringBuilder command = new StringBuilder().append("LD_LIBRARY_PATH=/vendor/lib:/system/lib pm uninstall")
.append(isKeepData ? " -k " : " ").append(packageName.replace(" ", "\\ "));
ShellUtil.CommandResult commandResult = ShellUtil.execCommand(command.toString(), !isSystemApplication(context), true);
if (commandResult.responseMsg != null
&& (commandResult.responseMsg.contains("Success") || commandResult.responseMsg.contains("success"))) {
return DELETE_SUCCEEDED;
}
Log.e(TAG,
new StringBuilder().append("uninstallSilent successMsg:").append(commandResult.responseMsg)
.append(", ErrorMsg:").append(commandResult.errorMsg).toString());
if (commandResult.errorMsg == null) {
return DELETE_FAILED_INTERNAL_ERROR;
}
if (commandResult.errorMsg.contains("Permission denied")) {
return DELETE_FAILED_PERMISSION_DENIED;
}
return DELETE_FAILED_INTERNAL_ERROR;
}
/**
* install package silent by root
* <ul>
* <strong>Attentions:</strong>
* <li>Don't call this on the ui thread, it may costs some times.</li>
* <li>You should add <strong>android.permission.INSTALL_PACKAGES</strong> in manifest, so no need to request root
* permission, if you are system app.</li>
* <li>Default pm install params is "-r".</li>
* </ul>
*
* @param context
* @param filePath file path of package
* @see #installSilent(Context, String, String)
*/
public int installSilent(Context context, String filePath) {
return installSilent(context, filePath, " -r " + getInstallLocationParams());
}
/**
* * install package silent by root
* <ul>
* <strong>Attentions:</strong>
* <li>Don't call this on the ui thread, it may costs some times.</li>
* <li>You should add <strong>android.permission.INSTALL_PACKAGES</strong> in manifest, so no need to request root
* permission, if you are system app.</li>
* </ul>
*/
public int installSilent(Context context, String filePath, String pmParams) {
if (filePath == null || filePath.length() == 0) {
return INSTALL_FAILED_INVALID_URI;
}
File file = new File(filePath);
if (file == null || file.length() <= 0 || !file.exists() || !file.isFile()) {
return INSTALL_FAILED_INVALID_URI;
}
/**
* if context is system app, don't need root permission, but should add <uses-permission
* android:name="android.permission.INSTALL_PACKAGES" /> in mainfest
**/
StringBuilder command = new StringBuilder().append("LD_LIBRARY_PATH=/vendor/lib:/system/lib pm install ")
.append(pmParams == null ? "" : pmParams).append(" ").append(filePath.replace(" ", "\\ "));
ShellUtil.CommandResult commandResult = ShellUtil.execCommand(command.toString(),
!isSystemApplication(context), true);
if (commandResult.responseMsg != null
&& (commandResult.responseMsg.contains("Success") || commandResult.responseMsg.contains("success"))) {
return INSTALL_SUCCEEDED;
}
Log.e(TAG,
new StringBuilder().append("installSilent successMsg:").append(commandResult.responseMsg)
.append(", ErrorMsg:").append(commandResult.errorMsg).toString());
if (commandResult.errorMsg == null) {
return INSTALL_FAILED_OTHER;
}
if (commandResult.errorMsg.contains("INSTALL_FAILED_ALREADY_EXISTS")) {
return INSTALL_FAILED_ALREADY_EXISTS;
}
if (commandResult.errorMsg.contains("INSTALL_FAILED_INVALID_APK")) {
return INSTALL_FAILED_INVALID_APK;
}
if (commandResult.errorMsg.contains("INSTALL_FAILED_INVALID_URI")) {
return INSTALL_FAILED_INVALID_URI;
}
if (commandResult.errorMsg.contains("INSTALL_FAILED_INSUFFICIENT_STORAGE")) {
return INSTALL_FAILED_INSUFFICIENT_STORAGE;
}
if (commandResult.errorMsg.contains("INSTALL_FAILED_DUPLICATE_PACKAGE")) {
return INSTALL_FAILED_DUPLICATE_PACKAGE;
}
if (commandResult.errorMsg.contains("INSTALL_FAILED_NO_SHARED_USER")) {
return INSTALL_FAILED_NO_SHARED_USER;
}
if (commandResult.errorMsg.contains("INSTALL_FAILED_UPDATE_INCOMPATIBLE")) {
return INSTALL_FAILED_UPDATE_INCOMPATIBLE;
}
if (commandResult.errorMsg.contains("INSTALL_FAILED_SHARED_USER_INCOMPATIBLE")) {
return INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
}
if (commandResult.errorMsg.contains("INSTALL_FAILED_MISSING_SHARED_LIBRARY")) {
return INSTALL_FAILED_MISSING_SHARED_LIBRARY;
}
if (commandResult.errorMsg.contains("INSTALL_FAILED_REPLACE_COULDNT_DELETE")) {
return INSTALL_FAILED_REPLACE_COULDNT_DELETE;
}
if (commandResult.errorMsg.contains("INSTALL_FAILED_DEXOPT")) {
return INSTALL_FAILED_DEXOPT;
}
if (commandResult.errorMsg.contains("INSTALL_FAILED_OLDER_SDK")) {
return INSTALL_FAILED_OLDER_SDK;
}
if (commandResult.errorMsg.contains("INSTALL_FAILED_CONFLICTING_PROVIDER")) {
return INSTALL_FAILED_CONFLICTING_PROVIDER;
}
if (commandResult.errorMsg.contains("INSTALL_FAILED_NEWER_SDK")) {
return INSTALL_FAILED_NEWER_SDK;
}
if (commandResult.errorMsg.contains("INSTALL_FAILED_TEST_ONLY")) {
return INSTALL_FAILED_TEST_ONLY;
}
if (commandResult.errorMsg.contains("INSTALL_FAILED_CPU_ABI_INCOMPATIBLE")) {
return INSTALL_FAILED_CPU_ABI_INCOMPATIBLE;
}
if (commandResult.errorMsg.contains("INSTALL_FAILED_MISSING_FEATURE")) {
return INSTALL_FAILED_MISSING_FEATURE;
}
if (commandResult.errorMsg.contains("INSTALL_FAILED_CONTAINER_ERROR")) {
return INSTALL_FAILED_CONTAINER_ERROR;
}
if (commandResult.errorMsg.contains("INSTALL_FAILED_INVALID_INSTALL_LOCATION")) {
return INSTALL_FAILED_INVALID_INSTALL_LOCATION;
}
if (commandResult.errorMsg.contains("INSTALL_FAILED_MEDIA_UNAVAILABLE")) {
return INSTALL_FAILED_MEDIA_UNAVAILABLE;
}
if (commandResult.errorMsg.contains("INSTALL_FAILED_VERIFICATION_TIMEOUT")) {
return INSTALL_FAILED_VERIFICATION_TIMEOUT;
}
if (commandResult.errorMsg.contains("INSTALL_FAILED_VERIFICATION_FAILURE")) {
return INSTALL_FAILED_VERIFICATION_FAILURE;
}
if (commandResult.errorMsg.contains("INSTALL_FAILED_PACKAGE_CHANGED")) {
return INSTALL_FAILED_PACKAGE_CHANGED;
}
if (commandResult.errorMsg.contains("INSTALL_FAILED_UID_CHANGED")) {
return INSTALL_FAILED_UID_CHANGED;
}
if (commandResult.errorMsg.contains("INSTALL_PARSE_FAILED_NOT_APK")) {
return INSTALL_PARSE_FAILED_NOT_APK;
}
if (commandResult.errorMsg.contains("INSTALL_PARSE_FAILED_BAD_MANIFEST")) {
return INSTALL_PARSE_FAILED_BAD_MANIFEST;
}
if (commandResult.errorMsg.contains("INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION")) {
return INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
}
if (commandResult.errorMsg.contains("INSTALL_PARSE_FAILED_NO_CERTIFICATES")) {
return INSTALL_PARSE_FAILED_NO_CERTIFICATES;
}
if (commandResult.errorMsg.contains("INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES")) {
return INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
}
if (commandResult.errorMsg.contains("INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING")) {
return INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING;
}
if (commandResult.errorMsg.contains("INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME")) {
return INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
}
if (commandResult.errorMsg.contains("INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID")) {
return INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
}
if (commandResult.errorMsg.contains("INSTALL_PARSE_FAILED_MANIFEST_MALFORMED")) {
return INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
}
if (commandResult.errorMsg.contains("INSTALL_PARSE_FAILED_MANIFEST_EMPTY")) {
return INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
}
if (commandResult.errorMsg.contains("INSTALL_FAILED_INTERNAL_ERROR")) {
return INSTALL_FAILED_INTERNAL_ERROR;
}
return INSTALL_FAILED_OTHER;
}
/**
* 获取当前系统安装应用的默认位置
*
* @return APP_INSTALL_AUTO or APP_INSTALL_INTERNAL or APP_INSTALL_EXTERNAL.
*/
public int getInstallLocation() {
ShellUtil.CommandResult commandResult = ShellUtil.execCommand(
"LD_LIBRARY_PATH=/vendor/lib:/system/lib pm get-install-location", false, true);
if (commandResult.result == 0 && commandResult.responseMsg != null && commandResult.responseMsg.length() > 0) {
try {
return Integer.parseInt(commandResult.responseMsg.substring(0, 1));
} catch (NumberFormatException e) {
e.printStackTrace();
}
}
return APP_INSTALL_AUTO;
}
/**
* get params for pm install location
*
* @return
*/
private String getInstallLocationParams() {
int location = getInstallLocation();
switch (location) {
case APP_INSTALL_INTERNAL:
return "-f";
case APP_INSTALL_EXTERNAL:
return "-s";
}
return "";
}
/**
* /**
* whether packageName is system application
*/
public boolean isSystemApplication(Context context) {
PackageManager packageManager = context.getPackageManager();
String packageName = context.getPackageName();
if (packageManager == null || packageName == null || packageName.length() == 0) {
return false;
}
try {
ApplicationInfo app = packageManager.getApplicationInfo(packageName, 0);
return (app != null && (app.flags & ApplicationInfo.FLAG_SYSTEM) > 0);
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
}
@@ -0,0 +1,65 @@
package com.litesuits.common.assist;
/**
* 时间均值计算器,只能用于单线程计时。
*
* @author MaTianyu
* 2013-12-12上午1:23:19
*/
public class TimeAverager {
/**
* 计时器
*/
private TimeCounter tc = new TimeCounter();
/**
* 均值器
*/
private Averager av = new Averager();
/**
* 一个计时开始
*/
public long start() {
return tc.start();
}
/**
* 一个计时结束
*/
public long end() {
long time = tc.duration();
av.add(time);
return time;
}
/**
* 一个计时结束,并且启动下次计时。
*/
public long endAndRestart() {
long time = tc.durationRestart();
av.add(time);
return time;
}
/**
* 求全部计时均值
*/
public Number average() {
return av.getAverage();
}
/**
* 打印全部时间值
*/
public void print() {
av.print();
}
/**
* 清楚数据
*/
public void clear() {
av.clear();
}
}
@@ -0,0 +1,58 @@
package com.litesuits.common.assist;
import com.litesuits.android.log.Log;
/**
* Time Counter.
*
* @author MaTianyu
* 2013-12-11下午3:42:28
*/
public class TimeCounter {
private static final String TAG = TimeCounter.class.getSimpleName();
private long t;
public TimeCounter() {
start();
}
/**
* Count start.
*/
public long start() {
t = System.currentTimeMillis();
return t;
}
/**
* Get duration and restart.
*/
public long durationRestart() {
long now = System.currentTimeMillis();
long d = now - t;
t = now;
return d;
}
/**
* Get duration.
*/
public long duration() {
return System.currentTimeMillis() - t;
}
/**
* Print duration.
*/
public void printDuration(String tag) {
Log.i(TAG, tag + " : " + duration());
}
/**
* Print duration.
*/
public void printDurationRestart(String tag) {
Log.i(TAG, tag + " : " + durationRestart());
}
}
@@ -0,0 +1,54 @@
package com.litesuits.common.assist;
import android.os.SystemClock;
import com.litesuits.android.log.Log;
/**
* @author 氢一 @http://litesuits.com
* @date 2017-05-27
*/
public class TimeKeeper {
private static final String TAG = "TimeKeeper";
private long keepTimeMillis;
private long startMillis;
public TimeKeeper(long keepTimeMillis) {
this.keepTimeMillis = keepTimeMillis;
}
public long getKeepTimeMillis() {
return keepTimeMillis;
}
public TimeKeeper setKeepTimeMillis(long keepTimeMillis) {
this.keepTimeMillis = keepTimeMillis;
return this;
}
public TimeKeeper printTimeCost(String event) {
long costMillis = SystemClock.elapsedRealtime() - startMillis;
Log.d(TAG, event + " cost time millis: " + costMillis);
return this;
}
public TimeKeeper startNow() {
startMillis = SystemClock.elapsedRealtime();
return this;
}
public TimeKeeper waitForEnd(OnEndCallback endCallback) {
long costMillis = SystemClock.elapsedRealtime() - startMillis;
long leftMillis = keepTimeMillis - costMillis;
if (leftMillis > 0) {
SystemClock.sleep(leftMillis);
endCallback.onEnd(costMillis, leftMillis);
} else {
endCallback.onEnd(costMillis, leftMillis);
}
return this;
}
public interface OnEndCallback {
void onEnd(long costTime, long leftTime);
}
}
@@ -0,0 +1,105 @@
package com.litesuits.common.assist;
import android.content.Context;
import android.widget.Toast;
/**
* @author MaTianyu
* @date 2014-07-31
*/
public class Toastor {
private Toast mToast;
private Context context;
public Toastor(Context context) {
this.context = context.getApplicationContext();
}
public Toast getSingletonToast(int resId) {
if (mToast == null) {
mToast = Toast.makeText(context, resId, Toast.LENGTH_SHORT);
}else{
mToast.setText(resId);
}
return mToast;
}
public Toast getSingletonToast(String text) {
if (mToast == null) {
mToast = Toast.makeText(context, text, Toast.LENGTH_SHORT);
}else{
mToast.setText(text);
}
return mToast;
}
public Toast getSingleLongToast(int resId) {
if (mToast == null) {
mToast = Toast.makeText(context, resId, Toast.LENGTH_LONG);
}else{
mToast.setText(resId);
}
return mToast;
}
public Toast getSingleLongToast(String text) {
if (mToast == null) {
mToast = Toast.makeText(context, text, Toast.LENGTH_LONG);
}else{
mToast.setText(text);
}
return mToast;
}
public Toast getToast(int resId) {
return Toast.makeText(context, resId, Toast.LENGTH_SHORT);
}
public Toast getToast(String text) {
return Toast.makeText(context, text, Toast.LENGTH_SHORT);
}
public Toast getLongToast(int resId) {
return Toast.makeText(context, resId, Toast.LENGTH_LONG);
}
public Toast getLongToast(String text) {
return Toast.makeText(context, text, Toast.LENGTH_LONG);
}
public void showSingletonToast(int resId) {
getSingletonToast(resId).show();
}
public void showSingletonToast(String text) {
getSingletonToast(text).show();
}
public void showSingleLongToast(int resId) {
getSingleLongToast(resId).show();
}
public void showSingleLongToast(String text) {
getSingleLongToast(text).show();
}
public void showToast(int resId) {
getToast(resId).show();
}
public void showToast(String text) {
getToast(text).show();
}
public void showLongToast(int resId) {
getLongToast(resId).show();
}
public void showLongToast(String text) {
getLongToast(text).show();
}
}
@@ -0,0 +1,84 @@
package com.litesuits.common.assist;
import android.content.Context;
import android.os.Build;
import android.os.PowerManager;
import com.litesuits.android.log.Log;
/**
* <!-- 亮屏 -->
* require <uses-permission android:name="android.permission.WAKE_LOCK"/>
*
* @author MaTianyu
* @date 2014-11-04
*/
public class WakeLock {
PowerManager powerManager;
PowerManager.WakeLock wakeLock;
public WakeLock(Context context, String tag) {
////获取电源的服务 声明电源管理器
powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.FULL_WAKE_LOCK, tag);
}
/**
* Call requires API level 7
*/
public boolean isScreenOn() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ECLAIR_MR1) {
Log.e("Log : ", "can not call isScreenOn if SDK_INT < 7 ");
return false;
} else {
return powerManager.isScreenOn();
}
}
public void turnScreenOn() {
//点亮亮屏
Log.i("Log : ", "PowerManager.WakeLock : wakeLock.isHeld: " + wakeLock.isHeld());
if (!wakeLock.isHeld()) {
Log.i("Log : ", "PowerManager.WakeLock : 点亮屏幕");
wakeLock.acquire();
}
}
public void turnScreenOff() {
//释放亮屏
Log.i("Log : ", "PowerManager.WakeLock : wakeLock.isHeld: " + wakeLock.isHeld());
if (wakeLock.isHeld()) {
Log.i("Log : ", "PowerManager.WakeLock : 灭掉屏幕");
try {
wakeLock.release();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void release() {
if (wakeLock != null && wakeLock.isHeld()) {
try {
wakeLock.release();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public PowerManager.WakeLock getWakeLock() {
return wakeLock;
}
public void setWakeLock(PowerManager.WakeLock wakeLock) {
this.wakeLock = wakeLock;
}
public PowerManager getPowerManager() {
return powerManager;
}
public void setPowerManager(PowerManager powerManager) {
this.powerManager = powerManager;
}
}
@@ -0,0 +1,128 @@
/*
* Copyright (C) 2013 litesuits.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.litesuits.common.data;
import android.content.Context;
import android.content.SharedPreferences;
import com.litesuits.android.log.Log;
import com.litesuits.common.data.cipher.Cipher;
import com.litesuits.common.utils.ByteUtil;
import com.litesuits.common.utils.HexUtil;
/**
* @author MaTianyu
* @date 14-7-10
*/
public class DataKeeper {
private SharedPreferences sp;
public static final String KEY_PK_HOME = "msg_pk_home";
public static final String KEY_PK_NEW = "msg_pk_new";
private static final String TAG = DataKeeper.class.getSimpleName();
public DataKeeper(Context context, String fileName) {
sp = context.getSharedPreferences(fileName, Context.MODE_PRIVATE);
}
/**
* *************** get ******************
*/
public String get(String key, String defValue) {
return sp.getString(key, defValue);
}
public boolean get(String key, boolean defValue) {
return sp.getBoolean(key, defValue);
}
public float get(String key, float defValue) {
return sp.getFloat(key, defValue);
}
public int getInt(String key, int defValue) {
return sp.getInt(key, defValue);
}
public long get(String key, long defValue) {
return sp.getLong(key, defValue);
}
public Object get(String key) {
return get(key, (Cipher) null);
}
public Object get(String key, Cipher cipher) {
try {
String hex = get(key, (String) null);
if (hex == null) return null;
byte[] bytes = HexUtil.decodeHex(hex.toCharArray());
if (cipher != null) bytes = cipher.decrypt(bytes);
Object obj = ByteUtil.byteToObject(bytes);
Log.i(TAG, key + " get: " + obj);
return obj;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* *************** put ******************
*/
public void put(String key, Object ser) {
put(key, ser, null);
}
public void put(String key, Object ser, Cipher cipher) {
try {
Log.i(TAG, key + " put: " + ser);
if (ser == null) {
sp.edit().remove(key).commit();
} else {
byte[] bytes = ByteUtil.objectToByte(ser);
if (cipher != null) bytes = cipher.encrypt(bytes);
put(key, HexUtil.encodeHexStr(bytes));
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void put(String key, String value) {
if (value == null) {
sp.edit().remove(key).commit();
} else {
sp.edit().putString(key, value).commit();
}
}
public void put(String key, boolean value) {
sp.edit().putBoolean(key, value).commit();
}
public void put(String key, float value) {
sp.edit().putFloat(key, value).commit();
}
public void put(String key, long value) {
sp.edit().putLong(key, value).commit();
}
public void putInt(String key, int value) {
sp.edit().putInt(key, value).commit();
}
}
@@ -0,0 +1,36 @@
package com.litesuits.common.data.cipher;
import com.litesuits.common.assist.Base64;
/**
* @author MaTianyu
* @date 14-7-31
*/
public class Base64Cipher extends Cipher {
private Cipher cipher;
public Base64Cipher() {
}
public Base64Cipher(Cipher cipher) {
this.cipher = cipher;
}
@Override
public byte[] decrypt(byte[] res) {
res = Base64.decode(res, Base64.DEFAULT);
if (cipher != null) {
res = cipher.decrypt(res);
}
return res;
}
@Override
public byte[] encrypt(byte[] res) {
if (cipher != null) {
res = cipher.encrypt(res);
}
return Base64.encode(res, Base64.DEFAULT);
}
}
@@ -0,0 +1,9 @@
package com.litesuits.common.data.cipher;
/**
* @author MaTianyu
* @date 14-7-31
*/
public abstract class Cipher implements Encrypt,Decrypt{
}
@@ -0,0 +1,9 @@
package com.litesuits.common.data.cipher;
/**
* @author MaTianyu
* @date 14-7-31
*/
public interface Decrypt {
public byte[] decrypt(byte[] res);
}
@@ -0,0 +1,9 @@
package com.litesuits.common.data.cipher;
/**
* @author MaTianyu
* @date 14-7-31
*/
public interface Encrypt {
public byte[] encrypt(byte[] res);
}
@@ -0,0 +1,37 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.litesuits.common.io;
import java.nio.charset.Charset;
/**
* Charsets
*/
public class Charsets {
public static Charset toCharset(Charset charset) {
return charset == null ? Charset.defaultCharset() : charset;
}
public static Charset toCharset(String charset) {
return charset == null ? Charset.defaultCharset() : Charset.forName(charset);
}
public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
public static final Charset US_ASCII = Charset.forName("US-ASCII");
public static final Charset UTF_16 = Charset.forName("UTF-16");
public static final Charset UTF_16BE = Charset.forName("UTF-16BE");
public static final Charset UTF_16LE = Charset.forName("UTF-16LE");
public static final Charset UTF_8 = Charset.forName("UTF-8");
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,27 @@
package com.litesuits.common.io;
import android.os.Build;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
/**
* @author MaTianyu
* @date 2014-12-05
*/
public class StringCodingUtils {
public static byte[] getBytes(String src, Charset charSet) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.GINGERBREAD) {
try {
return src.getBytes(charSet.name());
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
} else {
return src.getBytes(charSet);
}
}
}
@@ -0,0 +1,357 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.litesuits.common.io.stream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.SequenceInputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* This class implements an output stream in which the data is
* written into a byte array. The buffer automatically grows as data
* is written to it.
* <p>
* The data can be retrieved using <code>toByteArray()</code> and
* <code>toString()</code>.
* <p>
* Closing a <tt>ByteArrayOutputStream</tt> has no effect. The methods in
* this class can be called after the stream has been closed without
* generating an <tt>IOException</tt>.
* <p>
* This is an alternative implementation of the {@link java.io.ByteArrayOutputStream}
* class. The original implementation only allocates 32 bytes at the beginning.
* As this class is designed for heavy duty it starts at 1024 bytes. In contrast
* to the original it doesn't reallocate the whole memory block but allocates
* additional buffers. This way no buffers need to be garbage collected and
* the contents don't have to be copied to the new buffer. This class is
* designed to behave exactly like the original. The only exception is the
* deprecated toString(int) method that has been ignored.
*
* @version $Id: ByteArrayOutputStream.java 1304052 2012-03-22 20:55:29Z ggregory $
*/
public class ByteArrayOutputStream extends OutputStream {
/** A singleton empty byte array. */
private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
/** The list of buffers, which grows and never reduces. */
private final List<byte[]> buffers = new ArrayList<byte[]>();
/** The index of the current buffer. */
private int currentBufferIndex;
/** The total count of bytes in all the filled buffers. */
private int filledBufferSum;
/** The current buffer. */
private byte[] currentBuffer;
/** The total count of bytes written. */
private int count;
/**
* Creates a new byte array output stream. The buffer capacity is
* initially 1024 bytes, though its size increases if necessary.
*/
public ByteArrayOutputStream() {
this(1024);
}
/**
* Creates a new byte array output stream, with a buffer capacity of
* the specified size, in bytes.
*
* @param size the initial size
* @throws IllegalArgumentException if size is negative
*/
public ByteArrayOutputStream(int size) {
if (size < 0) {
throw new IllegalArgumentException(
"Negative initial size: " + size);
}
synchronized (this) {
needNewBuffer(size);
}
}
/**
* Makes a new buffer available either by allocating
* a new one or re-cycling an existing one.
*
* @param newcount the size of the buffer if one is created
*/
private void needNewBuffer(int newcount) {
if (currentBufferIndex < buffers.size() - 1) {
//Recycling old buffer
filledBufferSum += currentBuffer.length;
currentBufferIndex++;
currentBuffer = buffers.get(currentBufferIndex);
} else {
//Creating new buffer
int newBufferSize;
if (currentBuffer == null) {
newBufferSize = newcount;
filledBufferSum = 0;
} else {
newBufferSize = Math.max(
currentBuffer.length << 1,
newcount - filledBufferSum);
filledBufferSum += currentBuffer.length;
}
currentBufferIndex++;
currentBuffer = new byte[newBufferSize];
buffers.add(currentBuffer);
}
}
/**
* Write the bytes to byte array.
* @param b the bytes to write
* @param off The start offset
* @param len The number of bytes to write
*/
@Override
public void write(byte[] b, int off, int len) {
if ((off < 0)
|| (off > b.length)
|| (len < 0)
|| ((off + len) > b.length)
|| ((off + len) < 0)) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return;
}
synchronized (this) {
int newcount = count + len;
int remaining = len;
int inBufferPos = count - filledBufferSum;
while (remaining > 0) {
int part = Math.min(remaining, currentBuffer.length - inBufferPos);
System.arraycopy(b, off + len - remaining, currentBuffer, inBufferPos, part);
remaining -= part;
if (remaining > 0) {
needNewBuffer(newcount);
inBufferPos = 0;
}
}
count = newcount;
}
}
/**
* Write a byte to byte array.
* @param b the byte to write
*/
@Override
public synchronized void write(int b) {
int inBufferPos = count - filledBufferSum;
if (inBufferPos == currentBuffer.length) {
needNewBuffer(count + 1);
inBufferPos = 0;
}
currentBuffer[inBufferPos] = (byte) b;
count++;
}
/**
* Writes the entire contents of the specified input stream to this
* byte stream. Bytes from the input stream are read directly into the
* internal buffers of this streams.
*
* @param in the input stream to read from
* @return total number of bytes read from the input stream
* (and written to this stream)
* @throws java.io.IOException if an I/O error occurs while reading the input stream
* @since 1.4
*/
public synchronized int write(InputStream in) throws IOException {
int readCount = 0;
int inBufferPos = count - filledBufferSum;
int n = in.read(currentBuffer, inBufferPos, currentBuffer.length - inBufferPos);
while (n != -1) {
readCount += n;
inBufferPos += n;
count += n;
if (inBufferPos == currentBuffer.length) {
needNewBuffer(currentBuffer.length);
inBufferPos = 0;
}
n = in.read(currentBuffer, inBufferPos, currentBuffer.length - inBufferPos);
}
return readCount;
}
/**
* Return the current size of the byte array.
* @return the current size of the byte array
*/
public synchronized int size() {
return count;
}
/**
* Closing a <tt>ByteArrayOutputStream</tt> has no effect. The methods in
* this class can be called after the stream has been closed without
* generating an <tt>IOException</tt>.
*
* @throws java.io.IOException never (this method should not declare this exception
* but it has to now due to backwards compatability)
*/
@Override
public void close() throws IOException {
//nop
}
/**
* @see java.io.ByteArrayOutputStream#reset()
*/
public synchronized void reset() {
count = 0;
filledBufferSum = 0;
currentBufferIndex = 0;
currentBuffer = buffers.get(currentBufferIndex);
}
/**
* Writes the entire contents of this byte stream to the
* specified output stream.
*
* @param out the output stream to write to
* @throws java.io.IOException if an I/O error occurs, such as if the stream is closed
* @see java.io.ByteArrayOutputStream#writeTo(java.io.OutputStream)
*/
public synchronized void writeTo(OutputStream out) throws IOException {
int remaining = count;
for (byte[] buf : buffers) {
int c = Math.min(buf.length, remaining);
out.write(buf, 0, c);
remaining -= c;
if (remaining == 0) {
break;
}
}
}
/**
* Fetches entire contents of an <code>InputStream</code> and represent
* same data as result InputStream.
* <p>
* This method is useful where,
* <ul>
* <li>Source InputStream is slow.</li>
* <li>It has network resources associated, so we cannot keep it open for
* long time.</li>
* <li>It has network timeout associated.</li>
* </ul>
* It can be used in favor of {@link #toByteArray()}, since it
* avoids unnecessary allocation and copy of byte[].<br>
* This method buffers the input internally, so there is no need to use a
* <code>BufferedInputStream</code>.
*
* @param input Stream to be fully buffered.
* @return A fully buffered stream.
* @throws java.io.IOException if an I/O error occurs
* @since 2.0
*/
public static InputStream toBufferedInputStream(InputStream input)
throws IOException {
ByteArrayOutputStream output = new ByteArrayOutputStream();
output.write(input);
return output.toBufferedInputStream();
}
/**
* Gets the current contents of this byte stream as a Input Stream. The
* returned stream is backed by buffers of <code>this</code> stream,
* avoiding memory allocation and copy, thus saving space and time.<br>
*
* @return the current contents of this output stream.
* @see java.io.ByteArrayOutputStream#toByteArray()
* @see #reset()
* @since 2.0
*/
private InputStream toBufferedInputStream() {
int remaining = count;
if (remaining == 0) {
return new ClosedInputStream();
}
List<ByteArrayInputStream> list = new ArrayList<ByteArrayInputStream>(buffers.size());
for (byte[] buf : buffers) {
int c = Math.min(buf.length, remaining);
list.add(new ByteArrayInputStream(buf, 0, c));
remaining -= c;
if (remaining == 0) {
break;
}
}
return new SequenceInputStream(Collections.enumeration(list));
}
/**
* Gets the curent contents of this byte stream as a byte array.
* The result is independent of this stream.
*
* @return the current contents of this output stream, as a byte array
* @see java.io.ByteArrayOutputStream#toByteArray()
*/
public synchronized byte[] toByteArray() {
int remaining = count;
if (remaining == 0) {
return EMPTY_BYTE_ARRAY;
}
byte newbuf[] = new byte[remaining];
int pos = 0;
for (byte[] buf : buffers) {
int c = Math.min(buf.length, remaining);
System.arraycopy(buf, 0, newbuf, pos, c);
pos += c;
remaining -= c;
if (remaining == 0) {
break;
}
}
return newbuf;
}
/**
* Gets the curent contents of this byte stream as a string.
* @return the contents of the byte array as a String
* @see java.io.ByteArrayOutputStream#toString()
*/
@Override
public String toString() {
return new String(toByteArray());
}
/**
* Gets the curent contents of this byte stream as a string
* using the specified encoding.
*
* @param enc the name of the character encoding
* @return the string converted from the byte array
* @throws java.io.UnsupportedEncodingException if the encoding is not supported
* @see java.io.ByteArrayOutputStream#toString(String)
*/
public String toString(String enc) throws UnsupportedEncodingException {
return new String(toByteArray(), enc);
}
}
@@ -0,0 +1,49 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.litesuits.common.io.stream;
import java.io.InputStream;
/**
* Closed input stream. This stream returns -1 to all attempts to read
* something from the stream.
* <p>
* Typically uses of this class include testing for corner cases in methods
* that accept input streams and acting as a sentinel value instead of a
* {@code null} input stream.
*
* @version $Id: ClosedInputStream.java 1307459 2012-03-30 15:11:44Z ggregory $
* @since 1.4
*/
public class ClosedInputStream extends InputStream {
/**
* A singleton.
*/
public static final ClosedInputStream CLOSED_INPUT_STREAM = new ClosedInputStream();
/**
* Returns -1 to indicate that the stream is closed.
*
* @return always -1
*/
@Override
public int read() {
return -1;
}
}
@@ -0,0 +1,160 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.litesuits.common.io.stream;
import java.io.Serializable;
import java.io.Writer;
/**
* {@link java.io.Writer} implementation that outputs to a {@link StringBuilder}.
* <p>
* <strong>NOTE:</strong> This implementation, as an alternative to
* <code>java.io.StringWriter</code>, provides an <i>un-synchronized</i>
* (i.e. for use in a single thread) implementation for better performance.
* For safe usage with multiple {@link Thread}s then
* <code>java.io.StringWriter</code> should be used.
*
* @version $Id: StringBuilderWriter.java 1304052 2012-03-22 20:55:29Z ggregory $
* @since 2.0
*/
public class StringBuilderWriter extends Writer implements Serializable {
private final StringBuilder builder;
/**
* Construct a new {@link StringBuilder} instance with default capacity.
*/
public StringBuilderWriter() {
this.builder = new StringBuilder();
}
/**
* Construct a new {@link StringBuilder} instance with the specified capacity.
*
* @param capacity The initial capacity of the underlying {@link StringBuilder}
*/
public StringBuilderWriter(int capacity) {
this.builder = new StringBuilder(capacity);
}
/**
* Construct a new instance with the specified {@link StringBuilder}.
*
* @param builder The String builder
*/
public StringBuilderWriter(StringBuilder builder) {
this.builder = builder != null ? builder : new StringBuilder();
}
/**
* Append a single character to this Writer.
*
* @param value The character to append
* @return This writer instance
*/
@Override
public Writer append(char value) {
builder.append(value);
return this;
}
/**
* Append a character sequence to this Writer.
*
* @param value The character to append
* @return This writer instance
*/
@Override
public Writer append(CharSequence value) {
builder.append(value);
return this;
}
/**
* Append a portion of a character sequence to the {@link StringBuilder}.
*
* @param value The character to append
* @param start The index of the first character
* @param end The index of the last character + 1
* @return This writer instance
*/
@Override
public Writer append(CharSequence value, int start, int end) {
builder.append(value, start, end);
return this;
}
/**
* Closing this writer has no effect.
*/
@Override
public void close() {
}
/**
* Flushing this writer has no effect.
*/
@Override
public void flush() {
}
/**
* Write a String to the {@link StringBuilder}.
*
* @param value The value to write
*/
@Override
public void write(String value) {
if (value != null) {
builder.append(value);
}
}
/**
* Write a portion of a character array to the {@link StringBuilder}.
*
* @param value The value to write
* @param offset The index of the first character
* @param length The number of characters to write
*/
@Override
public void write(char[] value, int offset, int length) {
if (value != null) {
builder.append(value, offset, length);
}
}
/**
* Return the underlying builder.
*
* @return The underlying builder
*/
public StringBuilder getBuilder() {
return builder;
}
/**
* Returns {@link StringBuilder#toString()}.
*
* @return The contents of the String builder.
*/
@Override
public String toString() {
return builder.toString();
}
}
@@ -0,0 +1,152 @@
package com.litesuits.common.receiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import com.litesuits.android.log.Log;
import com.litesuits.common.assist.Check;
/**
* <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
* <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
* <p/>
* action: android.intent.action.PHONE_STATE; android.intent.action.NEW_OUTGOING_CALL;
* <p/>
* 去电时:
* 未接:phone_state=OFFHOOK;
* 挂断:phone_state=IDLE
* 来电时:
* 未接:phone_state=RINGING
* 已接:phone_state=OFFHOOK;
* 挂断:phone_state=IDLE
*
* @author MaTianyu
* @date 2015-03-09
*/
public class PhoneReceiver extends BroadcastReceiver {
private static final String TAG = "PhoneReceiver";
private static final String RINGING = "RINGING";
private static final String OFFHOOK = "OFFHOOK";
private static final String IDLE = "IDLE";
private static final String PHONE_STATE = "android.intent.action.PHONE_STATE";
private static final String NEW_OUTGOING_CALL = "android.intent.action.NEW_OUTGOING_CALL";
private static final String INTENT_STATE = "state";
private static final String INTENT_INCOMING_NUMBER = "incoming_number";
private PhoneListener phoneListener;
private boolean isDialOut;
private String number;
@Override
public void onReceive(Context context, Intent intent) {
if (Log.isPrint) {
Log.i(TAG, "action: " + intent.getAction());
Log.d(TAG, "intent : ");
Bundle bundle = intent.getExtras();
for (String key : bundle.keySet()) {
Log.d(TAG, key + " : " + bundle.get(key));
}
}
if (NEW_OUTGOING_CALL.equals(intent.getAction())) {
isDialOut = true;
String outNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
if (!Check.isEmpty(outNumber)) {
this.number = outNumber;
}
if (phoneListener != null) {
phoneListener.onPhoneStateChanged(CallState.Outgoing, number);
}
} else if (PHONE_STATE.equals(intent.getAction())) {
String state = intent.getStringExtra(INTENT_STATE);
String inNumber = intent.getStringExtra(INTENT_INCOMING_NUMBER);
if (!Check.isEmpty(inNumber)) {
this.number = inNumber;
}
if (RINGING.equals(state)) {
isDialOut = false;
if (phoneListener != null) {
phoneListener.onPhoneStateChanged(CallState.IncomingRing, number);
}
} else if (OFFHOOK.equals(state)) {
if (!isDialOut && phoneListener != null) {
phoneListener.onPhoneStateChanged(CallState.Incoming, number);
}
} else if (IDLE.equals(state)) {
if (isDialOut) {
if (phoneListener != null) {
phoneListener.onPhoneStateChanged(CallState.OutgoingEnd, number);
}
} else {
if (phoneListener != null) {
phoneListener.onPhoneStateChanged(CallState.IncomingEnd, number);
}
}
}
}
}
/**
* 去电时:
* 未接:phone_state=OFFHOOK;
* 挂断:phone_state=IDLE
* 来电时:
* 未接:phone_state=RINGING
* 已接:phone_state=OFFHOOK;
* 挂断:phone_state=IDLE
*/
//public void registerCallStateListener(Context context, PhoneStateListener listener) {
// try {
// //获取电话通讯服务
// TelephonyManager tpm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
// tpm.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
// } catch (Exception e) {
// e.printStackTrace();
// }
//}
public void registerReceiver(Context context, PhoneListener phoneListener) {
try {
IntentFilter filter = new IntentFilter();
filter.addAction("android.intent.action.PHONE_STATE");
filter.addAction("android.intent.action.NEW_OUTGOING_CALL");
filter.setPriority(Integer.MAX_VALUE);
context.registerReceiver(this, filter);
this.phoneListener = phoneListener;
} catch (Exception e) {
e.printStackTrace();
}
}
public void unRegisterReceiver(Context context) {
try {
context.unregisterReceiver(this);
} catch (Exception e) {
e.printStackTrace();
}
}
public interface PhoneListener {
void onPhoneStateChanged(CallState state, String number);
}
/**
* 分别是:
* <p/>
* 播出电话
* 播出电话结束
* 接入电话铃响
* 接入通话中
* 接入通话完毕
*/
public enum CallState {
Outgoing,
OutgoingEnd,
IncomingRing,
Incoming,
IncomingEnd
}
}
@@ -0,0 +1,61 @@
package com.litesuits.common.receiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import com.litesuits.android.log.Log;
public class ScreenReceiver extends BroadcastReceiver {
private String TAG = "ScreenActionReceiver";
private ScreenListener screenListener;
public ScreenReceiver() {
}
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(Intent.ACTION_SCREEN_ON)) {
Log.d(TAG, "屏幕解锁广播...");
if (screenListener != null) {
screenListener.screenOn();
}
} else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
Log.d(TAG, "屏幕加锁广播...");
if (screenListener != null) {
screenListener.screenOff();
}
}
}
public void registerScreenReceiver(Context context, ScreenListener screenListener) {
try {
this.screenListener = screenListener;
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_SCREEN_ON);
Log.d(TAG, "注册屏幕解锁、加锁广播接收者...");
context.registerReceiver(this, filter);
} catch (Exception e) {
e.printStackTrace();
}
}
public void unRegisterScreenReceiver(Context context) {
try {
context.unregisterReceiver(this);
Log.d(TAG, "注销屏幕解锁、加锁广播接收者...");
} catch (Exception e) {
e.printStackTrace();
}
}
public static interface ScreenListener {
public void screenOn();
public void screenOff();
}
}
@@ -0,0 +1,144 @@
package com.litesuits.common.receiver;
import android.content.*;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.telephony.SmsManager;
import android.telephony.SmsMessage;
import com.litesuits.android.log.Log;
import java.util.List;
/**
* Call requires API level 4
* <uses-permission android:name="android.permission.RECEIVE_SMS"/>
* <p/>
* action: android.provider.Telephony.SMS_RECEIVED
*
* @author MaTianyu
* @date 14-7-23
*/
public class SmsReceiver extends BroadcastReceiver {
private static final String TAG = SmsReceiver.class.getSimpleName();
private SmsListener smsListener;
public SmsReceiver() {
}
@Override
public void onReceive(Context context, Intent intent) {
try {
if (Log.isPrint) {
Log.i(TAG, "收到广播:" + intent.getAction());
Bundle bundle = intent.getExtras();
for (String key : bundle.keySet()) {
Log.i(TAG, key + " : " + bundle.get(key));
}
}
Object[] pdus = (Object[]) intent.getExtras().get("pdus");
String fromAddress = null;
String serviceCenterAddress = null;
if (pdus != null) {
String msgBody = "";
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.DONUT) {
for (Object obj : pdus) {
SmsMessage sms = SmsMessage.createFromPdu((byte[]) obj);
msgBody += sms.getMessageBody();
fromAddress = sms.getOriginatingAddress();
serviceCenterAddress = sms.getServiceCenterAddress();
if (smsListener != null) {
smsListener.onMessage(sms);
}
//Log.i(TAG, "getDisplayMessageBody" + sms.getDisplayMessageBody());
//Log.i(TAG, "getDisplayOriginatingAddress" + sms.getDisplayOriginatingAddress());
//Log.i(TAG, "getEmailBody" + sms.getEmailBody());
//Log.i(TAG, "getEmailFrom" + sms.getEmailFrom());
//Log.i(TAG, "getMessageBody" + sms.getMessageBody());
//Log.i(TAG, "getOriginatingAddress" + sms.getOriginatingAddress());
//Log.i(TAG, "getPseudoSubject" + sms.getPseudoSubject());
//Log.i(TAG, "getServiceCenterAddress" + sms.getServiceCenterAddress());
//Log.i(TAG, "getIndexOnIcc" + sms.getIndexOnIcc());
//Log.i(TAG, "getMessageClass" + sms.getMessageClass());
//Log.i(TAG, "getUserData" + new String(sms.getUserData()));
}
}
if (smsListener != null) {
smsListener.onMessage(msgBody, fromAddress, serviceCenterAddress);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void registerSmsReceiver(Context context, SmsListener smsListener) {
try {
this.smsListener = smsListener;
IntentFilter filter = new IntentFilter();
filter.addAction("android.provider.Telephony.SMS_RECEIVED");
filter.setPriority(Integer.MAX_VALUE);
context.registerReceiver(this, filter);
} catch (Exception e) {
e.printStackTrace();
}
}
public void unRegisterSmsReceiver(Context context) {
try {
context.unregisterReceiver(this);
} catch (Exception e) {
e.printStackTrace();
}
}
public static abstract class SmsListener {
public abstract void onMessage(String msg, String fromAddress, String serviceCenterAddress);
public void onMessage(SmsMessage msg) {}
}
/**
* Call requires API level 4
* <uses-permission android:name="android.permission.SEND_SMS"/>
*
* @param phone
* @param msg
*/
public static void sendMsgToPhone(String phone, String msg) {
Log.i(TAG, "发送手机:" + phone + " ,内容: " + msg);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.DONUT) {
SmsManager manager = SmsManager.getDefault();
List<String> texts = manager.divideMessage(msg);
for (String txt : texts) {
manager.sendTextMessage(phone, null, txt, null, null);
}
}else{
Log.e(TAG, "发送失败,系统版本低于DONUT" + phone + " ,内容: " + msg);
}
}
/**
* Call requires API level 4
* <uses-permission android:name="android.permission.WRITE_SMS"/>
*
* @param context
* @param phone
* @param msg
*/
public static void saveMsgToSystem(Context context, String phone, String msg) {
ContentValues values = new ContentValues();
values.put("date", System.currentTimeMillis());
//阅读状态 
values.put("read", 0);
//1为收 2为发  
values.put("type", 2);
values.put("address", phone);
values.put("body", msg);
context.getContentResolver().insert(Uri.parse("content://sms/inbox"), values);
}
}
@@ -0,0 +1,85 @@
package com.litesuits.common.receiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import com.litesuits.android.log.Log;
/**
* 时间广播
*
* @author MaTianyu
* @date 2015-03-09
*/
public class TimeReceiver extends BroadcastReceiver {
private static final String TAG = "TimeReceiver";
private TimeListener timeListener;
@Override
public void onReceive(Context context, Intent intent) {
if (Log.isPrint) {
Log.i(TAG, "action: " + intent.getAction());
Log.d(TAG, "intent : ");
Bundle bundle = intent.getExtras();
for (String key : bundle.keySet()) {
Log.d(TAG, key + " : " + bundle.get(key));
}
}
if (Intent.ACTION_TIME_TICK.equals(intent.getAction())) {
if (timeListener != null) {
timeListener.onTimeTick();
}
} else if (Intent.ACTION_TIME_CHANGED.equals(intent.getAction())) {
if (timeListener != null) {
timeListener.onTimeChanged();
}
} else if (Intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
if (timeListener != null) {
timeListener.onTimeZoneChanged();
}
}
}
public void registerReceiver(Context context, TimeListener timeListener) {
try {
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_TIME_CHANGED);
filter.addAction(Intent.ACTION_TIME_TICK);
filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
filter.setPriority(Integer.MAX_VALUE);
context.registerReceiver(this, filter);
this.timeListener = timeListener;
} catch (Exception e) {
e.printStackTrace();
}
}
public void unRegisterReceiver(Context context) {
try {
context.unregisterReceiver(this);
} catch (Exception e) {
e.printStackTrace();
}
}
public static interface TimeListener {
/**
* 时区改变
*/
public void onTimeZoneChanged();
/**
* 设置时间
*/
public void onTimeChanged();
/**
* 每分钟调用
*/
public void onTimeTick();
}
}
@@ -0,0 +1,180 @@
package com.litesuits.common.service;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Notification;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.text.TextUtils;
import com.litesuits.android.log.Log;
/**
* note: VERSION_CODE >= API_18
* <p/>
* manifest:
* <service android:name=".service.NotificationService"
* android:label="@string/app_name"
* android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
* <intent-filter>
* <action android:name="android.service.notification.NotificationListenerService" />
* </intent-filter>
* </service>
*
* @author MaTianyu
* @date 2015-03-09
*/
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
public class NotificationService extends NotificationListenerService {
private static final String TAG = "NotificationService";
public static final String ACTION_NOTIFICATION_LISTENER_SETTINGS = "android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS";
private static final String ENABLED_NOTIFICATION_LISTENERS = "enabled_notification_listeners";
private static NotificationService self;
private static NotificationListener notificationListener;
/*----------------- 静态方法 -----------------*/
public synchronized static void startNotificationService(Context context, NotificationListener notificationListener) {
NotificationService.notificationListener = notificationListener;
context.startService(new Intent(context, NotificationService.class));
}
public synchronized static void stopNotificationService(Context context) {
context.stopService(new Intent(context, NotificationService.class));
}
public static void startNotificationListenSettings(Context context) {
Intent intent = new Intent(ACTION_NOTIFICATION_LISTENER_SETTINGS);
if(!(context instanceof Activity)) {
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
context.startActivity(intent);
}
public static boolean isNotificationListenEnable(Context context) {
return isNotificationListenEnable(context, context.getPackageName());
}
public static boolean isNotificationListenEnable(Context context, String pkgName) {
final String flat = Settings.Secure.getString(context.getContentResolver(), ENABLED_NOTIFICATION_LISTENERS);
if (!TextUtils.isEmpty(flat)) {
final String[] names = flat.split(":");
for (int i = 0; i < names.length; i++) {
final ComponentName cn = ComponentName.unflattenFromString(names[i]);
if (cn != null) {
if (TextUtils.equals(pkgName, cn.getPackageName())) {
return true;
}
}
}
}
return false;
}
/*----------------- 生命周期 -----------------*/
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "onCreate..");
if (notificationListener != null) {
notificationListener.onServiceCreated(this);
}
self = this;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "onStartCommand..");
return notificationListener == null ? START_STICKY : notificationListener.onServiceStartCommand(this, intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i(TAG, "onDestroy..");
if (notificationListener != null) {
notificationListener.onServiceDestroy();
notificationListener = null;
}
self = null;
}
/*----------------- 通知回调 -----------------*/
@Override
public void onNotificationPosted(StatusBarNotification sbn) {
if (Log.isPrint) {
Log.i(TAG, sbn.toString());
Notification notification = sbn.getNotification();
Log.i(TAG, "tickerText : " + notification.tickerText);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
Bundle bundle = notification.extras;
for (String key : bundle.keySet()) {
Log.i(TAG, key + ": " + bundle.get(key));
}
}
}
if (self != null && notificationListener != null) {
notificationListener.onNotificationPosted(sbn);
}
}
@Override
public void onNotificationRemoved(StatusBarNotification sbn) {
if (self != null && notificationListener != null) {
notificationListener.onNotificationRemoved(sbn);
}
}
public void printCurrentNotifications() {
StatusBarNotification[] ns = getActiveNotifications();
for (StatusBarNotification n : ns) {
Log.i(TAG, String.format("%20s",n.getPackageName()) + ": " + n.getNotification().tickerText);
}
}
public static abstract class NotificationListener {
public void onServiceCreated(NotificationService service) {}
public abstract int onServiceStartCommand(NotificationService service, Intent intent, int flags, int startId);
public void onServiceDestroy() {}
/**
* Implement this method to learn about new notifications as they are posted by apps.
*
* @param sbn A data structure encapsulating the original {@link android.app.Notification}
* object as well as its identifying information (tag and id) and source
* (package name).
*/
public abstract void onNotificationPosted(StatusBarNotification sbn);
/**
* Implement this method to learn when notifications are removed.
* <p/>
* This might occur because the user has dismissed the notification using system UI (or another
* notification listener) or because the app has withdrawn the notification.
* <p/>
* NOTE: The {@link StatusBarNotification} object you receive will be "light"; that is, the
* result from {@link StatusBarNotification#getNotification} may be missing some heavyweight
* fields such as {@link android.app.Notification#contentView} and
* {@link android.app.Notification#largeIcon}. However, all other fields on
* {@link StatusBarNotification}, sufficient to match this call with a prior call to
* {@link #onNotificationPosted(StatusBarNotification)}, will be intact.
*
* @param sbn A data structure encapsulating at least the original information (tag and id)
* and source (package name) used to post the {@link android.app.Notification} that
* was just removed.
*/
public abstract void onNotificationRemoved(StatusBarNotification sbn);
}
}
@@ -0,0 +1,55 @@
package com.litesuits.common.utils;
import android.annotation.TargetApi;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
/**
* @author MaTianyu @http://litesuits.com
* @date 2015-08-22
*/
public class AlarmUtil {
/**
* 开启定时器
*/
@TargetApi(Build.VERSION_CODES.CUPCAKE)
public static void startAlarmIntent(Context context, int triggerAtMillis, PendingIntent pendingIntent) {
AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
manager.set(AlarmManager.RTC_WAKEUP,triggerAtMillis, pendingIntent);
}
/**
* 关闭定时器
*/
@TargetApi(Build.VERSION_CODES.CUPCAKE)
public static void stopAlarmIntent(Context context, PendingIntent pendingIntent) {
AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
manager.cancel(pendingIntent);
}
/**
* 开启轮询服务
*/
@TargetApi(Build.VERSION_CODES.CUPCAKE)
public static void startAlarmService(Context context, int triggerAtMillis, Class<?> cls, String action) {
Intent intent = new Intent(context, cls);
intent.setAction(action);
PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
startAlarmIntent(context, triggerAtMillis,pendingIntent);
}
/**
* 停止启轮询服务
*/
@TargetApi(Build.VERSION_CODES.CUPCAKE)
public static void stopAlarmService(Context context, Class<?> cls, String action) {
Intent intent = new Intent(context, cls);
intent.setAction(action);
PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
stopAlarmIntent(context, pendingIntent);
}
}
@@ -0,0 +1,142 @@
package com.litesuits.common.utils;
import android.content.Context;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.SystemClock;
import android.provider.Settings;
import com.litesuits.android.log.Log;
import com.litesuits.common.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 手机信息 & MAC地址 & 开机时间
*
* @author MaTianyu
* @date 2014-09-25
*/
public class AndroidUtil {
private static final String TAG = AndroidUtil.class.getSimpleName();
//Ethernet Mac Address
private static final String ETH0_MAC_ADDRESS = "/sys/class/net/eth0/address";
/**
* 获取 Wifi MAC 地址
* <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
*/
@Deprecated
public static String getMacAddress(Context context) {
return getWifiMacAddress(context);
}
/**
* 获取 Wifi MAC 地址
* <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
*/
public static String getWifiMacAddress(Context context) {
//wifi mac地址
WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
WifiInfo info = wifi.getConnectionInfo();
String mac = info.getMacAddress();
if (Log.isPrint) {
Log.i(TAG, "WIFI MAC" + mac);
}
return mac;
}
/**
* 获取 以太网 MAC 地址
*/
public static String getEthernetMacAddress() {
try {
String mac = FileUtils.readFileToString(new File(ETH0_MAC_ADDRESS));
if (Log.isPrint) {
Log.i(TAG, "Ethernet MAC" + mac);
}
return mac;
} catch (IOException e) {
Log.e(TAG, "IO Exception when getting eth0 mac address", e);
e.printStackTrace();
return "unknown";
}
}
/**
* 获取 ANDROID_ID
*/
public static String getAndroidId(Context context) {
String androidId = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
if (Log.isPrint) {
Log.i(TAG, "ANDROID_ID " + androidId);
}
return androidId;
}
/**
* 获取 开机时间
*/
public static String getBootTimeString() {
long ut = SystemClock.elapsedRealtime() / 1000;
int h = (int) ((ut / 3600));
int m = (int) ((ut / 60) % 60);
if (Log.isPrint) {
Log.i(TAG, h + ":" + m);
}
return h + ":" + m;
}
public static String printSystemInfo() {
Date date = new Date(System.currentTimeMillis());
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time = dateFormat.format(date);
StringBuilder sb = new StringBuilder();
sb.append("_______ 系统信息 ").append(time).append(" ______________");
sb.append("\nID :").append(Build.ID);
sb.append("\nBRAND :").append(Build.BRAND);
sb.append("\nMODEL :").append(Build.MODEL);
sb.append("\nRELEASE :").append(Build.VERSION.RELEASE);
sb.append("\nSDK :").append(Build.VERSION.SDK);
sb.append("\n_______ OTHER _______");
sb.append("\nBOARD :").append(Build.BOARD);
sb.append("\nPRODUCT :").append(Build.PRODUCT);
sb.append("\nDEVICE :").append(Build.DEVICE);
sb.append("\nFINGERPRINT :").append(Build.FINGERPRINT);
sb.append("\nHOST :").append(Build.HOST);
sb.append("\nTAGS :").append(Build.TAGS);
sb.append("\nTYPE :").append(Build.TYPE);
sb.append("\nTIME :").append(Build.TIME);
sb.append("\nINCREMENTAL :").append(Build.VERSION.INCREMENTAL);
sb.append("\n_______ CUPCAKE-3 _______");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.CUPCAKE) {
sb.append("\nDISPLAY :").append(Build.DISPLAY);
}
sb.append("\n_______ DONUT-4 _______");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.DONUT) {
sb.append("\nSDK_INT :").append(Build.VERSION.SDK_INT);
sb.append("\nMANUFACTURER :").append(Build.MANUFACTURER);
sb.append("\nBOOTLOADER :").append(Build.BOOTLOADER);
sb.append("\nCPU_ABI :").append(Build.CPU_ABI);
sb.append("\nCPU_ABI2 :").append(Build.CPU_ABI2);
sb.append("\nHARDWARE :").append(Build.HARDWARE);
sb.append("\nUNKNOWN :").append(Build.UNKNOWN);
sb.append("\nCODENAME :").append(Build.VERSION.CODENAME);
}
sb.append("\n_______ GINGERBREAD-9 _______");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
sb.append("\nSERIAL :").append(Build.SERIAL);
}
Log.i(TAG, sb.toString());
return sb.toString();
}
}
@@ -0,0 +1,87 @@
package com.litesuits.common.utils;
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Process;
import java.util.List;
/**
* @author MaTianyu
* @date 2014-12-10
*/
public class AppUtil {
/**
* 是否是主进程
*/
public static boolean isMainProcess(Context context) {
String procName = getCurrentProcessName(context);
return procName == null || procName.equalsIgnoreCase(context.getPackageName());
}
/**
* 获取当前进程名字
*/
public static String getCurrentProcessName(Context context) {
int pid = android.os.Process.myPid();
ActivityManager mActivityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningAppProcessInfo appProcess : mActivityManager.getRunningAppProcesses()) {
if (appProcess.pid == pid) {
return appProcess.processName;
}
}
return null;
}
/**
* 调用系统分享
*/
public static void shareToOtherApp(Context context, String title, String content, String dialogTitle) {
Intent intentItem = new Intent(Intent.ACTION_SEND);
intentItem.setType("text/plain");
intentItem.putExtra(Intent.EXTRA_SUBJECT, title);
intentItem.putExtra(Intent.EXTRA_TEXT, content);
intentItem.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(Intent.createChooser(intentItem, dialogTitle));
}
/**
* need < uses-permission android:name =“android.permission.GET_TASKS” />
* 判断是否前台运行
*/
public static boolean isRunningForeground(Context context) {
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> taskList = am.getRunningTasks(1);
if (taskList != null && !taskList.isEmpty()) {
ComponentName componentName = taskList.get(0).topActivity;
if (componentName != null && componentName.getPackageName().equals(context.getPackageName())) {
return true;
}
}
return false;
}
/**
* 获取App包 信息版本号
*/
public PackageInfo getPackageInfo(Context context) {
PackageManager packageManager = context.getPackageManager();
PackageInfo packageInfo = null;
try {
packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return packageInfo;
}
public static void killTheApp() {
android.os.Process.killProcess(Process.myPid());
System.exit(0);
}
}
@@ -0,0 +1,242 @@
package com.litesuits.common.utils;
import android.content.Intent;
import android.graphics.*;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.provider.MediaStore;
import com.litesuits.android.log.Log;
import com.litesuits.common.assist.Base64;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class BitmapUtil {
private static final String TAG = BitmapUtil.class.getSimpleName();
/**
* convert Bitmap to byte array
*/
public static byte[] bitmapToByte(Bitmap b) {
ByteArrayOutputStream o = new ByteArrayOutputStream();
b.compress(Bitmap.CompressFormat.PNG, 100, o);
return o.toByteArray();
}
/**
* convert byte array to Bitmap
*/
public static Bitmap byteToBitmap(byte[] b) {
return (b == null || b.length == 0) ? null : BitmapFactory.decodeByteArray(b, 0, b.length);
}
/**
* 把bitmap转换成Base64编码String
*/
public static String bitmapToString(Bitmap bitmap) {
return Base64.encodeToString(bitmapToByte(bitmap), Base64.DEFAULT);
}
/**
* convert Drawable to Bitmap
*/
public static Bitmap drawableToBitmap(Drawable drawable) {
return drawable == null ? null : ((BitmapDrawable) drawable).getBitmap();
}
/**
* convert Bitmap to Drawable
*/
public static Drawable bitmapToDrawable(Bitmap bitmap) {
return bitmap == null ? null : new BitmapDrawable(bitmap);
}
/**
* scale image
*/
public static Bitmap scaleImageTo(Bitmap org, int newWidth, int newHeight) {
return scaleImage(org, (float) newWidth / org.getWidth(), (float) newHeight / org.getHeight());
}
/**
* scale image
*/
public static Bitmap scaleImage(Bitmap org, float scaleWidth, float scaleHeight) {
if (org == null) {
return null;
}
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
return Bitmap.createBitmap(org, 0, 0, org.getWidth(), org.getHeight(), matrix, true);
}
public static Bitmap toRoundCorner(Bitmap bitmap) {
int height = bitmap.getHeight();
int width = bitmap.getHeight();
Bitmap output = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, width, height);
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
//paint.setColor(0xff424242);
paint.setColor(Color.TRANSPARENT);
canvas.drawCircle(width / 2, height / 2, width / 2, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
public static Bitmap createBitmapThumbnail(Bitmap bitMap, boolean needRecycle, int newHeight, int newWidth) {
int width = bitMap.getWidth();
int height = bitMap.getHeight();
// 计算缩放比例
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// 取得想要缩放的matrix参数
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
// 得到新的图片
Bitmap newBitMap = Bitmap.createBitmap(bitMap, 0, 0, width, height, matrix, true);
if (needRecycle)
bitMap.recycle();
return newBitMap;
}
public static boolean saveBitmap(Bitmap bitmap, File file) {
if (bitmap == null)
return false;
FileOutputStream fos = null;
try {
fos = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.flush();
return true;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return false;
}
public static boolean saveBitmap(Bitmap bitmap, String absPath) {
return saveBitmap(bitmap, new File(absPath));
}
public static Intent buildImageGetIntent(Uri saveTo, int outputX, int outputY, boolean returnData) {
return buildImageGetIntent(saveTo, 1, 1, outputX, outputY, returnData);
}
public static Intent buildImageGetIntent(Uri saveTo, int aspectX, int aspectY,
int outputX, int outputY, boolean returnData) {
Log.i(TAG, "Build.VERSION.SDK_INT : " + Build.VERSION.SDK_INT);
Intent intent = new Intent();
if (Build.VERSION.SDK_INT < 19) {
intent.setAction(Intent.ACTION_GET_CONTENT);
} else {
intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
}
intent.setType("image/*");
intent.putExtra("output", saveTo);
intent.putExtra("aspectX", aspectX);
intent.putExtra("aspectY", aspectY);
intent.putExtra("outputX", outputX);
intent.putExtra("outputY", outputY);
intent.putExtra("scale", true);
intent.putExtra("return-data", returnData);
intent.putExtra("outputFormat", Bitmap.CompressFormat.PNG.toString());
return intent;
}
public static Intent buildImageCropIntent(Uri uriFrom, Uri uriTo, int outputX, int outputY, boolean returnData) {
return buildImageCropIntent(uriFrom, uriTo, 1, 1, outputX, outputY, returnData);
}
public static Intent buildImageCropIntent(Uri uriFrom, Uri uriTo, int aspectX, int aspectY,
int outputX, int outputY, boolean returnData) {
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(uriFrom, "image/*");
intent.putExtra("crop", "true");
intent.putExtra("output", uriTo);
intent.putExtra("aspectX", aspectX);
intent.putExtra("aspectY", aspectY);
intent.putExtra("outputX", outputX);
intent.putExtra("outputY", outputY);
intent.putExtra("scale", true);
intent.putExtra("return-data", returnData);
intent.putExtra("outputFormat", Bitmap.CompressFormat.PNG.toString());
return intent;
}
public static Intent buildImageCaptureIntent(Uri uri) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
return intent;
}
public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
int h = options.outHeight;
int w = options.outWidth;
int inSampleSize = 0;
if (h > reqHeight || w > reqWidth) {
float ratioW = (float) w / reqWidth;
float ratioH = (float) h / reqHeight;
inSampleSize = (int) Math.min(ratioH, ratioW);
}
inSampleSize = Math.max(1, inSampleSize);
return inSampleSize;
}
public static Bitmap getSmallBitmap(String filePath, int reqWidth, int reqHeight) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filePath, options);
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(filePath, options);
}
public byte[] compressBitmapToBytes(String filePath, int reqWidth, int reqHeight, int quality) {
Bitmap bitmap = getSmallBitmap(filePath, reqWidth, reqHeight);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, baos);
byte[] bytes = baos.toByteArray();
bitmap.recycle();
Log.i(TAG, "Bitmap compressed success, size: " + bytes.length);
return bytes;
}
public byte[] compressBitmapSmallTo(String filePath, int reqWidth, int reqHeight, int maxLenth) {
int quality = 100;
byte[] bytes = compressBitmapToBytes(filePath, reqWidth, reqHeight, quality);
while (bytes.length > maxLenth && quality > 0) {
quality = quality / 2;
bytes = compressBitmapToBytes(filePath, reqWidth, reqHeight, quality);
}
return bytes;
}
public byte[] compressBitmapQuikly(String filePath) {
return compressBitmapToBytes(filePath, 480, 800, 50);
}
public byte[] compressBitmapQuiklySmallTo(String filePath, int maxLenth) {
return compressBitmapSmallTo(filePath, 480, 800, maxLenth);
}
}
@@ -0,0 +1,59 @@
package com.litesuits.common.utils;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
/**
* @author MaTianyu
* @date 14-7-31
*/
public class ByteUtil {
/**
* byte[] 转为 对象
*
* @param bytes
* @return
*/
public static Object byteToObject(byte[] bytes) throws Exception {
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
return ois.readObject();
} finally {
if (ois != null) ois.close();
}
}
/**
* 对象 转为 byte[]
*
* @param obj
* @return
*/
public static byte[] objectToByte(Object obj) throws Exception {
ObjectOutputStream oos = null;
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bos);
oos.writeObject(obj);
return bos.toByteArray();
} finally {
if (oos != null) oos.close();
}
}
public static void byteToBit(byte[] bytes, StringBuilder sb) {
for (int i = 0; i < Byte.SIZE * bytes.length; i++)
sb.append((bytes[i / Byte.SIZE] << i % Byte.SIZE & 0x80) == 0 ? '0' : '1');
}
public static String byteToBit(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < Byte.SIZE * bytes.length; i++)
sb.append((bytes[i / Byte.SIZE] << i % Byte.SIZE & 0x80) == 0 ? '0' : '1');
return sb.toString();
}
}
@@ -0,0 +1,71 @@
package com.litesuits.common.utils;
import java.lang.reflect.Constructor;
import java.util.Collection;
import java.util.Date;
/**
* 类工具
*
* @author mty
* @date 2013-6-10下午8:00:46
*/
public class ClassUtil {
/**
* 判断类是否是基础数据类型
* 目前支持11种
*
* @param clazz
* @return
*/
public static boolean isBaseDataType(Class<?> clazz) {
return clazz.isPrimitive() || clazz.equals(String.class) || clazz.equals(Boolean.class)
|| clazz.equals(Integer.class) || clazz.equals(Long.class) || clazz.equals(Float.class)
|| clazz.equals(Double.class) || clazz.equals(Byte.class) || clazz.equals(Character.class)
|| clazz.equals(Short.class) || clazz.equals(Date.class) || clazz.equals(byte[].class)
|| clazz.equals(Byte[].class);
}
/**
* 根据类获取对象:不再必须一个无参构造
*
* @param claxx
* @return
* @throws Exception
*/
public static <T> T newInstance(Class<T> claxx) throws Exception {
Constructor<?>[] cons = claxx.getDeclaredConstructors();
for (Constructor<?> c : cons) {
Class[] cls = c.getParameterTypes();
if (cls.length == 0) {
c.setAccessible(true);
return (T) c.newInstance();
} else {
Object[] objs = new Object[cls.length];
for (int i = 0; i < cls.length; i++) {
objs[i] = getDefaultPrimiticeValue(cls[i]);
}
c.setAccessible(true);
return (T) c.newInstance(objs);
}
}
return null;
}
public static Object getDefaultPrimiticeValue(Class clazz) {
if (clazz.isPrimitive()) {
return clazz == boolean.class ? false : 0;
}
return null;
}
public static boolean isCollection(Class claxx) {
return Collection.class.isAssignableFrom(claxx);
}
public static boolean isArray(Class claxx) {
return claxx.isArray();
}
}
@@ -0,0 +1,59 @@
package com.litesuits.common.utils;
import android.annotation.TargetApi;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.os.Build;
/**
* @author MaTianyu @http://litesuits.com
* @date 2015-08-25
*/
public class ClipboardUtil {
public static void copyToClipboardSupport(Context context, String text) {
android.text.ClipboardManager clipboard = (android.text.ClipboardManager) context
.getSystemService(Context.CLIPBOARD_SERVICE);
clipboard.setText(text);
}
public static void getLatestTextSupport(Context context) {
android.text.ClipboardManager clipboard = (android.text.ClipboardManager) context
.getSystemService(Context.CLIPBOARD_SERVICE);
clipboard.getText();
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static void copyToClipboard(Context context, String text) {
ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
clipboard.setPrimaryClip(ClipData.newPlainText(null, text));
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static int getItemCount(Context context) {
ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
ClipData data = clipboard.getPrimaryClip();
return data.getItemCount();
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static String getText(Context context, int index) {
ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = clipboard.getPrimaryClip();
if (clip != null && clip.getItemCount() > index) {
return String.valueOf(clip.getItemAt(0).coerceToText(context));
}
return null;
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static String getLatestText(Context context) {
ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = clipboard.getPrimaryClip();
if (clip != null && clip.getItemCount() > 0) {
return String.valueOf(clip.getItemAt(0).coerceToText(context));
}
return null;
}
}
@@ -0,0 +1,179 @@
package com.litesuits.common.utils;
import com.litesuits.android.log.Log;
import com.litesuits.common.assist.Check;
import java.io.*;
import java.util.regex.Pattern;
/**
* Get CPU info.
*
* @author MaTianyu
* @date 2015-04-18
*/
public class CpuUtil {
private static final String TAG = CpuUtil.class.getSimpleName();
private static final String CPU_INFO_PATH = "/proc/cpuinfo";
private static final String CPU_FREQ_NULL = "N/A";
private static final String CMD_CAT = "/system/bin/cat";
private static final String CPU_FREQ_CUR_PATH = "/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq";
private static final String CPU_FREQ_MAX_PATH = "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq";
private static final String CPU_FREQ_MIN_PATH = "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq";
private static String CPU_NAME;
private static int CPU_CORES = 0;
private static long CPU_MAX_FREQENCY = 0;
private static long CPU_MIN_FREQENCY = 0;
/**
* Print cpu info.
*/
public static String printCpuInfo() {
String info = FileUtil.getFileOutputString(CPU_INFO_PATH);
if (Log.isPrint) {
Log.i(TAG, "_______ CPU : \n" + info);
}
return info;
}
/**
* Get available processors.
*/
public static int getProcessorsCount() {
return Runtime.getRuntime().availableProcessors();
}
/**
* Gets the number of cores available in this device, across all processors.
* Requires: Ability to peruse the filesystem at "/sys/devices/system/cpu"
*
* @return The number of cores, or available processors if failed to get result
*/
public static int getCoresNumbers() {
if (CPU_CORES != 0) {
return CPU_CORES;
}
//Private Class to display only CPU devices in the directory listing
class CpuFilter implements FileFilter {
@Override
public boolean accept(File pathname) {
//Check if filename is "cpu", followed by a single digit number
if (Pattern.matches("cpu[0-9]+", pathname.getName())) {
return true;
}
return false;
}
}
try {
//Get directory containing CPU info
File dir = new File("/sys/devices/system/cpu/");
//Filter to only list the devices we care about
File[] files = dir.listFiles(new CpuFilter());
//Return the number of cores (virtual CPU devices)
CPU_CORES = files.length;
} catch (Exception e) {
e.printStackTrace();
}
if (CPU_CORES < 1) {
CPU_CORES = Runtime.getRuntime().availableProcessors();
}
if (CPU_CORES < 1) {
CPU_CORES = 1;
}
return CPU_CORES;
}
/**
* Get CPU name.
*/
public static String getCpuName() {
if (!Check.isEmpty(CPU_NAME)) {
return CPU_NAME;
}
try {
BufferedReader bufferedReader = new BufferedReader(new FileReader(CPU_INFO_PATH), 8192);
String line = bufferedReader.readLine();
bufferedReader.close();
String[] array = line.split(":\\s+", 2);
if (array.length > 1) {
if (Log.isPrint) {
Log.i(TAG, array[1]);
}
CPU_NAME = array[1];
}
} catch (IOException e) {
e.printStackTrace();
}
return CPU_NAME;
}
/**
* Get current CPU freqency.
*/
public static long getCurrentFreqency() {
try {
return Long.parseLong(FileUtil.getFileOutputString(CPU_FREQ_CUR_PATH).trim());
} catch (Exception e) {
e.printStackTrace();
}
return 0;
}
/**
* Get maximum CPU freqency
*/
public static long getMaxFreqency() {
if (CPU_MAX_FREQENCY > 0) {
return CPU_MAX_FREQENCY;
}
try {
CPU_MAX_FREQENCY = Long.parseLong(getCMDOutputString(new String[]{CMD_CAT, CPU_FREQ_MAX_PATH}).trim());
} catch (Exception e) {
e.printStackTrace();
}
return CPU_MAX_FREQENCY;
}
/**
* Get minimum frenqency.
*/
public static long getMinFreqency() {
if (CPU_MIN_FREQENCY > 0) {
return CPU_MIN_FREQENCY;
}
try {
CPU_MIN_FREQENCY = Long.parseLong(getCMDOutputString(new String[]{CMD_CAT, CPU_FREQ_MIN_PATH}).trim());
} catch (Exception e) {
e.printStackTrace();
}
return CPU_MIN_FREQENCY;
}
/**
* Get command output string.
*/
public static String getCMDOutputString(String[] args) {
try {
ProcessBuilder cmd = new ProcessBuilder(args);
Process process = cmd.start();
InputStream in = process.getInputStream();
StringBuilder sb = new StringBuilder();
byte[] re = new byte[64];
int len;
while ((len = in.read(re)) != -1) {
sb.append(new String(re, 0, len));
}
in.close();
process.destroy();
if (Log.isPrint) {
Log.i(TAG, "CMD: " + sb.toString());
}
return sb.toString();
} catch (IOException ex) {
ex.printStackTrace();
}
return null;
}
}
@@ -0,0 +1,73 @@
package com.litesuits.common.utils;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.text.Html;
import android.view.View;
public class DialogUtil {
public static AlertDialog.Builder dialogBuilder(Context context, String title, String msg) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
if (msg != null) {
builder.setMessage(msg);
}
if (title != null) {
builder.setTitle(title);
}
return builder;
}
public static AlertDialog.Builder dialogBuilder(Context context, String title, String msg, int i) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
if (msg != null) {
builder.setMessage(Html.fromHtml(msg));
}
if (title != null) {
builder.setTitle(title);
}
return builder;
}
public static AlertDialog.Builder dialogBuilder(Context context, int title, View view) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
if (view != null) {
builder.setView(view);
}
if (title > 0) {
builder.setTitle(title);
}
return builder;
}
public static AlertDialog.Builder dialogBuilder(Context context, int titleResId, int msgResId) {
String title = titleResId > 0 ? context.getResources().getString(titleResId) : null;
String msg = msgResId > 0 ? context.getResources().getString(msgResId) : null;
return dialogBuilder(context, title, msg);
}
public static Dialog showTips(Context context, String title, String des) {
return showTips(context, title, des, null, null);
}
public static Dialog showTips(Context context, int title, int des) {
return showTips(context, context.getString(title), context.getString(des));
}
public static Dialog showTips(Context context, int title, int des, int btn, DialogInterface.OnDismissListener dismissListener) {
return showTips(context, context.getString(title), context.getString(des), context.getString(btn), dismissListener);
}
public static Dialog showTips(Context context, String title, String des, String btn, DialogInterface.OnDismissListener dismissListener) {
AlertDialog.Builder builder = dialogBuilder(context, title, des);
builder.setCancelable(true);
builder.setPositiveButton(btn, null);
Dialog dialog = builder.show();
dialog.setCanceledOnTouchOutside(true);
dialog.setOnDismissListener(dismissListener);
return dialog;
}
}
@@ -0,0 +1,41 @@
package com.litesuits.common.utils;
import android.content.Context;
import android.util.DisplayMetrics;
import com.litesuits.android.log.Log;
/**
* @author MaTianyu
* @date 2015-04-19
*/
public class DisplayUtil {
private static final String TAG = DisplayUtil.class.getSimpleName();
/**
* 获取 显示信息
*/
public static DisplayMetrics getDisplayMetrics(Context context) {
DisplayMetrics dm = context.getResources().getDisplayMetrics();
return dm;
}
/**
* 打印 显示信息
*/
public static DisplayMetrics printDisplayInfo(Context context) {
DisplayMetrics dm = getDisplayMetrics(context);
if (Log.isPrint) {
StringBuilder sb = new StringBuilder();
sb.append("_______ 显示信息: ");
sb.append("\ndensity :").append(dm.density);
sb.append("\ndensityDpi :").append(dm.densityDpi);
sb.append("\nheightPixels :").append(dm.heightPixels);
sb.append("\nwidthPixels :").append(dm.widthPixels);
sb.append("\nscaledDensity :").append(dm.scaledDensity);
sb.append("\nxdpi :").append(dm.xdpi);
sb.append("\nydpi :").append(dm.ydpi);
Log.i(TAG, sb.toString());
}
return dm;
}
}
@@ -0,0 +1,128 @@
package com.litesuits.common.utils;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.LinkedList;
import java.util.List;
/**
* 域工具
*
* @author mty
* @date 2013-6-10下午6:36:29
*/
public class FieldUtil {
/**
* 判断是否序列化
*
* @param f
* @return
*/
public static boolean isSerializable(Field f) {
Class<?>[] cls = f.getType().getInterfaces();
for (Class<?> c : cls) {
if (Serializable.class == c) {
return true;
}
}
return false;
}
/**
* 设置域的值
*
* @param f
* @param obj
* @return
* @throws IllegalAccessException
* @throws IllegalArgumentException
*/
public static Object set(Field f, Object obj, Object value) throws IllegalArgumentException, IllegalAccessException {
f.setAccessible(true);
f.set(obj, value);
return f.get(obj);
}
/**
* 获取域的值
*
* @param f
* @param obj
* @return
* @throws IllegalAccessException
* @throws IllegalArgumentException
*/
public static Object get(Field f, Object obj) throws IllegalArgumentException, IllegalAccessException {
f.setAccessible(true);
return f.get(obj);
}
public static boolean isLong(Field field) {
return field.getType() == long.class || field.getType() == Long.class;
}
public static boolean isInteger(Field field) {
return field.getType() == int.class || field.getType() != Integer.class;
}
/**
* 获取域的泛型类型,如果不带泛型返回null
*
* @param f
* @return
*/
public static Class<?> getGenericType(Field f) {
Type type = f.getGenericType();
if (type instanceof ParameterizedType) {
type = ((ParameterizedType) type).getActualTypeArguments()[0];
if (type instanceof Class<?>) return (Class<?>) type;
} else if (type instanceof Class<?>) return (Class<?>) type;
return null;
}
/**
* 获取数组的类型
*
* @param f
* @return
*/
public static Class<?> getComponentType(Field f) {
return f.getType().getComponentType();
}
/**
* 获取全部Field,包括父类
*
* @param claxx
* @return
*/
public static List<Field> getAllDeclaredFields(Class<?> claxx) {
// find all field.
LinkedList<Field> fieldList = new LinkedList<Field>();
while (claxx != null && claxx != Object.class) {
Field[] fs = claxx.getDeclaredFields();
for (int i = 0; i < fs.length; i++) {
Field f = fs[i];
if (!isInvalid(f)) {
fieldList.addLast(f);
}
}
claxx = claxx.getSuperclass();
}
return fieldList;
}
/**
* 是静态常量或者内部结构属性
*
* @param f
* @return
*/
public static boolean isInvalid(Field f) {
return (Modifier.isStatic(f.getModifiers()) && Modifier.isFinal(f.getModifiers())) || f.isSynthetic();
}
}
@@ -0,0 +1,93 @@
package com.litesuits.common.utils;
import java.io.*;
import java.nio.channels.FileChannel;
import java.text.DecimalFormat;
/**
* @author MaTianyu
* @date 2014-08-10
*/
public class FileUtil {
private static final String TAG = FileUtil.class.getSimpleName();
public static void fileChannelCopy(File s, File t) {
FileInputStream fi = null;
FileOutputStream fo = null;
try {
fi = new FileInputStream(s);
fo = new FileOutputStream(t);
FileChannel in = fi.getChannel();//得到对应的文件通道
FileChannel out = fo.getChannel();//得到对应的文件通道
in.transferTo(0, in.size(), out);//连接两个通道,并且从in通道读取,然后写入out通道
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fo != null) fo.close();
if (fi != null) fi.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static String formatFileSizeToString(long fileLen) {// 转换文件大小
DecimalFormat df = new DecimalFormat("#.00");
String fileSizeString = "";
if (fileLen < 1024) {
fileSizeString = df.format((double) fileLen) + "B";
} else if (fileLen < 1048576) {
fileSizeString = df.format((double) fileLen / 1024) + "K";
} else if (fileLen < 1073741824) {
fileSizeString = df.format((double) fileLen / 1048576) + "M";
} else {
fileSizeString = df.format((double) fileLen / 1073741824) + "G";
}
return fileSizeString;
}
/***
* 根据路径删除图片
*/
public static boolean deleteFile(File file)throws IOException{
return file != null && file.delete();
}
/***
* 获取文件扩展名
* @param filename
* @return 返回文件扩展名
*/
public static String getExtensionName(String filename) {
if ((filename != null) && (filename.length() > 0)) {
int dot = filename.lastIndexOf('.');
if ((dot >-1) && (dot < (filename.length() - 1))) {
return filename.substring(dot + 1);
}
}
return filename;
}
/**
* 读取指定文件的输出
*/
public static String getFileOutputString(String path) {
try {
BufferedReader bufferedReader = new BufferedReader(new FileReader(path), 8192);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = bufferedReader.readLine()) != null) {
sb.append("\n").append(line);
}
bufferedReader.close();
return sb.toString();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
@@ -0,0 +1,24 @@
package com.litesuits.common.utils;
import android.os.Handler;
import android.os.Looper;
/**
* @author MaTianyu
* @date 2015-03-12
*/
public class HandlerUtil {
public static final Handler HANDLER = new Handler(Looper.getMainLooper());
public static void runOnUiThread(Runnable runnable){
HANDLER.post(runnable);
}
public static void runOnUiThreadDelay(Runnable runnable, long delayMillis){
HANDLER.postDelayed(runnable,delayMillis);
}
public static void removeRunable(Runnable runnable){
HANDLER.removeCallbacks(runnable);
}
}
@@ -0,0 +1,165 @@
package com.litesuits.common.utils;
/**
* reference apache commons <a
* href="http://commons.apache.org/codec/">http://commons.apache.org/codec/</a>
*
* @author Aub
*
*/
public class HexUtil {
/**
* 用于建立十六进制字符的输出的小写字符数组
*/
private static final char[] DIGITS_LOWER = { '0', '1', '2', '3', '4', '5',
'6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
/**
* 用于建立十六进制字符的输出的大写字符数组
*/
private static final char[] DIGITS_UPPER = { '0', '1', '2', '3', '4', '5',
'6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
/**
* 将字节数组转换为十六进制字符数组
*
* @param data
* byte[]
* @return 十六进制char[]
*/
public static char[] encodeHex(byte[] data) {
return encodeHex(data, true);
}
/**
* 将字节数组转换为十六进制字符数组
*
* @param data
* byte[]
* @param toLowerCase
* <code>true</code> 传换成小写格式 <code>false</code> 传换成大写格式
* @return 十六进制char[]
*/
public static char[] encodeHex(byte[] data, boolean toLowerCase) {
return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
}
/**
* 将字节数组转换为十六进制字符数组
*
* @param data
* byte[]
* @param toDigits
* 用于控制输出的char[]
* @return 十六进制char[]
*/
protected static char[] encodeHex(byte[] data, char[] toDigits) {
int l = data.length;
char[] out = new char[l << 1];
// two characters form the hex value.
for (int i = 0, j = 0; i < l; i++) {
out[j++] = toDigits[(0xF0 & data[i]) >>> 4];
out[j++] = toDigits[0x0F & data[i]];
}
return out;
}
/**
* 将字节数组转换为十六进制字符串
*
* @param data
* byte[]
* @return 十六进制String
*/
public static String encodeHexStr(byte[] data) {
return encodeHexStr(data, true);
}
/**
* 将字节数组转换为十六进制字符串
*
* @param data
* byte[]
* @param toLowerCase
* <code>true</code> 传换成小写格式 <code>false</code> 传换成大写格式
* @return 十六进制String
*/
public static String encodeHexStr(byte[] data, boolean toLowerCase) {
return encodeHexStr(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
}
/**
* 将字节数组转换为十六进制字符串
*
* @param data
* byte[]
* @param toDigits
* 用于控制输出的char[]
* @return 十六进制String
*/
protected static String encodeHexStr(byte[] data, char[] toDigits) {
return new String(encodeHex(data, toDigits));
}
/**
* 将十六进制字符数组转换为字节数组
*
* @param data
* 十六进制char[]
* @return byte[]
* @throws RuntimeException
* 如果源十六进制字符数组是一个奇怪的长度,将抛出运行时异常
*/
public static byte[] decodeHex(char[] data) {
int len = data.length;
if ((len & 0x01) != 0) {
throw new RuntimeException("Odd number of characters.");
}
byte[] out = new byte[len >> 1];
// two characters form the hex value.
for (int i = 0, j = 0; j < len; i++) {
int f = toDigit(data[j], j) << 4;
j++;
f = f | toDigit(data[j], j);
j++;
out[i] = (byte) (f & 0xFF);
}
return out;
}
/**
* 将十六进制字符转换成一个整数
*
* @param ch
* 十六进制char
* @param index
* 十六进制字符在字符数组中的位置
* @return 一个整数
* @throws RuntimeException
* 当ch不是一个合法的十六进制字符时,抛出运行时异常
*/
protected static int toDigit(char ch, int index) {
int digit = Character.digit(ch, 16);
if (digit == -1) {
throw new RuntimeException("Illegal hexadecimal character " + ch
+ " at index " + index);
}
return digit;
}
public static void main(String[] args) {
String srcStr = "待转换字符串";
String encodeStr = encodeHexStr(srcStr.getBytes());
String decodeStr = new String(decodeHex(encodeStr.toCharArray()));
System.out.println("转换前:" + srcStr);
System.out.println("转换后:" + encodeStr);
System.out.println("还原后:" + decodeStr);
}
}
@@ -0,0 +1,55 @@
package com.litesuits.common.utils;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.os.Build;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
/**
* @author MaTianyu(http://litesuits.com) on 2015-06-01
*/
@TargetApi(Build.VERSION_CODES.CUPCAKE)
public class InputMethodUtils {
public static void toggleSoftInput(Context context) {
InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
}
public static boolean showSoftInput(View view) {
InputMethodManager imm = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
return imm.showSoftInput(view, InputMethodManager.SHOW_FORCED);
}
public static boolean showSoftInput(Activity activity) {
View view = activity.getCurrentFocus();
if (view != null) {
InputMethodManager imm = (InputMethodManager) view.getContext().getSystemService(
Context.INPUT_METHOD_SERVICE);
return imm.showSoftInput(view, InputMethodManager.SHOW_FORCED);
}
return false;
}
public static boolean hideSoftInput(View view) {
InputMethodManager imm = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
return imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
public static boolean hideSoftInput(Activity activity) {
if (activity.getCurrentFocus() != null) {
InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
return imm.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0);
}
return false;
}
public static boolean isActive(Context context) {
InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
return imm.isActive();
}
}
@@ -0,0 +1,49 @@
package com.litesuits.common.utils;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* MS5
*/
public class MD5Util {
private static final String TAG = MD5Util.class.getSimpleName();
private static final int STREAM_BUFFER_LENGTH = 1024;
public static MessageDigest getDigest(final String algorithm) throws NoSuchAlgorithmException {
return MessageDigest.getInstance(algorithm);
}
public static byte[] md5(String txt) {
return md5(txt.getBytes());
}
public static byte[] md5(byte[] bytes) {
try {
MessageDigest digest = getDigest("MD5");
digest.update(bytes);
return digest.digest();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
public static byte[] md5(InputStream is) throws NoSuchAlgorithmException, IOException {
return updateDigest(getDigest("MD5"), is).digest();
}
public static MessageDigest updateDigest(final MessageDigest digest, final InputStream data) throws IOException {
final byte[] buffer = new byte[STREAM_BUFFER_LENGTH];
int read = data.read(buffer, 0, STREAM_BUFFER_LENGTH);
while (read > -1) {
digest.update(buffer, 0, read);
read = data.read(buffer, 0, STREAM_BUFFER_LENGTH);
}
return digest;
}
}
@@ -0,0 +1,112 @@
package com.litesuits.common.utils;
import android.annotation.TargetApi;
import android.app.ActivityManager;
import android.content.Context;
import android.os.Build;
import android.text.format.Formatter;
import com.litesuits.android.log.Log;
/**
* Get memory info.
*
* @author MaTianyu
* @date 2015-04-19
*/
public class MemoryUtil {
private static final String TAG = MemoryUtil.class.getSimpleName();
private static final String MEM_INFO_PATH = "/proc/meminfo";
/**
* Print memory info. such as:
*
* MemTotal: 1864292 kB
* MemFree: 779064 kB
* Buffers: 4540 kB
* Cached: 185656 kB
* SwapCached: 13160 kB
* Active: 435588 kB
* Inactive: 269312 kB
* Active(anon): 386188 kB
* Inactive(anon): 132576 kB
* Active(file): 49400 kB
* Inactive(file): 136736 kB
* Unevictable: 2420 kB
* Mlocked: 0 kB
* HighTotal: 1437692 kB
* HighFree: 520212 kB
* LowTotal: 426600 kB
* LowFree: 258852 kB
* SwapTotal: 511996 kB
* SwapFree: 171876 kB
* Dirty: 412 kB
* Writeback: 0 kB
* AnonPages: 511924 kB
* Mapped: 152368 kB
* Shmem: 1636 kB
* Slab: 109224 kB
* SReclaimable: 75932 kB
* SUnreclaim: 33292 kB
* KernelStack: 13056 kB
* PageTables: 28032 kB
* NFS_Unstable: 0 kB
* Bounce: 0 kB
* WritebackTmp: 0 kB
* CommitLimit: 1444140 kB
* Committed_AS: 25977748 kB
* VmallocTotal: 458752 kB
* VmallocUsed: 123448 kB
* VmallocChunk: 205828 kB
*/
public static String printMemInfo() {
String info = FileUtil.getFileOutputString(MEM_INFO_PATH);
if (Log.isPrint) {
Log.i(TAG, "_______ 内存信息: \n" + info);
}
return info;
}
/**
* Get memory info of device.
*/
@TargetApi(Build.VERSION_CODES.CUPCAKE)
public static ActivityManager.MemoryInfo getMemoryInfo(Context context) {
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo();
am.getMemoryInfo(mi);
return mi;
}
/**
* Print Memory info.
*/
@TargetApi(Build.VERSION_CODES.CUPCAKE)
public static ActivityManager.MemoryInfo printMemoryInfo(Context context) {
ActivityManager.MemoryInfo mi = getMemoryInfo(context);
if (Log.isPrint) {
StringBuilder sb = new StringBuilder();
sb.append("_______ Memory : ");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
sb.append("\ntotalMem :").append(mi.totalMem);
}
sb.append("\navailMem :").append(mi.availMem);
sb.append("\nlowMemory :").append(mi.lowMemory);
sb.append("\nthreshold :").append(mi.threshold);
Log.i(TAG, sb.toString());
}
return mi;
}
/**
* Get available memory info.
*/
@TargetApi(Build.VERSION_CODES.CUPCAKE)
public static String getAvailMemory(Context context) {// 获取android当前可用内存大小
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo();
am.getMemoryInfo(mi);
// mi.availMem; 当前系统的可用内存
return Formatter.formatFileSize(context, mi.availMem);// 将获取的内存大小规格化
}
}
@@ -0,0 +1,137 @@
package com.litesuits.common.utils;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import com.litesuits.android.log.Log;
import java.util.ArrayList;
/**
* @author MaTianyu
* @date 2014-11-19
*/
public class NotificationUtil {
private static int LedID = 0;
private static final String TAG = NotificationUtil.class.getSimpleName();
public static void notification(Context context, Uri uri,
int icon, String ticker, String title, String msg) {
Log.i(TAG, "notiry uri :" + uri);
// 设置通知的事件消息
Intent intent = new Intent();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.DONUT) {
intent.setPackage(context.getPackageName());
}
intent.setData(uri);
notification(context, intent, 0, icon, ticker, title, msg);
}
public static void notification(Context context, String activityClass, Bundle bundle,
int icon, String ticker, String title, String msg) {
// 设置通知的事件消息
Intent intent = new Intent();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.DONUT) {
intent.setPackage(context.getPackageName());
}
intent.putExtras(bundle);
intent.setComponent(new ComponentName(context.getPackageName(), activityClass));
notification(context, intent, 0, icon, ticker, title, msg);
}
public static void notification(Context context, Intent intent, int id,
int icon, String ticker, String title, String msg) {
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
notification(context, pendingIntent, id, icon, ticker, title, msg);
}
public static void notification(Context context, PendingIntent pendingIntent, int id,
int icon, String ticker, String title, String msg) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
Notification.Builder builder = new Notification.Builder(context);
builder.setSmallIcon(icon);
builder.setContentTitle(title);
builder.setTicker(ticker);
builder.setContentText(msg);
builder.setDefaults(Notification.DEFAULT_SOUND);
builder.setLights(0xFFFFFF00, 0, 2000);
builder.setVibrate(new long[]{0, 100, 300});
builder.setAutoCancel(true);
builder.setContentIntent(pendingIntent);
Notification baseNF;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
baseNF = builder.getNotification();
} else {
baseNF = builder.build();
}
//发出状态栏通知
NotificationManager nm = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);
nm.notify(id, baseNF);
}
}
public static void lightLed(Context context, int colorOx, int durationMS) {
lightLed(context, colorOx, 0, durationMS);
}
public static void lightLed(Context context, int colorOx, int startOffMS, int durationMS) {
NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification();
notification.ledARGB = colorOx;
notification.ledOffMS = startOffMS;
notification.ledOnMS = durationMS;
notification.flags = Notification.FLAG_SHOW_LIGHTS;
LedID++;
nm.notify(LedID, notification);
nm.cancel(LedID);
}
public static void lightLed(final Context context, final int colorOx, final int startOffMS, final int durationMS,
int repeat) {
if (repeat < 1) {
repeat = 1;
}
Handler handler = new Handler(Looper.getMainLooper());
for (int i = 0; i < repeat; i++) {
handler.postDelayed(new Runnable() {
@Override
public void run() {
lightLed(context, colorOx, startOffMS, durationMS);
}
}, (startOffMS + durationMS) * i);
}
}
public static void lightLed(Context context, ArrayList<LightPattern> patterns) {
if (patterns == null) {
return;
}
for (LightPattern lp : patterns) {
lightLed(context, lp.argb, lp.startOffMS, lp.durationMS);
}
}
public static class LightPattern {
public int argb = 0;
public int startOffMS = 0;
public int durationMS = 0;
public LightPattern(int argb, int startOffMS, int durationMS) {
this.argb = argb;
this.startOffMS = startOffMS;
this.durationMS = durationMS;
}
}
}
@@ -0,0 +1,82 @@
package com.litesuits.common.utils;
/**
* @author MaTianyu
* @date 2014-11-21
*/
public class NumberUtil {
public static int convertToint(String intStr, int defValue) {
try {
return Integer.parseInt(intStr);
} catch (NumberFormatException e) {
//e.printStackTrace();
}
return defValue;
}
public static long convertTolong(String longStr, long defValue) {
try {
return Long.parseLong(longStr);
} catch (NumberFormatException e) {
//e.printStackTrace();
}
return defValue;
}
public static float convertTofloat(String fStr, float defValue) {
try {
return Float.parseFloat(fStr);
} catch (NumberFormatException e) {
//e.printStackTrace();
}
return defValue;
}
public static double convertTodouble(String dStr, double defValue) {
try {
return Double.parseDouble(dStr);
} catch (NumberFormatException e) {
//e.printStackTrace();
}
return defValue;
}
public static Integer convertToInteger(String intStr) {
try {
return Integer.parseInt(intStr);
} catch (NumberFormatException e) {
//e.printStackTrace();
}
return null;
}
public static Long convertToLong(String longStr) {
try {
return Long.parseLong(longStr);
} catch (NumberFormatException e) {
//e.printStackTrace();
}
return null;
}
public static Float convertToFloat(String fStr) {
try {
return Float.parseFloat(fStr);
} catch (NumberFormatException e) {
//e.printStackTrace();
}
return null;
}
public static Double convertToDouble(String dStr) {
try {
return Double.parseDouble(dStr);
} catch (NumberFormatException e) {
//e.printStackTrace();
}
return null;
}
}
@@ -0,0 +1,280 @@
package com.litesuits.common.utils;
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import android.widget.Toast;
import com.litesuits.common.assist.Check;
import java.io.File;
import java.util.List;
import java.util.Map;
/**
* @author MaTianyu
* @date 14-11-7
*/
public class PackageUtil {
/**
* App installation location flags of android system
*/
public static final int APP_INSTALL_AUTO = 0;
public static final int APP_INSTALL_INTERNAL = 1;
public static final int APP_INSTALL_EXTERNAL = 2;
/**
* 调用系统安装应用
*/
public static boolean install(Context context, File file) {
if (file == null || !file.exists() || !file.isFile()) {
return false;
}
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
return true;
}
/**
* 调用系统卸载应用
*/
public static void uninstallApk(Context context, String packageName) {
Intent intent = new Intent(Intent.ACTION_DELETE);
Uri packageURI = Uri.parse("package:" + packageName);
intent.setData(packageURI);
context.startActivity(intent);
}
/**
* 打开已安装应用的详情
*/
public static void goToInstalledAppDetails(Context context, String packageName) {
Intent intent = new Intent();
int sdkVersion = Build.VERSION.SDK_INT;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.fromParts("package", packageName, null));
} else {
intent.setAction(Intent.ACTION_VIEW);
intent.setClassName("com.android.settings", "com.android.settings.InstalledAppDetails");
intent.putExtra((sdkVersion == Build.VERSION_CODES.FROYO ? "pkg"
: "com.android.settings.ApplicationPkgName"), packageName);
}
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
/**
* 获取指定程序信息
*/
public static ActivityManager.RunningTaskInfo getTopRunningTask(Context context) {
try {
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
// 得到当前正在运行的任务栈
List<ActivityManager.RunningTaskInfo> runningTasks = am.getRunningTasks(1);
// 得到前台显示的任务栈
ActivityManager.RunningTaskInfo runningTaskInfo = runningTasks.get(0);
return runningTaskInfo;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static String getAppVersionName(Context context) {
try {
PackageManager pm = context.getPackageManager();
PackageInfo pi = pm.getPackageInfo(context.getPackageName(), 0);
return pi.versionName;
} catch (NameNotFoundException e) {
e.printStackTrace();
}
return "";
}
public static int getAppVersionCode(Context context) {
try {
PackageManager pm = context.getPackageManager();
PackageInfo pi = pm.getPackageInfo(context.getPackageName(), 0);
return pi.versionCode;
} catch (NameNotFoundException e) {
e.printStackTrace();
}
return -1;
}
/**
* 获取当前系统安装应用的默认位置
*
* @return APP_INSTALL_AUTO or APP_INSTALL_INTERNAL or APP_INSTALL_EXTERNAL.
*/
public static int getInstallLocation() {
ShellUtil.CommandResult commandResult = ShellUtil.execCommand(
"LD_LIBRARY_PATH=/vendor/lib:/system/lib pm get-install-location", false, true);
if (commandResult.result == 0 && commandResult.responseMsg != null && commandResult.responseMsg.length() > 0) {
try {
return Integer.parseInt(commandResult.responseMsg.substring(0, 1));
} catch (NumberFormatException e) {
e.printStackTrace();
}
}
return APP_INSTALL_AUTO;
}
/**
* get app package info
*/
public static PackageInfo getAppPackageInfo(Context context) {
if (context != null) {
PackageManager pm = context.getPackageManager();
if (pm != null) {
PackageInfo pi;
try {
return pm.getPackageInfo(context.getPackageName(), 0);
} catch (Exception e) {
e.printStackTrace();
}
}
}
return null;
}
/**
* whether context is system application
*/
public static boolean isSystemApplication(Context context) {
if (context == null) {
return false;
}
return isSystemApplication(context, context.getPackageName());
}
/**
* whether packageName is system application
*/
public static boolean isSystemApplication(Context context, String packageName) {
PackageManager packageManager = context.getPackageManager();
if (packageManager == null || packageName == null || packageName.length() == 0) {
return false;
}
try {
ApplicationInfo app = packageManager.getApplicationInfo(packageName, 0);
return (app != null && (app.flags & ApplicationInfo.FLAG_SYSTEM) > 0);
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
/**
* 获取已安装的全部应用信息
*/
public static List<PackageInfo> getInsatalledPackages(Context context) {
return context.getPackageManager().getInstalledPackages(0);
}
/**
* 获取已安装的全部应用信息
*/
public static boolean isInsatalled(Context context, String pkg) {
if (!Check.isEmpty(pkg)) {
List<PackageInfo> list = getInsatalledPackages(context);
if (!Check.isEmpty(list)) {
for (PackageInfo pi : list) {
if (pkg.equalsIgnoreCase(pi.packageName)) {
return true;
}
}
}
}
return false;
}
/**
* 获取指定程序信息
*/
public static ApplicationInfo getApplicationInfo(Context context, String pkg) {
try {
return context.getPackageManager().getApplicationInfo(pkg, 0);
} catch (NameNotFoundException e) {
e.printStackTrace();
}
return null;
}
/**
* 获取指定程序信息
*/
public static android.content.pm.PackageInfo getPackageInfo(Context context, String pkg) {
try {
return context.getPackageManager().getPackageInfo(pkg, 0);
} catch (NameNotFoundException e) {
e.printStackTrace();
}
return null;
}
/**
* 启动应用
*/
public static boolean startAppByPackageName(Context context, String packageName) {
return startAppByPackageName(context, packageName, null);
}
/**
* 启动应用
*/
public static boolean startAppByPackageName(Context context, String packageName, Map<String, String> param) {
android.content.pm.PackageInfo pi = null;
try {
pi = context.getPackageManager().getPackageInfo(packageName, 0);
Intent resolveIntent = new Intent(Intent.ACTION_MAIN, null);
resolveIntent.addCategory(Intent.CATEGORY_LAUNCHER);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.DONUT) {
resolveIntent.setPackage(pi.packageName);
}
List<ResolveInfo> apps = context.getPackageManager().queryIntentActivities(resolveIntent, 0);
ResolveInfo ri = apps.iterator().next();
if (ri != null) {
String packageName1 = ri.activityInfo.packageName;
String className = ri.activityInfo.name;
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
ComponentName cn = new ComponentName(packageName1, className);
intent.setComponent(cn);
if (param != null) {
for (Map.Entry<String, String> en : param.entrySet()) {
intent.putExtra(en.getKey(), en.getValue());
}
}
context.startActivity(intent);
return true;
}
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(context.getApplicationContext(), "启动失败",
Toast.LENGTH_LONG).show();
}
return false;
}
}
@@ -0,0 +1,59 @@
package com.litesuits.common.utils;
import android.annotation.TargetApi;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.SystemClock;
/**
* @author MaTianyu
* @date 2015-03-26
*/
public class PollingUtil {
/**
* 开启轮询
*/
@TargetApi(Build.VERSION_CODES.CUPCAKE)
public static void startPolling(Context context, int mills, PendingIntent pendingIntent) {
AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
manager.setRepeating(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime(),
mills, pendingIntent);
}
/**
* 停止轮询
*/
@TargetApi(Build.VERSION_CODES.CUPCAKE)
public static void stopPolling(Context context, PendingIntent pendingIntent) {
AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
manager.cancel(pendingIntent);
}
/**
* 开启轮询服务
*/
@TargetApi(Build.VERSION_CODES.CUPCAKE)
public static void startPollingService(Context context, int mills, Class<?> cls, String action) {
Intent intent = new Intent(context, cls);
intent.setAction(action);
PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
startPolling(context, mills, pendingIntent);
}
/**
* 停止启轮询服务
*/
@TargetApi(Build.VERSION_CODES.CUPCAKE)
public static void stopPollingService(Context context, Class<?> cls, String action) {
Intent intent = new Intent(context, cls);
intent.setAction(action);
PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
stopPolling(context, pendingIntent);
}
}
@@ -0,0 +1,206 @@
package com.litesuits.common.utils;
import java.util.Random;
/**
* 随机工具类
* modified form Trinea
* @author trinea
* @date 2014-12-10
*/
public class RandomUtil {
public static final String NUMBERS_AND_LETTERS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static final String NUMBERS = "0123456789";
public static final String LETTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static final String CAPITAL_LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static final String LOWER_CASE_LETTERS = "abcdefghijklmnopqrstuvwxyz";
private RandomUtil() {
throw new AssertionError();
}
/**
* get a fixed-length random string, its a mixture of uppercase, lowercase letters and numbers
*
* @param length
* @return
* @see RandomUtil#getRandom(String source, int length)
*/
public static String getRandomNumbersAndLetters(int length) {
return getRandom(NUMBERS_AND_LETTERS, length);
}
/**
* get a fixed-length random string, its a mixture of numbers
*
* @param length
* @return
* @see RandomUtil#getRandom(String source, int length)
*/
public static String getRandomNumbers(int length) {
return getRandom(NUMBERS, length);
}
/**
* get a fixed-length random string, its a mixture of uppercase and lowercase letters
*
* @param length
* @return
* @see RandomUtil#getRandom(String source, int length)
*/
public static String getRandomLetters(int length) {
return getRandom(LETTERS, length);
}
/**
* get a fixed-length random string, its a mixture of uppercase letters
*
* @param length
* @return
* @see RandomUtil#getRandom(String source, int length)
*/
public static String getRandomCapitalLetters(int length) {
return getRandom(CAPITAL_LETTERS, length);
}
/**
* get a fixed-length random string, its a mixture of lowercase letters
*
* @param length
* @return
* @see RandomUtil#getRandom(String source, int length)
*/
public static String getRandomLowerCaseLetters(int length) {
return getRandom(LOWER_CASE_LETTERS, length);
}
/**
* get a fixed-length random string, its a mixture of chars in source
*
* @param source
* @param length
* @return <ul>
* <li>if source is null or empty, return null</li>
* <li>else see {@link RandomUtil#getRandom(char[] sourceChar, int length)}</li>
* </ul>
*/
public static String getRandom(String source, int length) {
return source == null ? null : getRandom(source.toCharArray(), length);
}
/**
* get a fixed-length random string, its a mixture of chars in sourceChar
*
* @param sourceChar
* @param length
* @return <ul>
* <li>if sourceChar is null or empty, return null</li>
* <li>if length less than 0, return null</li>
* </ul>
*/
public static String getRandom(char[] sourceChar, int length) {
if (sourceChar == null || sourceChar.length == 0 || length < 0) {
return null;
}
StringBuilder str = new StringBuilder(length);
Random random = new Random();
for (int i = 0; i < length; i++) {
str.append(sourceChar[random.nextInt(sourceChar.length)]);
}
return str.toString();
}
/**
* get random int between 0 and max
*
* @param max
* @return <ul>
* <li>if max <= 0, return 0</li>
* <li>else return random int between 0 and max</li>
* </ul>
*/
public static int getRandom(int max) {
return getRandom(0, max);
}
/**
* get random int between min and max
*
* @param min
* @param max
* @return <ul>
* <li>if min > max, return 0</li>
* <li>if min == max, return min</li>
* <li>else return random int between min and max</li>
* </ul>
*/
public static int getRandom(int min, int max) {
if (min > max) {
return 0;
}
if (min == max) {
return min;
}
return min + new Random().nextInt(max - min);
}
/**
* Shuffling algorithm, Randomly permutes the specified array using a default source of randomness
*/
public static boolean shuffle(Object[] objArray) {
if (objArray == null) {
return false;
}
return shuffle(objArray, getRandom(objArray.length));
}
/**
* Shuffling algorithm, Randomly permutes the specified array
*/
public static boolean shuffle(Object[] objArray, int shuffleCount) {
int length;
if (objArray == null || shuffleCount < 0 || (length = objArray.length) < shuffleCount) {
return false;
}
for (int i = 1; i <= shuffleCount; i++) {
int random = getRandom(length - i);
Object temp = objArray[length - i];
objArray[length - i] = objArray[random];
objArray[random] = temp;
}
return true;
}
/**
* Shuffling algorithm, Randomly permutes the specified int array using a default source of randomness
*/
public static int[] shuffle(int[] intArray) {
if (intArray == null) {
return null;
}
return shuffle(intArray, getRandom(intArray.length));
}
/**
* Shuffling algorithm, Randomly permutes the specified int array
*/
public static int[] shuffle(int[] intArray, int shuffleCount) {
int length;
if (intArray == null || shuffleCount < 0 || (length = intArray.length) < shuffleCount) {
return null;
}
int[] out = new int[shuffleCount];
for (int i = 1; i <= shuffleCount; i++) {
int random = getRandom(length - i);
out[i - 1] = intArray[random];
int temp = intArray[length - i];
intArray[length - i] = intArray[random];
intArray[random] = temp;
}
return out;
}
}
@@ -0,0 +1,212 @@
package com.litesuits.common.utils;
import android.annotation.TargetApi;
import android.os.Build;
import android.os.Environment;
import android.os.StatFs;
import com.litesuits.android.log.Log;
import java.io.*;
import java.util.ArrayList;
/**
* Get SD card info.
*
* @author MaTianyu
* @date 2015-04-19
*/
public class SdCardUtil {
private static final String TAG = SdCardUtil.class.getSimpleName();
/**
* is sd card available.
* @return true if available
*/
public boolean isSdCardAvailable() {
return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState());
}
/**
* Get {@link android.os.StatFs}.
*/
public static StatFs getStatFs(String path) {
return new StatFs(path);
}
/**
* Get phone data path.
*/
public static String getDataPath() {
return Environment.getDataDirectory().getPath();
}
/**
* Get SD card path.
*/
public static String getNormalSDCardPath() {
return Environment.getExternalStorageDirectory().getPath();
}
/**
* Get SD card path by CMD.
*/
public static String getSDCardPath() {
String cmd = "cat /proc/mounts";
String sdcard = null;
Runtime run = Runtime.getRuntime();// 返回与当前 Java 应用程序相关的运行时对象
BufferedReader bufferedReader = null;
try {
Process p = run.exec(cmd);// 启动另一个进程来执行命令
bufferedReader = new BufferedReader(new InputStreamReader(new BufferedInputStream(p.getInputStream())));
String lineStr;
while ((lineStr = bufferedReader.readLine()) != null) {
Log.i(TAG, "proc/mounts: " + lineStr);
if (lineStr.contains("sdcard")
&& lineStr.contains(".android_secure")) {
String[] strArray = lineStr.split(" ");
if (strArray.length >= 5) {
sdcard = strArray[1].replace("/.android_secure", "");
Log.i(TAG, "find sd card path: " + sdcard);
return sdcard;
}
}
if (p.waitFor() != 0 && p.exitValue() == 1) {
// p.exitValue()==0表示正常结束,1:非正常结束
Log.e(TAG, cmd + " 命令执行失败");
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (bufferedReader != null) {
bufferedReader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
sdcard = Environment.getExternalStorageDirectory().getPath();
Log.i(TAG, "not find sd card path return default: " + sdcard);
return sdcard;
}
/**
* Get SD card path list.
*/
public static ArrayList<String> getSDCardPathEx() {
ArrayList<String> list = new ArrayList<String>();
try {
Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec("mount");
InputStream is = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
String line;
BufferedReader br = new BufferedReader(isr);
while ((line = br.readLine()) != null) {
Log.i(TAG, "mount: " + line);
if (line.contains("secure")) {
continue;
}
if (line.contains("asec")) {
continue;
}
if (line.contains("fat")) {
String columns[] = line.split(" ");
if (columns.length > 1) {
list.add("*" + columns[1]);
}
} else if (line.contains("fuse")) {
String columns[] = line.split(" ");
if (columns.length > 1) {
list.add(columns[1]);
}
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return list;
}
/**
* Get available size of SD card.
*/
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
public static long getAvailableSize(String path) {
try {
File base = new File(path);
StatFs stat = new StatFs(base.getPath());
return stat.getBlockSizeLong() * stat.getAvailableBlocksLong();
} catch (Exception e) {
e.printStackTrace();
}
return 0;
}
/**
* Get SD card info detail.
*/
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
public static SDCardInfo getSDCardInfo() {
SDCardInfo sd = new SDCardInfo();
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
sd.isExist = true;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
File sdcardDir = Environment.getExternalStorageDirectory();
StatFs sf = new StatFs(sdcardDir.getPath());
sd.totalBlocks = sf.getBlockCountLong();
sd.blockByteSize = sf.getBlockSizeLong();
sd.availableBlocks = sf.getAvailableBlocksLong();
sd.availableBytes = sf.getAvailableBytes();
sd.freeBlocks = sf.getFreeBlocksLong();
sd.freeBytes = sf.getFreeBytes();
sd.totalBytes = sf.getTotalBytes();
}
}
if (Log.isPrint) {
Log.i(TAG, sd.toString());
}
return sd;
}
/**
* see more {@link android.os.StatFs}
*/
public static class SDCardInfo {
public boolean isExist;
public long totalBlocks;
public long freeBlocks;
public long availableBlocks;
public long blockByteSize;
public long totalBytes;
public long freeBytes;
public long availableBytes;
@Override
public String toString() {
return "SDCardInfo{" +
"isExist=" + isExist +
", totalBlocks=" + totalBlocks +
", freeBlocks=" + freeBlocks +
", availableBlocks=" + availableBlocks +
", blockByteSize=" + blockByteSize +
", totalBytes=" + totalBytes +
", freeBytes=" + freeBytes +
", availableBytes=" + availableBytes +
'}';
}
}
}
@@ -0,0 +1,137 @@
package com.litesuits.common.utils;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
/**
* modified form Trinea
* @author trinea
* @date 2014-12-10
*/
public class ShellUtil {
/**
* check whether has root permission
*/
public static boolean hasRootPermission() {
return execCommand("echo root", true, false).result == 0;
}
public static CommandResult execCommand(String command, boolean isRoot) {
return execCommand(new String[] {command}, isRoot, true);
}
public static CommandResult execCommand(String command, boolean isRoot, boolean isNeedResultMsg) {
return execCommand(new String[]{command}, isRoot, isNeedResultMsg);
}
public static CommandResult execCommand(List<String> commands, boolean isRoot, boolean isNeedResultMsg) {
return execCommand(commands == null ? null : commands.toArray(new String[]{}), isRoot, isNeedResultMsg);
}
/**
* execute shell commands
* {@link CommandResult#result} is -1, there maybe some excepiton.
*
* @param commands command array
* @param isRoot whether need to run with root
* @param needResponse whether need result msg
*/
public static CommandResult execCommand(String[] commands, boolean isRoot, boolean needResponse) {
int result = -1;
if (commands == null || commands.length == 0) {
return new CommandResult(result, null, "空命令");
}
Process process = null;
BufferedReader successResult = null;
BufferedReader errorResult = null;
StringBuilder successMsg = null;
StringBuilder errorMsg = null;
DataOutputStream os = null;
try {
process = Runtime.getRuntime().exec(isRoot ? COMMAND_SU : COMMAND_SH);
os = new DataOutputStream(process.getOutputStream());
for (String command : commands) {
if (command == null) {
continue;
}
// donnot use os.writeBytes(commmand), avoid chinese charset error
os.write(command.getBytes());
os.writeBytes(COMMAND_LINE_END);
os.flush();
}
os.writeBytes(COMMAND_EXIT);
os.flush();
result = process.waitFor();
if (needResponse) {
successMsg = new StringBuilder();
errorMsg = new StringBuilder();
successResult = new BufferedReader(new InputStreamReader(process.getInputStream()));
errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String s;
while ((s = successResult.readLine()) != null) {
successMsg.append(s);
}
while ((s = errorResult.readLine()) != null) {
errorMsg.append(s);
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (errorResult != null) {
errorResult.close();
}
if (successResult != null) {
successResult.close();
}
if (os != null) {
os.close();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (process != null) {
process.destroy();
}
}
}
return new CommandResult(result, successMsg == null ? null : successMsg.toString(), errorMsg == null ? null
: errorMsg.toString());
}
public static class CommandResult {
public int result;
public String responseMsg;
public String errorMsg;
public CommandResult(int result) {
this.result = result;
}
public CommandResult(int result, String responseMsg, String errorMsg) {
this.result = result;
this.responseMsg = responseMsg;
this.errorMsg = errorMsg;
}
}
public static final String COMMAND_SU = "su";
public static final String COMMAND_SH = "sh";
public static final String COMMAND_EXIT = "exit\n";
public static final String COMMAND_LINE_END = "\n";
}
@@ -0,0 +1,289 @@
package com.litesuits.common.utils;
import android.content.Context;
import android.telephony.TelephonyManager;
import com.litesuits.android.log.Log;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Get phone info, such as IMEI,IMSI,Number,Sim State, etc.
*
* <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
*
* @author MaTianyu
* @date 2014-09-25
*/
public class TelephoneUtil {
private static final String TAG = TelephoneUtil.class.getSimpleName();
/**
* IMSI是国际移动用户识别码的简称(International Mobile Subscriber Identity)
* IMSI共有15位,其结构如下:
* MCC+MNC+MIN
* MCCMobile Country Code,移动国家码,共3位,中国为460;
* MNC:Mobile NetworkCode,移动网络码,共2位
* 在中国,移动的代码为电00和02,联通的代码为01,电信的代码为03
* 合起来就是(也是Android手机中APN配置文件中的代码):
* 中国移动:46000 46002
* 中国联通:46001
* 中国电信:46003
* 举例,一个典型的IMSI号码为460030912121001
*/
public static String getIMSI(Context context) {
TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
String IMSI = telephonyManager.getSubscriberId();
Log.i(TAG, " IMSI" + IMSI);
return IMSI;
}
/**
* IMEI是International Mobile Equipment Identity (国际移动设备标识)的简称
* IMEI由15位数字组成的”电子串号”,它与每台手机一一对应,而且该码是全世界唯一的
* 其组成为:
* 1. 前6位数(TAC)是”型号核准号码”,一般代表机型
* 2. 接着的2位数(FAC)是”最后装配号”,一般代表产地
* 3. 之后的6位数(SNR)是”串号”,一般代表生产顺序号
* 4. 最后1位数(SP)通常是”0″,为检验码,目前暂备用
*/
public static String getIMEI(Context context) {
TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
String IMEI = telephonyManager.getDeviceId();
Log.i(TAG, " IMEI" + IMEI);
return IMEI;
}
/**
* Print telephone info.
*/
public static String printTelephoneInfo(Context context) {
Date date = new Date(System.currentTimeMillis());
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time = dateFormat.format(date);
StringBuilder sb = new StringBuilder();
sb.append("_______ 手机信息 ").append(time).append(" ______________");
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
String IMSI = tm.getSubscriberId();
//IMSI前面三位460是国家号码,其次的两位是运营商代号,00、02是中国移动,01是联通,03是电信。
String providerName = null;
if (IMSI != null) {
if (IMSI.startsWith("46000") || IMSI.startsWith("46002")) {
providerName = "中国移动";
} else if (IMSI.startsWith("46001")) {
providerName = "中国联通";
} else if (IMSI.startsWith("46003")) {
providerName = "中国电信";
}
}
sb.append(providerName).append(" 手机号:").append(tm.getLine1Number()).append(" IMSI是:").append(IMSI);
sb.append("\nDeviceID(IMEI) :").append(tm.getDeviceId());
sb.append("\nDeviceSoftwareVersion:").append(tm.getDeviceSoftwareVersion());
sb.append("\ngetLine1Number :").append(tm.getLine1Number());
sb.append("\nNetworkCountryIso :").append(tm.getNetworkCountryIso());
sb.append("\nNetworkOperator :").append(tm.getNetworkOperator());
sb.append("\nNetworkOperatorName :").append(tm.getNetworkOperatorName());
sb.append("\nNetworkType :").append(tm.getNetworkType());
sb.append("\nPhoneType :").append(tm.getPhoneType());
sb.append("\nSimCountryIso :").append(tm.getSimCountryIso());
sb.append("\nSimOperator :").append(tm.getSimOperator());
sb.append("\nSimOperatorName :").append(tm.getSimOperatorName());
sb.append("\nSimSerialNumber :").append(tm.getSimSerialNumber());
sb.append("\ngetSimState :").append(tm.getSimState());
sb.append("\nSubscriberId :").append(tm.getSubscriberId());
sb.append("\nVoiceMailNumber :").append(tm.getVoiceMailNumber());
Log.i(TAG, sb.toString());
return sb.toString();
}
/////_________________ 双卡双待系统IMEI和IMSI方案(see more on http://benson37.iteye.com/blog/1923946
/**
* 双卡双待神机IMSI、IMSI、PhoneType信息
* <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
*/
public static class TeleInfo {
public String imsi_1;
public String imsi_2;
public String imei_1;
public String imei_2;
public int phoneType_1;
public int phoneType_2;
@Override
public String toString() {
return "TeleInfo{" +
"imsi_1='" + imsi_1 + '\'' +
", imsi_2='" + imsi_2 + '\'' +
", imei_1='" + imei_1 + '\'' +
", imei_2='" + imei_2 + '\'' +
", phoneType_1=" + phoneType_1 +
", phoneType_2=" + phoneType_2 +
'}';
}
}
/**
* MTK Phone.
*
* 获取 MTK 神机的双卡 IMSI、IMSI 信息
*/
public static TeleInfo getMtkTeleInfo(Context context) {
TeleInfo teleInfo = new TeleInfo();
try {
Class<?> phone = Class.forName("com.android.internal.telephony.Phone");
Field fields1 = phone.getField("GEMINI_SIM_1");
fields1.setAccessible(true);
int simId_1 = (Integer) fields1.get(null);
Field fields2 = phone.getField("GEMINI_SIM_2");
fields2.setAccessible(true);
int simId_2 = (Integer) fields2.get(null);
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
Method getSubscriberIdGemini = TelephonyManager.class.getDeclaredMethod("getSubscriberIdGemini", int.class);
String imsi_1 = (String) getSubscriberIdGemini.invoke(tm, simId_1);
String imsi_2 = (String) getSubscriberIdGemini.invoke(tm, simId_2);
teleInfo.imsi_1 = imsi_1;
teleInfo.imsi_2 = imsi_2;
Method getDeviceIdGemini = TelephonyManager.class.getDeclaredMethod("getDeviceIdGemini", int.class);
String imei_1 = (String) getDeviceIdGemini.invoke(tm, simId_1);
String imei_2 = (String) getDeviceIdGemini.invoke(tm, simId_2);
teleInfo.imei_1 = imei_1;
teleInfo.imei_2 = imei_2;
Method getPhoneTypeGemini = TelephonyManager.class.getDeclaredMethod("getPhoneTypeGemini", int.class);
int phoneType_1 = (Integer) getPhoneTypeGemini.invoke(tm, simId_1);
int phoneType_2 = (Integer) getPhoneTypeGemini.invoke(tm, simId_2);
teleInfo.phoneType_1 = phoneType_1;
teleInfo.phoneType_2 = phoneType_2;
} catch (Exception e) {
e.printStackTrace();
}
Log.i(TAG, "MTK: " + teleInfo);
return teleInfo;
}
/**
* MTK Phone.
*
* 获取 MTK 神机的双卡 IMSI、IMSI 信息
*/
public static TeleInfo getMtkTeleInfo2(Context context) {
TeleInfo teleInfo = new TeleInfo();
try {
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
Class<?> phone = Class.forName("com.android.internal.telephony.Phone");
Field fields1 = phone.getField("GEMINI_SIM_1");
fields1.setAccessible(true);
int simId_1 = (Integer) fields1.get(null);
Field fields2 = phone.getField("GEMINI_SIM_2");
fields2.setAccessible(true);
int simId_2 = (Integer) fields2.get(null);
Method getDefault = TelephonyManager.class.getMethod("getDefault", int.class);
TelephonyManager tm1 = (TelephonyManager) getDefault.invoke(tm, simId_1);
TelephonyManager tm2 = (TelephonyManager) getDefault.invoke(tm, simId_2);
String imsi_1 = tm1.getSubscriberId();
String imsi_2 = tm2.getSubscriberId();
teleInfo.imsi_1 = imsi_1;
teleInfo.imsi_2 = imsi_2;
String imei_1 = tm1.getDeviceId();
String imei_2 = tm2.getDeviceId();
teleInfo.imei_1 = imei_1;
teleInfo.imei_2 = imei_2;
int phoneType_1 = tm1.getPhoneType();
int phoneType_2 = tm2.getPhoneType();
teleInfo.phoneType_1 = phoneType_1;
teleInfo.phoneType_2 = phoneType_2;
} catch (Exception e) {
e.printStackTrace();
}
Log.i(TAG, "MTK2: " + teleInfo);
return teleInfo;
}
/**
* Qualcomm Phone.
* 获取 高通 神机的双卡 IMSI、IMSI 信息
*/
public static TeleInfo getQualcommTeleInfo(Context context) {
TeleInfo teleInfo = new TeleInfo();
try {
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
Class<?> simTMclass = Class.forName("android.telephony.MSimTelephonyManager");
Object sim = context.getSystemService("phone_msim");
int simId_1 = 0;
int simId_2 = 1;
Method getSubscriberId = simTMclass.getMethod("getSubscriberId", int.class);
String imsi_1 = (String) getSubscriberId.invoke(sim, simId_1);
String imsi_2 = (String) getSubscriberId.invoke(sim, simId_2);
teleInfo.imsi_1 = imsi_1;
teleInfo.imsi_2 = imsi_2;
Method getDeviceId = simTMclass.getMethod("getDeviceId", int.class);
String imei_1 = (String) getDeviceId.invoke(sim, simId_1);
String imei_2 = (String) getDeviceId.invoke(sim, simId_2);
teleInfo.imei_1 = imei_1;
teleInfo.imei_2 = imei_2;
Method getDataState = simTMclass.getMethod("getDataState");
int phoneType_1 = tm.getDataState();
int phoneType_2 = (Integer) getDataState.invoke(sim);
teleInfo.phoneType_1 = phoneType_1;
teleInfo.phoneType_2 = phoneType_2;
} catch (Exception e) {
e.printStackTrace();
}
Log.i(TAG, "Qualcomm: " + teleInfo);
return teleInfo;
}
/**
* Spreadtrum Phone.
*
* 获取 展讯 神机的双卡 IMSI、IMSI 信息
*/
public static TeleInfo getSpreadtrumTeleInfo(Context context) {
TeleInfo teleInfo = new TeleInfo();
try {
TelephonyManager tm1 = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
String imsi_1 = tm1.getSubscriberId();
String imei_1 = tm1.getDeviceId();
int phoneType_1 = tm1.getPhoneType();
teleInfo.imsi_1 = imsi_1;
teleInfo.imei_1 = imei_1;
teleInfo.phoneType_1 = phoneType_1;
Class<?> phoneFactory = Class.forName("com.android.internal.telephony.PhoneFactory");
Method getServiceName = phoneFactory.getMethod("getServiceName", String.class, int.class);
getServiceName.setAccessible(true);
String spreadTmService = (String) getServiceName.invoke(phoneFactory, Context.TELEPHONY_SERVICE, 1);
TelephonyManager tm2 = (TelephonyManager) context.getSystemService(spreadTmService);
String imsi_2 = tm2.getSubscriberId();
String imei_2 = tm2.getDeviceId();
int phoneType_2 = tm2.getPhoneType();
teleInfo.imsi_2 = imsi_2;
teleInfo.imei_2 = imei_2;
teleInfo.phoneType_2 = phoneType_2;
} catch (Exception e) {
e.printStackTrace();
}
Log.i(TAG, "Spreadtrum: " + teleInfo);
return teleInfo;
}
}
@@ -0,0 +1,52 @@
package com.litesuits.common.utils;
import android.content.Context;
import android.os.Vibrator;
/**
* <p>All methods requires the caller to hold the permission
* {@link android.Manifest.permission#VIBRATE}.
*
* @author MaTianyu
* @date 2014-11-21
*/
public class VibrateUtil {
/**
* Vibrate constantly for the specified period of time.
* <p>This method requires the caller to hold the permission
* {@link android.Manifest.permission#VIBRATE}.
*
* @param milliseconds The number of milliseconds to vibrate.
*/
public static void vibrate(Context context, long milliseconds) {
Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(milliseconds);
}
/**
* Vibrate with a given pattern.
* <p/>
* <p>
* Pass in an array of ints that are the durations for which to turn on or off
* the vibrator in milliseconds. The first value indicates the number of milliseconds
* to wait before turning the vibrator on. The next value indicates the number of milliseconds
* for which to keep the vibrator on before turning it off. Subsequent values alternate
* between durations in milliseconds to turn the vibrator off or to turn the vibrator on.
* </p><p>
* To cause the pattern to repeat, pass the index into the pattern array at which
* to start the repeat, or -1 to disable repeating.
* </p>
* <p>This method requires the caller to hold the permission
* {@link android.Manifest.permission#VIBRATE}.
*
* @param pattern an array of longs of times for which to turn the vibrator on or off.
* @param repeat the index into pattern at which to repeat, or -1 if
* you don't want to repeat.
*/
public static void vibrate(Context context, long[] pattern, int repeat) {
Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(pattern, repeat);
}
}
@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<resources></resources>
@@ -0,0 +1,3 @@
<resources>
<string name="app_name">android-common</string>
</resources>
@@ -0,0 +1 @@
<resources></resources>
+30
View File
@@ -0,0 +1,30 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.6.1'
// classpath 'com.android.tools.build:gradle:4.2.1'
// classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5'
// classpath "com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
maven { url "https://jitpack.io" }
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
Binary file not shown.
+160
View File
@@ -0,0 +1,160 @@
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
+90
View File
@@ -0,0 +1,90 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
+1
View File
@@ -0,0 +1 @@
include ':app'