Skip to content

Commit ffbbbf8

Browse files
committed
新增 Android 8.0 通知渠道开关适配
优化 Android 14 前台 Service 类型适配 优化 Logcat 在有悬浮窗权限的情况下的显示逻辑
1 parent dd34a59 commit ffbbbf8

File tree

14 files changed

+177
-48
lines changed

14 files changed

+177
-48
lines changed

HelpDoc.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
* [我如果要在线上使用这个库该怎么办](#我如果要在线上使用这个库该怎么办)
1616

17+
* [在多进程情况下无法展示入口怎么办](#在多进程情况下无法展示入口怎么办)
18+
1719
#### Logcat 入口配置
1820

1921
* 框架默认提供了两种入口
@@ -276,4 +278,51 @@ try {
276278
} catch (ClassNotFoundException e) {
277279
e.printStackTrace();
278280
}
281+
```
282+
283+
#### 在多进程情况下无法展示入口怎么办
284+
285+
* 这个问题其实之前就有人提出过 [Logcat/issues/35](https://github.com/getActivity/Logcat/issues/35),但是经过核实是无法修复的,这是因为在开启子进程的情况下,会二次创建 Application 对象,然后重新走一遍 onCreate 方法,但是 ContentProvider 组件就不一样了,并不会重复创建,这就导致一个问题,Logcat 这个框架本身就依赖 ContentProvider 作为框架的初始化入口,但是它在子进程并不会被系统二次创建,更别说调用了,这个属于硬伤。
286+
287+
* 当然不代表这就没有解决手段,你可以手动初始化 Logcat 框架来解决这一问题,具体方式如下:
288+
289+
* 第一步:先在清单文件中去除 Logcat 框架初始化入口
290+
291+
```xml
292+
<?xml version="1.0" encoding="utf-8"?>
293+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
294+
xmlns:tools="http://schemas.android.com/tools"
295+
package="com.xxx.xxx">
296+
297+
<application>
298+
299+
<provider
300+
android:name="com.hjq.logcat.LogcatProvider"
301+
tools:node="remove" />
302+
303+
</application>
304+
305+
</manifest>
306+
```
307+
308+
* 第二步:在 Application.onCreate 方法中手动初始化 Logcat 框架
309+
310+
```java
311+
public final class XxxApplication extends Application {
312+
313+
@Override
314+
public void onCreate() {
315+
super.onCreate();
316+
317+
try {
318+
Class<?> logcatProviderClass = Class.forName("com.hjq.logcat.LogcatProvider");
319+
Object logcatProvider = logcatProviderClass.newInstance();
320+
Method attachInfoMethod = logcatProviderClass.getMethod("attachInfo", Context.class, ProviderInfo.class);
321+
attachInfoMethod.setAccessible(true);
322+
attachInfoMethod.invoke(logcatProvider, this, null);
323+
} catch (Exception e) {
324+
e.printStackTrace();
325+
}
326+
}
327+
}
279328
```

README.md

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
* 项目地址:[Github](https://github.com/getActivity/Logcat)
66

7-
* 可以扫码下载 Demo 进行演示或者测试,如果扫码下载不了的,[点击此处可直接下载](https://github.com/getActivity/Logcat/releases/download/11.82/Logcat.apk)
7+
* 可以扫码下载 Demo 进行演示或者测试,如果扫码下载不了的,[点击此处可直接下载](https://github.com/getActivity/Logcat/releases/download/11.85/Logcat.apk)
88

99
![](picture/demo_code.png)
1010

@@ -51,7 +51,7 @@ dependencyResolutionManagement {
5151
```groovy
5252
dependencies {
5353
// 日志调试框架:https://github.com/getActivity/Logcat
54-
debugImplementation 'com.github.getActivity:Logcat:11.82'
54+
debugImplementation 'com.github.getActivity:Logcat:11.85'
5555
}
5656
```
5757

@@ -66,18 +66,6 @@ android.enableJetifier = true
6666

6767
* 如果项目是基于 **Support** 包则不需要加入此配置
6868

69-
#### compileSdk 版本要求
70-
71-
* 如果项目的 `compileSdkVersion` 小于 29,则需要先升级成 29
72-
73-
```groovy
74-
android {
75-
compileSdkVersion 29
76-
}
77-
```
78-
79-
* 如果项目的 `compileSdkVersion` 大于等于 29,则不需要修改此配置
80-
8169
#### 使用方式
8270

8371
* 无需调用,直接运行,然后授予悬浮窗权限即可
@@ -158,18 +146,6 @@ android {
158146

159147
![](https://raw.githubusercontent.com/getActivity/Donate/master/picture/pay_ali.png) ![](https://raw.githubusercontent.com/getActivity/Donate/master/picture/pay_wechat.png)
160148

161-
#### 广告区
162-
163-
* 我现在任腾讯云服务器推广大使,大家如果有购买服务器的需求,可以通过下面的链接购买
164-
165-
[![](https://upload-dianshi-1255598498.file.myqcloud.com/upload/nodir/345X200-9ae456f58874df499adf7c331c02cb0fed12b81d.jpg)](https://curl.qcloud.com/A6cYskvv)
166-
167-
[【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中](https://curl.qcloud.com/A6cYskvv)
168-
169-
[![](https://upload-dianshi-1255598498.file.myqcloud.com/345-200-b28f7dee9552f4241ea6a543f15a9798049701d4.jpg)](https://curl.qcloud.com/up4fQsdn)
170-
171-
[【腾讯云】中小企业福利专场,多款刚需产品,满足企业通用场景需求](https://curl.qcloud.com/up4fQsdn)
172-
173149
## License
174150

175151
```text

app/src/main/AndroidManifest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
xmlns:tools="http://schemas.android.com/tools"
44
package="com.hjq.logcat.demo">
55

6+
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
67
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
78
<uses-permission android:name="android.permission.INTERNET" />
89

common.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ android {
88
minSdk 16
99
// Android 版本适配指南:https://github.com/getActivity/AndroidVersionAdapter
1010
targetSdk 34
11-
versionCode 1182
12-
versionName "11.82"
11+
versionCode 1185
12+
versionName "11.85"
1313
}
1414

1515
// 支持 Java JDK 8

library/src/main/AndroidManifest.xml

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,7 @@
3131
android:theme="@style/Theme.AppCompat.Light.NoActionBar"
3232
android:windowSoftInputMode="stateHidden" />
3333

34-
<!-- 适配 targetSdk 34:https://developer.android.google.cn/about/versions/14/changes/fgs-types-required?hl=zh-cn -->
35-
<!-- java.lang.RuntimeException:
36-
Unable to start service com.hjq.logcat.LogcatService with Intent:
37-
android.app.MissingForegroundServiceTypeException:
38-
Starting FGS without a type callerApp=ProcessRecord targetSDK=34 -->
39-
<!-- 加上 foregroundServiceType 属性后,compileSdkVersion 需要 29 及以上的版本才能编译通过 -->
40-
<service android:name=".LogcatService" android:foregroundServiceType="dataSync" />
34+
<service android:name=".LogcatService" />
4135

4236
</application>
4337

library/src/main/java/com/hjq/logcat/LogcatActivity.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ public final class LogcatActivity extends AppCompatActivity
4444
CompoundButton.OnCheckedChangeListener, LogcatManager.Callback,
4545
LogcatAdapter.OnItemLongClickListener, LogcatAdapter.OnItemClickListener {
4646

47-
private final static String[] ARRAY_LOG_LEVEL = {"Verbose", "Debug", "Info", "Warn", "Error"};
48-
private final static String[] ARRAY_LOG_LEVEL_PORTRAIT = {"V", "D", "I", "W", "E"};
47+
private static final String[] ARRAY_LOG_LEVEL = {"Verbose", "Debug", "Info", "Warn", "Error"};
48+
private static final String[] ARRAY_LOG_LEVEL_PORTRAIT = {"V", "D", "I", "W", "E"};
4949

5050
private View mRootView;
5151
private View mBarView;
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package com.hjq.logcat;
2+
3+
import android.app.Activity;
4+
import android.app.Application;
5+
import android.os.Bundle;
6+
import android.view.View;
7+
8+
/**
9+
* author : Android 轮子哥
10+
* github : https://github.com/getActivity/Logcat
11+
* time : 2020/01/24
12+
* desc : Logcat 悬浮窗全局显示派发
13+
*/
14+
final class LogcatGlobalDispatcher implements Application.ActivityLifecycleCallbacks {
15+
16+
static void launch(Application application) {
17+
LogcatWindow logcatWindow = new LogcatWindow(application);
18+
logcatWindow.show();
19+
20+
application.registerActivityLifecycleCallbacks(new LogcatGlobalDispatcher(logcatWindow));
21+
}
22+
23+
private final LogcatWindow mLogcatWindow;
24+
25+
private LogcatGlobalDispatcher(LogcatWindow logcatWindow) {
26+
mLogcatWindow = logcatWindow;
27+
}
28+
29+
@Override
30+
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {}
31+
32+
@Override
33+
public void onActivityStarted(Activity activity) {}
34+
35+
@Override
36+
public void onActivityResumed(Activity activity) {
37+
if (!(activity instanceof LogcatActivity)) {
38+
return;
39+
}
40+
mLogcatWindow.setWindowVisibility(View.GONE);
41+
}
42+
43+
@Override
44+
public void onActivityPaused(Activity activity) {}
45+
46+
@Override
47+
public void onActivityStopped(Activity activity) {
48+
if (!(activity instanceof LogcatActivity)) {
49+
return;
50+
}
51+
mLogcatWindow.setWindowVisibility(View.VISIBLE);
52+
}
53+
54+
@Override
55+
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {}
56+
57+
@Override
58+
public void onActivityDestroyed(Activity activity) {}
59+
}

library/src/main/java/com/hjq/logcat/LogcatDispatcher.java renamed to library/src/main/java/com/hjq/logcat/LogcatLocalDispatcher.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@
99
* author : Android 轮子哥
1010
* github : https://github.com/getActivity/Logcat
1111
* time : 2020/01/24
12-
* desc : Logcat 悬浮窗显示派发
12+
* desc : Logcat 悬浮窗局部显示派发
1313
*/
14-
final class LogcatDispatcher implements Application.ActivityLifecycleCallbacks {
14+
final class LogcatLocalDispatcher implements Application.ActivityLifecycleCallbacks {
1515

16-
static void with(Application application) {
17-
application.registerActivityLifecycleCallbacks(new LogcatDispatcher());
16+
static void launch(Application application) {
17+
application.registerActivityLifecycleCallbacks(new LogcatLocalDispatcher());
1818
}
1919

2020
@Override

library/src/main/java/com/hjq/logcat/LogcatProvider.java

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
package com.hjq.logcat;
22

33
import android.app.Application;
4+
import android.app.NotificationChannel;
5+
import android.app.NotificationManager;
46
import android.content.ContentProvider;
57
import android.content.ContentValues;
68
import android.content.Context;
79
import android.database.Cursor;
810
import android.net.Uri;
11+
import android.os.Build;
12+
import android.os.Build.VERSION;
13+
import android.os.Build.VERSION_CODES;
14+
import android.provider.Settings;
915
import android.support.v4.app.NotificationManagerCompat;
1016
import android.widget.Toast;
1117

@@ -29,7 +35,7 @@ public boolean onCreate() {
2935
Boolean windowEntrance = LogcatUtils.getMetaBooleanData(
3036
context, LogcatContract.META_DATA_LOGCAT_WINDOW_ENTRANCE);
3137
if (notifyEntrance == null && windowEntrance == null) {
32-
if (NotificationManagerCompat.from(context).areNotificationsEnabled()) {
38+
if (isNotificationChannelEnabled(context)) {
3339
notifyEntrance = true;
3440
} else {
3541
windowEntrance = true;
@@ -44,7 +50,11 @@ public boolean onCreate() {
4450

4551
if (windowEntrance != null && windowEntrance) {
4652
if (context instanceof Application) {
47-
LogcatDispatcher.with((Application) context);
53+
if (VERSION.SDK_INT >= VERSION_CODES.M && Settings.canDrawOverlays(context)) {
54+
LogcatGlobalDispatcher.launch((Application) context);
55+
} else {
56+
LogcatLocalDispatcher.launch((Application) context);
57+
}
4858
} else {
4959
Toast.makeText(context, R.string.logcat_launch_error, Toast.LENGTH_LONG).show();
5060
}
@@ -77,4 +87,22 @@ public int delete(Uri uri, String selection, String[] selectionArgs) {
7787
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
7888
return 0;
7989
}
90+
91+
private boolean isNotificationChannelEnabled(Context context) {
92+
if (!NotificationManagerCompat.from(context).areNotificationsEnabled()) {
93+
return false;
94+
}
95+
96+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
97+
return true;
98+
}
99+
100+
NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
101+
NotificationChannel channel = manager.getNotificationChannel(LogcatService.NOTIFICATION_CHANNEL_ID);
102+
if (channel == null) {
103+
return true;
104+
}
105+
106+
return channel.getImportance() != NotificationManager.IMPORTANCE_NONE;
107+
}
80108
}

library/src/main/java/com/hjq/logcat/LogcatService.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
*/
2525
public final class LogcatService extends Service {
2626

27+
public static final String NOTIFICATION_CHANNEL_ID = "logcat";
28+
2729
private static final int BACKUP_SERVICE_NOTIFICATION_ID = Integer.MAX_VALUE >> 2;
2830

2931
@Override
@@ -65,7 +67,7 @@ public int onStartCommand(Intent intent, int flags, int startId) {
6567
// 设置通知渠道
6668
if (VERSION.SDK_INT >= VERSION_CODES.O) {
6769
// 通知渠道的id
68-
String notificationChannelId = "logcat";
70+
String notificationChannelId = NOTIFICATION_CHANNEL_ID;
6971
NotificationChannel channel = new NotificationChannel(notificationChannelId,
7072
getString(R.string.logcat_notify_channel_name), NotificationManager.IMPORTANCE_MIN);
7173
// 配置通知渠道的属性

0 commit comments

Comments
 (0)