飞飞的AI实验室

用AI放大灵感,把想法变成作品。

/**
 * 匹配手机号的规则:[3578]是手机号第二位可能出现的数字
 */
public static final String REGEX_MOBILE = "^[1][3578][0-9]{9}$";

/**
 * 校验手机号
 * @param mobile
 * @return 校验通过返回true,否则返回false
 */
public static boolean isMobile(String mobile) {
    return Pattern.matches(REGEX_MOBILE, mobile);
}


1、手机号开头集合
176,177,178,  
180,181,182,183,184,185,186,187,188。,189。  
145,147   
130,131,132,133,134,135,136,137, 138,139  
150,151, 152,153,155,156,157,158,159,  


2、正则表达式

public static boolean isChinaPhoneLegal(String str)  
            throws PatternSyntaxException {  
        String regExp = "^((13[0-9])|(15[^4])|(18[0-9])|(17[0-8])|(147,145))\\d{8}$";  
        Pattern p = Pattern.compile(regExp);  
        Matcher m = p.matcher(str);  
        return m.matches();  
    }  

13开头的后面跟0-9的任意8位数;

15开头的后面跟除了4以外的0-9的任意8位数;

18开头的后面跟0-9的任意8位数;

17开头的后面跟0-8的任意8位数,或者17[^9];

147,145开头后面跟任意8位数;

阅读全文 »

需求:当用户点击提现按钮的时候,弹出输入支付密码的popupwindow,输入密码框后面有显示和隐藏支付密码的切换按钮。

老规矩先验货:

##1.布局文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<LinearLayout
android:layout_width="275dp"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:background="#FFFFFF"
android:orientation="vertical">

<TextView
android:id="@+id/tvRecharge"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:gravity="center"
android:text="支付密码验证"
android:textSize="18sp" />

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="#11000000"
android:gravity="center_vertical"
android:orientation="horizontal">

<EditText
android:id="@+id/etPayPwd"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@null"
android:hint="输入支付密码"
android:inputType="textPassword"
android:padding="10dp"
android:paddingRight="10dp" />

<ToggleButton
android:id="@+id/togglePwd"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginRight="10dp"
android:background="@drawable/toggle_pwd_selector"
android:padding="10dp"
android:textOff=""
android:textOn="" />
</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">

<TextView
android:id="@+id/tvCancel"
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_weight="1"
android:gravity="center"
android:text="取消"
android:textSize="16sp" />

<TextView
android:id="@+id/tvConfirm"
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_weight="1"
android:gravity="center"
android:text="确定"
android:textSize="16sp" />
</LinearLayout>
</LinearLayout>

</RelativeLayout>

##2.代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
public class MainActivity extends AppCompatActivity {

private PopupWindow popupWindow;
private View popupView;
private EditText etPayPwd;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btnWithdraw = (Button) findViewById(R.id.btnWithdraw);
btnWithdraw.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
showPayPwdDialog();
BrightnessManager.lightOff(MainActivity.this);
}
});
}

private void showPayPwdDialog() {
if (popupWindow == null) {
popupView = View.inflate(MainActivity.this, R.layout.popupwindow_pay_pwd, null);
popupWindow = new PopupWindow(popupView, WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT);
popupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
BrightnessManager.lightOn(MainActivity.this);
etPayPwd.setText("");
}
});
popupWindow.setBackgroundDrawable(new BitmapDrawable());
popupWindow.setFocusable(true);
popupWindow.setOutsideTouchable(true);

ToggleButton togglePwd = (ToggleButton) popupView.findViewById(R.id.togglePwd);
etPayPwd = (EditText) popupView.findViewById(R.id.etPayPwd);
togglePwd.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
//如果选中,显示密码
etPayPwd.setTransformationMethod(HideReturnsTransformationMethod.getInstance());
} else {
//否则隐藏密码
etPayPwd.setTransformationMethod(PasswordTransformationMethod.getInstance());
}
}
});

popupView.findViewById(R.id.tvCancel).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
popupWindow.dismiss();
BrightnessManager.lightOn(MainActivity.this);
}
});

popupView.findViewById(R.id.tvConfirm).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String payPwd = etPayPwd.getText().toString();
popupWindow.dismiss();
BrightnessManager.lightOn(MainActivity.this);
if (!TextUtils.isEmpty(payPwd)) {
Toast.makeText(MainActivity.this, "提现请求提交成功!", Toast.LENGTH_SHORT).show();
}
}
});
}

if (popupWindow.isShowing()) {
popupWindow.dismiss();
BrightnessManager.lightOn(MainActivity.this);
}
popupWindow.showAtLocation(MainActivity.this.findViewById(R.id.activity_main),
Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, 0);
}
}

OK!今天双11,马云硬是将光棍节过成了购物狂欢节,你让我们这些光棍儿们怎么想?好吧,与我们没关系,咱们继续撸咱们的代码,为了早日迎娶白富美,走向人生巅峰,继续撸不要停!!!

阅读全文 »

今天刚升级完 Android Studio 到3.0.1版本,装完之后,遇到一堆问题,改了一大堆问题,终于改完了,就想打包apk试试,没想到打包时报了如下错误:

Error Expected resource of type id [ResourceType]

点击到报错的地方,原来是依赖的一个开源库一个if判断处报错了,如下图:

但是点击进去之后看了一下也是返回的Int类型的值,我就郁闷了,为什么不能比较了?有哪位大神可以解释一下是为什么吗?

解决办法:

后来在网上搜了一下,只要在这个报错代码所在方法的头上加入如下代码即可:

@SuppressWarnings("ResourceType")

试了试,果然好使,但还是不知道为什么?

大神求解释!!!

阅读全文 »

##1.产生指定位数的随机数

以产生6位数随机数为例

int num = (int) ((Math.random() * 9 + 1) * 100000);

产生其他位数随机数在最后面要乘的数即 100000 后加0即可

##2.产生指定范围的随机数

以产生[10,99]范围内的随机数为例

1
2
3
4
int min=10;
int max=99;
Random random = new Random();
int num = random.nextInt(max)%(max-min+1) + min;

end ~

阅读全文 »

Android布局中颜色表示都是使用十六进制来表示的,使用RGB和ARGB,后者多了一个透明度,而UI设计师通常在标注图中标注的透明度通常为百分比,这就需要我们做一些转换才能使用,透明度从0(透明)到1(不透明)对应的透明度为0%–100%,对应的十六进制为00–FF,对应的十进制为0–255,所以转换公式为:255 x 透明百分比,再将其转换为16进制即可,下面列出了常用的透明度百分比对应的十六进制。

透明度 透明度值
100% FF
95% F2
90% E6
85% D9
80% CC
75% BF
70% B3
65% A6
60% 99
55% 8C
50% 80
45% 73
40% 66
35% 59
30% 4D
25% 40
20% 33
15% 26
10% 1A
5% 0D
0% 00

###Thanks all.

阅读全文 »

1.在res的drawable下新建一个布局animation.xml*文件

version
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="true">

<item
android:drawable="@drawable/image1"
android:duration="32" />
<item
android:drawable="@drawable/image2"
android:duration="32" />
<item
android:drawable="@drawable/image3"
android:duration="32" />
<item
android:drawable="@drawable/image4"
android:duration="32" />
<item
android:drawable="@drawable/image5"
android:duration="32" />
<item
android:drawable="@drawable/image6"
android:duration="32" />
<item
android:drawable="@drawable/image7"
android:duration="32" />
<item
android:drawable="@drawable/image8"
android:duration="32" />
<item
android:drawable="@drawable/image9"
android:duration="32" />
<item
android:drawable="@drawable/image10"
android:duration="32" />
<item
android:drawable="@drawable/image11"
android:duration="32" />
<item
android:drawable="@drawable/image12"
android:duration="32" />
<item
android:drawable="@drawable/image13"
android:duration="32" />
<item
android:drawable="@drawable/image14"
android:duration="32" />
<item
android:drawable="@drawable/image15"
android:duration="32" />
<item
android:drawable="@drawable/image16"
android:duration="32" />
<item
android:drawable="@drawable/image17"
android:duration="32" />
<item
android:drawable="@drawable/image18"
android:duration="32" />
<item
android:drawable="@drawable/image19"
android:duration="32" />
<item
android:drawable="@drawable/image20"
android:duration="32" />
<item
android:drawable="@drawable/image21"
android:duration="32" />
<item
android:drawable="@drawable/image22"
android:duration="32" />
<item
android:drawable="@drawable/image23"
android:duration="32" />
<item
android:drawable="@drawable/image24"
android:duration="32" />
<item
android:drawable="@drawable/image25"
android:duration="32" />
<item
android:drawable="@drawable/image26"
android:duration="32" />
<item
android:drawable="@drawable/image27"
android:duration="32" />
<item
android:drawable="@drawable/image28"
android:duration="32" />
<item
android:drawable="@drawable/image29"
android:duration="32" />
<item
android:drawable="@drawable/image30"
android:duration="32" />
<item
android:drawable="@drawable/image31"
android:duration="32" />
<item
android:drawable="@drawable/image32"
android:duration="32" />
<item
android:drawable="@drawable/image33"
android:duration="32" />
<item
android:drawable="@drawable/image34"
android:duration="32" />
<item
android:drawable="@drawable/image35"
android:duration="32" />
<item
android:drawable="@drawable/image36"
android:duration="32" />
<item
android:drawable="@drawable/image37"
android:duration="32" />
<item
android:drawable="@drawable/image38"
android:duration="32" />
<item
android:drawable="@drawable/image39"
android:duration="32" />
<item
android:drawable="@drawable/image40"
android:duration="32" />
<item
android:drawable="@drawable/image41"
android:duration="32" />
<item
android:drawable="@drawable/image42"
android:duration="32" />
<item
android:drawable="@drawable/image43"
android:duration="32" />
<item
android:drawable="@drawable/image44"
android:duration="32" />
<item
android:drawable="@drawable/image45"
android:duration="32" />
<item
android:drawable="@drawable/image46"
android:duration="32" />
<item
android:drawable="@drawable/image47"
android:duration="32" />
<item
android:drawable="@drawable/image48"
android:duration="32" />
<item
android:drawable="@drawable/image49"
android:duration="32" />
<item
android:drawable="@drawable/image50"
android:duration="32" />
<item
android:drawable="@drawable/image51"
android:duration="32" />
<item
android:drawable="@drawable/image52"
android:duration="32" />
<item
android:drawable="@drawable/image53"
android:duration="32" />
<item
android:drawable="@drawable/image54"
android:duration="32" />
<item
android:drawable="@drawable/image55"
android:duration="32" />
<item
android:drawable="@drawable/image56"
android:duration="32" />
<item
android:drawable="@drawable/image57"
android:duration="32" />
<item
android:drawable="@drawable/image58"
android:duration="32" />
<item
android:drawable="@drawable/image59"
android:duration="32" />
<item
android:drawable="@drawable/image60"
android:duration="32" />

</animation-list>

**android:oneshot=”true”**当为true时表示只播放一次,为false时表示循环播放;

2.给ImageView设置帧动画的src

1
2
3
4
5
6
7
<ImageView
android:id="@+id/ivLoading"
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_centerInParent="true"
android:src="@drawable/animation"
android:visibility="gone" />

3.播放帧动画

1
2
3
ivLoading.setImageResource(R.drawable.animation);
drawable = (AnimationDrawable) ivLoading.getDrawable();
drawable.start();

4.以上播放默认是没有监听的,所以我们这里提供一种自定义View,可以监听帧动画播完的监听

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
/**
* 自定义可以播放动态图片的ImageView
*/
public class AnimationImageView extends ImageView {

public AnimationImageView(Context context) {
super(context);
}

public AnimationImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}

public AnimationImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}



public interface OnFrameAnimationListener{
/**
* 动画开始播放后调用
*/
void onStart();
/**
* 动画结束播放后调用
*/
void onEnd();
}

/**
* 不带动画监听的播放
* @param resId
*/
public void loadAnimation(int resId){
setImageResource(resId);
AnimationDrawable anim = (AnimationDrawable)getDrawable();
anim.start();
}

/**
* 带动画监听的播放
* @param resId
* @param listener
*/
public void loadAnimation(int resId, final OnFrameAnimationListener listener) {
setImageResource(resId);
AnimationDrawable anim = (AnimationDrawable)getDrawable();
anim.start();
if(listener != null){
// 调用回调函数onStart
listener.onStart();
}

// 计算动态图片所花费的事件
int durationTime = 0;
for (int i = 0; i < anim.getNumberOfFrames(); i++) {
durationTime += anim.getDuration(i);
}

// 动画结束后
new Handler().postDelayed(new Runnable() {

@Override
public void run() {
if(listener != null){
// 调用回调函数onEnd
listener.onEnd();
}
}
}, durationTime);
}
}

5.代码中加载并设置监听

阅读全文 »

微信公众号:CodingAndroid
CSDN:https://blog.csdn.net/xinpengfei521
声明:本文由 CodingAndroid 原创,未经授权,不可随意转载!

需求

我们在开发中都会遇到这样的一个需求:删除指定目录下指定的前缀或者后缀文件名的文件。

实现思路

对外暴露三个参数,参数一:要删除的文件目录的路径,参数二:区分是前缀还是后缀,参数三:具体前缀或者后缀字符规则。

先枚举出路径目录下的所有文件,枚举的同时实现一个FilenameFilter接口的类,可以自定义规则,比说前缀、后缀或者其他规则,枚举的同时将我们的过滤器作为参数,这样我们就可以匹配到指定条件的文件,然后删除即可。

实现一个删除逻辑的Runnable

代码实现的逻辑也比较简单,大家都能看得懂,下面我就直接贴代码了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
package com.xpf.deletedemo;


import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.util.Log;

import java.io.File;
import java.io.FilenameFilter;

/**
* Created by xpf on 2017/12/25 :)
* Function:删除指定规则的文件
*/

public class DeleteRunnable implements Runnable {

private String mRegEx;
private String dirPath;
private boolean isPrefix;
private static final String TAG = DeleteRunnable.class.getSimpleName();

/**
* Constructor
*
* @param dirPath 要删除文件所在的目录路径
* @param isPrefix true为前缀 false为后缀
* @param mRegEx 规则
*/
public DeleteRunnable(String dirPath, boolean isPrefix, String mRegEx) {
this.mRegEx = mRegEx;
this.dirPath = dirPath;
this.isPrefix = isPrefix;
}

@Override
public void run() {
enumAllFileList();
}

/**
* 枚举并删除所有符合条件(前缀)的文件
*/
private void enumAllFileList() {
if (!TextUtils.isEmpty(dirPath)) {
File adDir = new File(dirPath);
if (adDir.exists() && adDir.isDirectory()) {
if (!TextUtils.isEmpty(mRegEx)) {
DeleteFileFilter filter = new DeleteFileFilter(isPrefix, mRegEx);
// 2.匹配是否是需要删除的文件
File[] fileList = adDir.listFiles(filter);
if (fileList != null && fileList.length > 0) {
for (File file : fileList) {
if (file.isFile() && file.exists()) {
boolean delete = file.delete();
Log.i(TAG, "删除符合条件前缀的旧广告素材" + (delete ? "成功~" : "失败!"));
}
}
}
}
}
}
}

/**
* Created by xpf on 2017/12/25 :)
* Function:以xxx开头或后缀的文件名的过滤器
*/
class DeleteFileFilter implements FilenameFilter {

private boolean isPrefix;
private String mRegEx;// 前缀或后缀规则

public DeleteFileFilter(boolean isPrefix, @NonNull String regEx) {
this.isPrefix = isPrefix;
this.mRegEx = regEx;
}

@Override
public boolean accept(File file, String s) {
return isPrefix ? s.startsWith(mRegEx) : s.endsWith(mRegEx);
}
}
}

定义文件删除的异常操作工具类

因为操作文件属于耗时操作,我们使用 SingleThreadExecutor 线程池实现如下一个工具类

阅读全文 »

点击上面蓝色字体关注“IT大飞说”
置顶公众号(**ID:ITBigFly**)第一时间收到推送

本篇文章来自「UartAnd7c」的投稿
原文地址:https://www.jianshu.com/p/9495ba92c138 原作者简书主页:https://www.jianshu.com/u/621bfbc7c878
UartAnd7c 是一个在简书坚持原创的 Android 开发者,欢迎大家关注!

今天把玩公司App发现了一个有趣的现象。启动app白屏。之前没太留意过;在参照大厂App解决白屏的方案后。简单汇总一下。

前言

冷启动:App第一次启动的时候会加载一个Application进程,首先会创建和初始化Appliation类,然后在加载Activity。
热启动:利用后台已经拥有的进程,从而避免了Application的加载。直接去加载Activity。

解决白屏的方案大致有以下四种

  • 加入动画
  • 使用占位图
  • 使用图片
  • 使用windowDisablePreview属性

这里我就描述一下使用占位图和windowDisablePreview属性

阅读全文 »

在使用EventBus时报如下异常:

1
2
3
4
E/EventBus: Could not dispatch event: class com.model.EventBusMsg to subscribing class class com.anloq.activity.SettingActivity
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6096)
at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:824)

上面大致说的意思是EventBus再设置处理UI时只能在UI线程中,我使用的是 BACKGROUND

解决办法:1.改为 MAIN
2.处理UI时加上runOnUiThread即可;

阅读全文 »

需求:假设我们的APP有3个页面AActivity,BActivity,CActivity,我们的APP需要一直运行在前台(特殊设备),要求实现一个监控服务,来监视APP是否运行,如果有3个页面都不运行了就说明这个APP已经挂掉了,否则说明APP在运行状态,不做处理,挂掉之后,我们需要重新启动App来让它继续处理运行状态,对外暴露一个来停止监控服务的广播,这样我们想停止监控服务时,发送一个广播即可。

思路:实现一个双进程的监控服务,服务中写一个定时器 Timer 来重复进行检测是否正在运行,如果否就直接重新启动APP。

##1.定义一个监控服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package com.anloq.nfcservice;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.util.Log;

import com.anloq.MyApplication;
import com.anloq.activity.AdActivity;
import com.anloq.utils.DetectionASUtils;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Timer;
import java.util.TimerTask;

/**
* Created by xpf on 2017/6/3 :)
* 检测APP页面是否一直运行,不运行就直接启动
*/

public class MonitoringService extends Service {

private final static String TAG = "MonitoringService";

private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if ("kill_self".equals(intent.getAction())) {
Log.e(TAG, "onReceive:杀死自己的进程!");
killMyselfPid(); // 杀死自己的进程
}
}
};

private Timer timer = new Timer();
private TimerTask task = new TimerTask() {
@Override
public void run() {
checkIsAlive();
}
};

/**
* 检测应用是否活着
*/
private void checkIsAlive() {
String format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss",
Locale.CHINA).format(new Date());
Log.e(TAG, "CustodyService Run: " + format);

boolean AIsRunning = CheckUtil.isClsRunning(
MonitoringService.this, "com.xpf.monitor", "com.xpf.monitor.activity.AActivity");
boolean BIsRunning = CheckUtil.isClsRunning(
MonitoringService.this, "com.xpf.monitor", "com.xpf.monitor.activity.BActivity");
boolean b = (AIsRunning || BIsRunning);
boolean CIsRunning = CheckUtil.isClsRunning(
MonitoringService.this, "com.xpf.monitor", "com.xpf.monitor.activity.CActivity");

Log.e(TAG, "AIsRunning || BIsRunning is running:" + b + ",CIsRunning:" + CIsRunning);

if (!CIsRunning) {
if (!b) { //如果界面挂掉直接启动AActivity
Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setClass(MonitoringService.this, AActivity.class);
startActivity(intent);
}
}
}


@Override
public void onCreate() {
super.onCreate();
Log.e(TAG, "onCreate: 启动监控服务! ");
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("kill_self");
registerReceiver(broadcastReceiver, intentFilter);
timer.schedule(task, 0, 10000);// 设置检测的时间周期(毫秒数)
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}

@Override
public IBinder onBind(Intent arg0) {
return null;
}

/**
* 杀死自身的进程
*/
private void killMyselfPid() {
int pid = android.os.Process.myPid();
String command = "kill -9 " + pid;
Log.e(TAG, "killMyselfPid: " + command);
stopService(new Intent(MonitoringService.this, MonitoringService.class));
try {
Runtime.getRuntime().exec(command);
System.exit(0);
} catch (Exception e) {
e.printStackTrace();
}
}

@Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(broadcastReceiver);
if (task != null) {
task.cancel();
}
if (timer != null) {
timer.cancel();
}
}
}

##2.注册双进程Service

1
2
3
4
5
6
7
8
9
<service
android:name="com.xpf.monitor.MonitoringService"
android:enabled="true"
android:label="MonitoringService"
android:process=":gray">
<intent-filter>
<action android:name="android.intent.action.RESPOND_VIA_MESSAGE" />
</intent-filter>
</service>

##3.检测是否活着的工具类CheckUtil

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
public class CheckUtil {
//检测service是否在运行
public static boolean isServiceWorked(Context context, String serviceName) {
ActivityManager myManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
ArrayList<ActivityManager.RunningServiceInfo> runningService = (ArrayList<ActivityManager.RunningServiceInfo>) myManager.getRunningServices(Integer.MAX_VALUE);
for (int i = 0; i < runningService.size(); i++) {
if (runningService.get(i).service.getClassName().toString().equals(serviceName)) {
return true;
}
}
return false;
}

//检测activity是否存在再栈顶
public static boolean isForeground(Context context, String PackageName) {
ActivityManager myManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> task = myManager.getRunningTasks(1);
ComponentName componentInfo = task.get(0).topActivity;
if (componentInfo.getPackageName().equals(PackageName))
return true;
return false;
}

/**
* 判断某个app进程是否在运行
*
* @param context
* @param appInfo
* @return
*/
public static boolean isRunningProcess(Context context, String appInfo) {
ActivityManager myManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> runningAppPs = myManager.getRunningAppProcesses();
if (runningAppPs != null && runningAppPs.size() > 0) {
if (runningAppPs.contains(appInfo)) {
return true;
}
}
return false;
}

/**
* 判断一个Activity是否正在运行
*
* @param pkg pkg为应用包名
* @param cls cls为类名eg
* @param context
* @return
*/
public static boolean isClsRunning(Context context, String pkg, String cls) {
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(1);
ActivityManager.RunningTaskInfo task = tasks.get(0);
if (task != null) {
return TextUtils.equals(task.topActivity.getPackageName(), pkg) &&
TextUtils.equals(task.topActivity.getClassName(), cls);
}
return false;
}
}

##4.MainActivity中启动监控服务

1
2
3
Intent intent = new Intent(MainActivity.this, MonitoringService.class);
intent.setAction("android.intent.action.RESPOND_VIA_MESSAGE");
startService(intent);
阅读全文 »
0%