list) {
114 | this.list = list;
115 | }
116 |
117 | public String getNewApkMd5() {
118 | return newApkMd5;
119 | }
120 |
121 | public void setNewApkMd5(String newApkMd5) {
122 | this.newApkMd5 = newApkMd5;
123 | }
124 |
125 | public String getNewApkUrl() {
126 | return newApkUrl;
127 | }
128 |
129 | public void setNewApkUrl(String newApkUrl) {
130 | this.newApkUrl = newApkUrl;
131 | }
132 |
133 | public int getNewApkVersionCode() {
134 | return newApkVersionCode;
135 | }
136 |
137 | public void setNewApkVersionCode(int newApkVersionCode) {
138 | this.newApkVersionCode = newApkVersionCode;
139 | }
140 |
141 | public int getCurrentApkVersionCode() {
142 | return currentApkVersionCode;
143 | }
144 |
145 | public void setCurrentApkVersionCode(int currentApkVersionCode) {
146 | this.currentApkVersionCode = currentApkVersionCode;
147 | }
148 | }
149 |
150 |
--------------------------------------------------------------------------------
/uudownload/src/main/java/com/thjolin/download/task/DownloadCall.java:
--------------------------------------------------------------------------------
1 | package com.thjolin.download.task;
2 |
3 | import android.util.Log;
4 |
5 | import com.thjolin.download.constant.Status;
6 | import com.thjolin.download.database.DownloadEntity;
7 | import com.thjolin.download.database.download.DownloadDaoFatory;
8 | import com.thjolin.download.http.HttpUtil;
9 | import com.thjolin.download.util.Logl;
10 | import com.thjolin.download.util.NamedRunnable;
11 | import com.thjolin.download.util.Utils;
12 |
13 | import java.io.File;
14 | import java.io.InputStream;
15 | import java.io.RandomAccessFile;
16 | import java.util.Objects;
17 |
18 | import okhttp3.Response;
19 |
20 | /**
21 | * Created by th on 2021/5/27
22 | */
23 | public class DownloadCall extends NamedRunnable {
24 |
25 | private final static int RETRY_COUNT = 5;
26 | int retry = 0;
27 | DownloadEntity downloadEntity;
28 | DownloadTask task;
29 | int index;
30 | volatile boolean canceled;
31 | volatile boolean finishing;
32 |
33 | public DownloadCall(String name, DownloadTask task, int index) {
34 | super(name);
35 | this.task = task;
36 | this.downloadEntity = task.getInfoList().get(index);
37 | this.index = index;
38 | }
39 |
40 | @Override
41 | protected void execute() {
42 | Logl.e("DownloadCall: " + downloadEntity.getProgress());
43 | InputStream inputStream = null;
44 | RandomAccessFile randomAccessFile = null;
45 | if (downloadEntity.getProgress() == downloadEntity.getContentLength() || canceled || finishing) {
46 | return;
47 | }
48 | try {
49 | if (task.getBlockSize() == 1 && task.getBody() != null) {
50 | inputStream = task.getBody();
51 | } else {
52 | Response response = HttpUtil.with().syncResponse(task.getUrl(),
53 | downloadEntity.getStart() + downloadEntity.getProgress(),
54 | downloadEntity.getStart() + downloadEntity.getContentLength());
55 | inputStream = Objects.requireNonNull(response.body()).byteStream();
56 | }
57 | //保存文件的路径
58 | File file = new File(task.getFileParent(), task.getFileName());
59 | randomAccessFile = new RandomAccessFile(file, "rwd");
60 | //seek从哪里开始
61 | randomAccessFile.seek(downloadEntity.getStart() + downloadEntity.getProgress());
62 | int length;
63 | byte[] bytes = new byte[10 * 1024];
64 | while ((length = inputStream.read(bytes)) != -1) {
65 | if (canceled || finishing) {
66 | return;
67 | }
68 | randomAccessFile.write(bytes, 0, length);
69 | task.dealProgress(length);
70 | downloadEntity.addProgress(length);
71 | }
72 | finishing = true;
73 | Logl.e("写入完成: " + bytes.length);
74 | setFinished(true);
75 | Logl.e("isFinish(): " + isFinished());
76 | } catch (Exception e) {
77 | Logl.e("IOException: " + e.getMessage());
78 | if ("interrupted".equals(e.getMessage())) {
79 | return;
80 | }
81 | if (retry++ < RETRY_COUNT) {
82 | Utils.close(inputStream);
83 | Utils.close(randomAccessFile);
84 | execute();
85 | } else {
86 | task.cancel(Status.DOWNLOAD_ERROR);
87 | }
88 | } finally {
89 | Utils.close(inputStream);
90 | Utils.close(randomAccessFile);
91 | //保存到数据库
92 | saveToDb();
93 | Logl.e("isFinish(): " + isFinished());
94 | if (isFinished()) {
95 | task.dealFinishDownloadCall(index);
96 | }
97 | }
98 | }
99 |
100 | private void saveToDb() {
101 | Log.e("TAG", "**************保存到数据库*******************");
102 | DownloadEntity entity = new DownloadEntity();
103 | entity.setProgress(downloadEntity.getProgress());
104 | entity.setUrl(task.getUrl());
105 | entity.setStart(downloadEntity.getStart());
106 | entity.setContentLength(downloadEntity.getContentLength());
107 | entity.setThreadId(index);
108 | entity.setId(downloadEntity.getId());
109 | //保存到数据库
110 | Logl.e("saveToDb: " + entity);
111 | Logl.e("插入数据库:" + DownloadDaoFatory.getDao().insertOrUpdate(downloadEntity) + "");
112 | }
113 |
114 | public synchronized void cancel() {
115 | canceled = true;
116 | if (getmCurrentThread() != null) {
117 | getmCurrentThread().interrupt();
118 | } else {
119 | setFinished(true);
120 | }
121 | }
122 |
123 | @Override
124 | protected void interrupted(InterruptedException e) {
125 | Logl.e("InterruptedException: " + e.getMessage());
126 | }
127 | }
--------------------------------------------------------------------------------
/uudownload/src/main/java/com/thjolin/download/task/speed/SpeedAssist.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2017 LingoChamp Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.thjolin.download.task.speed;
18 |
19 | import android.os.SystemClock;
20 |
21 | import java.util.Locale;
22 |
23 | public class SpeedAssist {
24 |
25 | long timestamp;
26 | long increaseBytes;
27 |
28 | long bytesPerSecond;
29 |
30 | long beginTimestamp;
31 | long endTimestamp;
32 | long allIncreaseBytes;
33 |
34 | public synchronized void reset() {
35 | timestamp = 0;
36 | increaseBytes = 0;
37 | bytesPerSecond = 0;
38 |
39 | beginTimestamp = 0;
40 | endTimestamp = 0;
41 | allIncreaseBytes = 0;
42 | }
43 |
44 | long nowMillis() {
45 | return SystemClock.uptimeMillis();
46 | }
47 |
48 | public synchronized void uu_downloading(long increaseBytes) {
49 | if (timestamp == 0) {
50 | this.timestamp = nowMillis();
51 | this.beginTimestamp = timestamp;
52 | }
53 | this.increaseBytes += increaseBytes;
54 | this.allIncreaseBytes += increaseBytes;
55 | }
56 |
57 | public synchronized void flush() {
58 | final long nowMillis = nowMillis();
59 | final long sinceNowIncreaseBytes = increaseBytes;
60 | final long durationMillis = Math.max(1, nowMillis - timestamp);
61 |
62 | increaseBytes = 0;
63 | timestamp = nowMillis;
64 | bytesPerSecond = (long) ((float) sinceNowIncreaseBytes / durationMillis * 1000f);
65 | }
66 |
67 | /**
68 | * Get instant bytes per-second.
69 | */
70 | public long getInstantBytesPerSecondAndFlush() {
71 | flush();
72 | return bytesPerSecond;
73 | }
74 |
75 | public synchronized long getBytesPerSecondAndFlush() {
76 | final long interval = nowMillis() - timestamp;
77 | if (interval < 1000 && bytesPerSecond != 0) return bytesPerSecond;
78 | if (bytesPerSecond == 0 && interval < 500) return 0;
79 |
80 | return getInstantBytesPerSecondAndFlush();
81 | }
82 |
83 | public synchronized long getBytesPerSecondFromBegin() {
84 | final long endTimestamp = this.endTimestamp == 0 ? nowMillis() : this.endTimestamp;
85 | final long sinceNowIncreaseBytes = allIncreaseBytes;
86 | final long durationMillis = Math.max(1, endTimestamp - beginTimestamp);
87 |
88 | // precision loss
89 | return (long) ((float) sinceNowIncreaseBytes / durationMillis * 1000f);
90 | }
91 |
92 | public synchronized void endTask() {
93 | endTimestamp = nowMillis();
94 | }
95 |
96 | public String instantSpeed() {
97 | return getSpeedWithSIAndFlush();
98 | }
99 |
100 |
101 | public String speed() {
102 | return humanReadableSpeed(getBytesPerSecondAndFlush(), true);
103 | }
104 |
105 | public String lastSpeed() {
106 | return humanReadableSpeed(bytesPerSecond, true);
107 | }
108 |
109 | public synchronized long getInstantSpeedDurationMillis() {
110 | return nowMillis() - timestamp;
111 | }
112 |
113 | public String getSpeedWithBinaryAndFlush() {
114 | return humanReadableSpeed(getInstantBytesPerSecondAndFlush(), false);
115 | }
116 |
117 | /**
118 | * With wikipedia: https://en.wikipedia.org/wiki/Kilobyte
119 | *
120 | * 1KB = 1000B
121 | * 1MB = 1000KB
122 | */
123 | public String getSpeedWithSIAndFlush() {
124 | return humanReadableSpeed(getInstantBytesPerSecondAndFlush(), true);
125 | }
126 |
127 | public String averageSpeed() {
128 | return speedFromBegin();
129 | }
130 |
131 | public String speedFromBegin() {
132 | return humanReadableSpeed(getBytesPerSecondFromBegin(), true);
133 | }
134 |
135 | private static String humanReadableSpeed(long bytes, boolean si) {
136 | return humanReadableBytes(bytes, si) + "/s";
137 | }
138 |
139 | private static String humanReadableBytes(long bytes, boolean si) {
140 | int unit = si ? 1000 : 1024;
141 | if (bytes < unit) return bytes + " B";
142 | int exp = (int) (Math.log(bytes) / Math.log(unit));
143 | String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp - 1) + (si ? "" : "i");
144 | return String.format(Locale.ENGLISH, "%.1f %sB", bytes / Math.pow(unit, exp), pre);
145 | }
146 |
147 | }
148 |
--------------------------------------------------------------------------------
/library/src/main/cpp/bzip2/crctable.c:
--------------------------------------------------------------------------------
1 |
2 | /*-------------------------------------------------------------*/
3 | /*--- Table for doing CRCs ---*/
4 | /*--- crctable.c ---*/
5 | /*-------------------------------------------------------------*/
6 |
7 | /* ------------------------------------------------------------------
8 | This file is part of bzip2/libbzip2, a program and library for
9 | lossless, block-sorting data compression.
10 |
11 | bzip2/libbzip2 version 1.0.6 of 6 September 2010
12 | Copyright (C) 1996-2010 Julian Seward
13 |
14 | Please read the WARNING, DISCLAIMER and PATENTS sections in the
15 | README file.
16 |
17 | This program is released under the terms of the license contained
18 | in the file LICENSE.
19 | ------------------------------------------------------------------ */
20 |
21 |
22 | #include "bzlib_private.h"
23 |
24 | /*--
25 | I think this is an implementation of the AUTODIN-II,
26 | Ethernet & FDDI 32-bit CRC standard. Vaguely derived
27 | from code by Rob Warnock, in Section 51 of the
28 | comp.compression FAQ.
29 | --*/
30 |
31 | UInt32 BZ2_crc32Table[256] = {
32 |
33 | /*-- Ugly, innit? --*/
34 |
35 | 0x00000000L, 0x04c11db7L, 0x09823b6eL, 0x0d4326d9L,
36 | 0x130476dcL, 0x17c56b6bL, 0x1a864db2L, 0x1e475005L,
37 | 0x2608edb8L, 0x22c9f00fL, 0x2f8ad6d6L, 0x2b4bcb61L,
38 | 0x350c9b64L, 0x31cd86d3L, 0x3c8ea00aL, 0x384fbdbdL,
39 | 0x4c11db70L, 0x48d0c6c7L, 0x4593e01eL, 0x4152fda9L,
40 | 0x5f15adacL, 0x5bd4b01bL, 0x569796c2L, 0x52568b75L,
41 | 0x6a1936c8L, 0x6ed82b7fL, 0x639b0da6L, 0x675a1011L,
42 | 0x791d4014L, 0x7ddc5da3L, 0x709f7b7aL, 0x745e66cdL,
43 | 0x9823b6e0L, 0x9ce2ab57L, 0x91a18d8eL, 0x95609039L,
44 | 0x8b27c03cL, 0x8fe6dd8bL, 0x82a5fb52L, 0x8664e6e5L,
45 | 0xbe2b5b58L, 0xbaea46efL, 0xb7a96036L, 0xb3687d81L,
46 | 0xad2f2d84L, 0xa9ee3033L, 0xa4ad16eaL, 0xa06c0b5dL,
47 | 0xd4326d90L, 0xd0f37027L, 0xddb056feL, 0xd9714b49L,
48 | 0xc7361b4cL, 0xc3f706fbL, 0xceb42022L, 0xca753d95L,
49 | 0xf23a8028L, 0xf6fb9d9fL, 0xfbb8bb46L, 0xff79a6f1L,
50 | 0xe13ef6f4L, 0xe5ffeb43L, 0xe8bccd9aL, 0xec7dd02dL,
51 | 0x34867077L, 0x30476dc0L, 0x3d044b19L, 0x39c556aeL,
52 | 0x278206abL, 0x23431b1cL, 0x2e003dc5L, 0x2ac12072L,
53 | 0x128e9dcfL, 0x164f8078L, 0x1b0ca6a1L, 0x1fcdbb16L,
54 | 0x018aeb13L, 0x054bf6a4L, 0x0808d07dL, 0x0cc9cdcaL,
55 | 0x7897ab07L, 0x7c56b6b0L, 0x71159069L, 0x75d48ddeL,
56 | 0x6b93dddbL, 0x6f52c06cL, 0x6211e6b5L, 0x66d0fb02L,
57 | 0x5e9f46bfL, 0x5a5e5b08L, 0x571d7dd1L, 0x53dc6066L,
58 | 0x4d9b3063L, 0x495a2dd4L, 0x44190b0dL, 0x40d816baL,
59 | 0xaca5c697L, 0xa864db20L, 0xa527fdf9L, 0xa1e6e04eL,
60 | 0xbfa1b04bL, 0xbb60adfcL, 0xb6238b25L, 0xb2e29692L,
61 | 0x8aad2b2fL, 0x8e6c3698L, 0x832f1041L, 0x87ee0df6L,
62 | 0x99a95df3L, 0x9d684044L, 0x902b669dL, 0x94ea7b2aL,
63 | 0xe0b41de7L, 0xe4750050L, 0xe9362689L, 0xedf73b3eL,
64 | 0xf3b06b3bL, 0xf771768cL, 0xfa325055L, 0xfef34de2L,
65 | 0xc6bcf05fL, 0xc27dede8L, 0xcf3ecb31L, 0xcbffd686L,
66 | 0xd5b88683L, 0xd1799b34L, 0xdc3abdedL, 0xd8fba05aL,
67 | 0x690ce0eeL, 0x6dcdfd59L, 0x608edb80L, 0x644fc637L,
68 | 0x7a089632L, 0x7ec98b85L, 0x738aad5cL, 0x774bb0ebL,
69 | 0x4f040d56L, 0x4bc510e1L, 0x46863638L, 0x42472b8fL,
70 | 0x5c007b8aL, 0x58c1663dL, 0x558240e4L, 0x51435d53L,
71 | 0x251d3b9eL, 0x21dc2629L, 0x2c9f00f0L, 0x285e1d47L,
72 | 0x36194d42L, 0x32d850f5L, 0x3f9b762cL, 0x3b5a6b9bL,
73 | 0x0315d626L, 0x07d4cb91L, 0x0a97ed48L, 0x0e56f0ffL,
74 | 0x1011a0faL, 0x14d0bd4dL, 0x19939b94L, 0x1d528623L,
75 | 0xf12f560eL, 0xf5ee4bb9L, 0xf8ad6d60L, 0xfc6c70d7L,
76 | 0xe22b20d2L, 0xe6ea3d65L, 0xeba91bbcL, 0xef68060bL,
77 | 0xd727bbb6L, 0xd3e6a601L, 0xdea580d8L, 0xda649d6fL,
78 | 0xc423cd6aL, 0xc0e2d0ddL, 0xcda1f604L, 0xc960ebb3L,
79 | 0xbd3e8d7eL, 0xb9ff90c9L, 0xb4bcb610L, 0xb07daba7L,
80 | 0xae3afba2L, 0xaafbe615L, 0xa7b8c0ccL, 0xa379dd7bL,
81 | 0x9b3660c6L, 0x9ff77d71L, 0x92b45ba8L, 0x9675461fL,
82 | 0x8832161aL, 0x8cf30badL, 0x81b02d74L, 0x857130c3L,
83 | 0x5d8a9099L, 0x594b8d2eL, 0x5408abf7L, 0x50c9b640L,
84 | 0x4e8ee645L, 0x4a4ffbf2L, 0x470cdd2bL, 0x43cdc09cL,
85 | 0x7b827d21L, 0x7f436096L, 0x7200464fL, 0x76c15bf8L,
86 | 0x68860bfdL, 0x6c47164aL, 0x61043093L, 0x65c52d24L,
87 | 0x119b4be9L, 0x155a565eL, 0x18197087L, 0x1cd86d30L,
88 | 0x029f3d35L, 0x065e2082L, 0x0b1d065bL, 0x0fdc1becL,
89 | 0x3793a651L, 0x3352bbe6L, 0x3e119d3fL, 0x3ad08088L,
90 | 0x2497d08dL, 0x2056cd3aL, 0x2d15ebe3L, 0x29d4f654L,
91 | 0xc5a92679L, 0xc1683bceL, 0xcc2b1d17L, 0xc8ea00a0L,
92 | 0xd6ad50a5L, 0xd26c4d12L, 0xdf2f6bcbL, 0xdbee767cL,
93 | 0xe3a1cbc1L, 0xe760d676L, 0xea23f0afL, 0xeee2ed18L,
94 | 0xf0a5bd1dL, 0xf464a0aaL, 0xf9278673L, 0xfde69bc4L,
95 | 0x89b8fd09L, 0x8d79e0beL, 0x803ac667L, 0x84fbdbd0L,
96 | 0x9abc8bd5L, 0x9e7d9662L, 0x933eb0bbL, 0x97ffad0cL,
97 | 0xafb010b1L, 0xab710d06L, 0xa6322bdfL, 0xa2f33668L,
98 | 0xbcb4666dL, 0xb8757bdaL, 0xb5365d03L, 0xb1f740b4L
99 | };
100 |
101 |
102 | /*-------------------------------------------------------------*/
103 | /*--- end crctable.c ---*/
104 | /*-------------------------------------------------------------*/
105 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/progress_tang_update.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
13 |
14 |
20 |
21 |
31 |
32 |
36 |
37 |
46 |
47 |
59 |
60 |
68 |
69 |
76 |
77 |
84 |
85 |
86 |
87 |
98 |
99 |
104 |
105 |
109 |
110 |
120 |
121 |
126 |
127 |
137 |
138 |
139 |
140 |
141 |
145 |
--------------------------------------------------------------------------------
/uudownload/src/main/java/com/thjolin/download/permission/MyPermissionActivity.java:
--------------------------------------------------------------------------------
1 | package com.thjolin.download.permission;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.os.Build;
7 | import android.os.Bundle;
8 | import android.os.Environment;
9 | import android.provider.Settings;
10 |
11 | import androidx.annotation.NonNull;
12 | import androidx.annotation.Nullable;
13 | import androidx.core.app.ActivityCompat;
14 |
15 | import com.example.uudownload.R;
16 | import com.thjolin.download.permission.core.IPermission;
17 | import com.thjolin.download.permission.util.PermissionUtils;
18 | import com.thjolin.download.util.Logl;
19 |
20 |
21 | public class MyPermissionActivity extends Activity {
22 |
23 | // 定义权限处理的标记, ---- 接收用户传递进来的
24 | private final static String PARAM_PERMSSION = "param_permission";
25 | private final static String PARAM_PERMSSION_CODE = "param_permission_code";
26 | public final static int PARAM_PERMSSION_CODE_DEFAULT = -1;
27 |
28 | // 真正接收存储的变量
29 | private String[] permissions;
30 | private int requestCode;
31 | // 方便回调的监听 告诉外交 已授权,被拒绝,被取消
32 | private static IPermission iPermissionListener;
33 |
34 | @Override
35 | protected void onCreate(@Nullable Bundle savedInstanceState) {
36 | super.onCreate(savedInstanceState);
37 | setContentView(R.layout.activity_tang_permission); // 透明
38 |
39 | if (getIntent().getBooleanExtra("storageManager", false)) {
40 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
41 | if (!Environment.isExternalStorageManager()) {
42 | //跳转新页面申请权限
43 | startActivityForResult(new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION), 101);
44 | }
45 | }
46 | return;
47 | }
48 |
49 | // 我们就接收到了
50 | permissions = getIntent().getStringArrayExtra(PARAM_PERMSSION); // READ_EXTERNAL_STORAGE
51 | requestCode = getIntent().getIntExtra(PARAM_PERMSSION_CODE, PARAM_PERMSSION_CODE_DEFAULT);
52 |
53 | if (permissions == null && requestCode < 0 && iPermissionListener == null) {
54 | this.finish();
55 | return;
56 | }
57 |
58 | // 能够走到这里,就开始去检查,是否已经授权了
59 | boolean permissionRequest = PermissionUtils.hasPermissionRequest(this, permissions);
60 | if (permissionRequest) {
61 | // 通过监听接口,告诉外交,已经授权了
62 | iPermissionListener.ganted();
63 |
64 | this.finish();
65 | return;
66 | }
67 |
68 | // 能够走到这里,就证明,还需要去申请权限
69 | ActivityCompat.requestPermissions(this, permissions, requestCode);
70 | }
71 |
72 | // 申请的结果
73 | @Override
74 | public void onRequestPermissionsResult(int requestCode,
75 | @NonNull String[] permissions,
76 | @NonNull int[] grantResults) { // 如果申请三个权限 grantResults.len = 3
77 | super.onRequestPermissionsResult(requestCode, permissions, grantResults);
78 |
79 | // 返回的结果,需要去验证一下,是否完全成功
80 | if (PermissionUtils.requestPermissionSuccess(grantResults)) {
81 | iPermissionListener.ganted(); // 已经授权成功了
82 |
83 | this.finish();
84 | return;
85 | }
86 |
87 | // 没有成功,可能是用户 不听话
88 | // 如果用户点击了,拒绝(勾选了”不再提醒“) 等操作
89 | if (!PermissionUtils.shouldShowRequestPermissionRationale(this, permissions)) {
90 | // 用户拒绝,不再提醒
91 | iPermissionListener.denied();
92 |
93 | this.finish();
94 | return;
95 | }
96 |
97 | // 取消
98 | iPermissionListener.cancel();
99 | this.finish();
100 | return;
101 | }
102 |
103 | @Override
104 | protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
105 | super.onActivityResult(requestCode, resultCode, data);
106 | //申请权限结果
107 | if (requestCode == 101) {
108 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
109 | if (Environment.isExternalStorageManager()) {
110 | iPermissionListener.ganted();
111 | } else {
112 | iPermissionListener.denied();
113 | }
114 | }
115 | }
116 | }
117 |
118 | // 让此Activity不要有任何动画
119 | @Override
120 | public void finish() {
121 | super.finish();
122 | overridePendingTransition(0, 0);
123 | }
124 |
125 | public static void requestPermissionAction(Context context, String[] permissions,
126 | int requestCode, IPermission iPermissionListener) {
127 | Logl.e("PermissionActivity: requestPermissionAction");
128 | MyPermissionActivity.iPermissionListener = iPermissionListener;
129 | Intent intent = new Intent(context, MyPermissionActivity.class);
130 | // 效果
131 | intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
132 | Bundle bundle = new Bundle();
133 | bundle.putInt(PARAM_PERMSSION_CODE, requestCode);
134 | bundle.putStringArray(PARAM_PERMSSION, permissions);
135 |
136 | intent.putExtras(bundle);
137 | context.startActivity(intent);
138 | }
139 |
140 | // TODO 此权限申请专用的Activity ,对外暴露, static
141 | public static void requestStorageManagerPermission(Context context, IPermission iPermissionListener) {
142 | MyPermissionActivity.iPermissionListener = iPermissionListener;
143 | Intent intent = new Intent(context, MyPermissionActivity.class);
144 | // 效果
145 | intent.putExtra("storageManager", true);
146 | intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
147 | context.startActivity(intent);
148 | }
149 |
150 | }
151 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/library/src/main/cpp/bspatch.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 |
7 | #define errx err
8 | void err(int exitcode, const char * fmt, ...)
9 | {
10 | va_list valist;
11 | va_start(valist, fmt);
12 | vprintf(fmt, valist);
13 | va_end(valist);
14 | exit(exitcode);
15 | }
16 |
17 | static long offtin(u_char *buf)
18 | {
19 | long y;
20 |
21 | y = buf[7] & 0x7F;
22 | y = y * 256;y += buf[6];
23 | y = y * 256;y += buf[5];
24 | y = y * 256;y += buf[4];
25 | y = y * 256;y += buf[3];
26 | y = y * 256;y += buf[2];
27 | y = y * 256;y += buf[1];
28 | y = y * 256;y += buf[0];
29 |
30 | if (buf[7] & 0x80) y = -y;
31 |
32 | return y;
33 | }
34 |
35 | int executePatch(int argc, char * argv[])
36 | {
37 | FILE * f, *cpf, *dpf, *epf;
38 | BZFILE * cpfbz2, *dpfbz2, *epfbz2;
39 | int cbz2err, dbz2err, ebz2err;
40 | FILE * fs;
41 | long oldsize, newsize;
42 | long bzctrllen, bzdatalen;
43 | u_char header[32], buf[8];
44 | u_char *pold, *pnew;
45 | long oldpos, newpos;
46 | long ctrl[3];
47 | long lenread;
48 | long i;
49 |
50 | if (argc != 4) errx(1, "usage: %s oldfile newfile patchfile\n", argv[0]);
51 |
52 | /* Open patch file */
53 | if ((f = fopen(argv[3], "rb")) == NULL)
54 | err(1, "fopen(%s)", argv[3]);
55 |
56 | /*
57 | File format:
58 | 0 8 "BSDIFF40"
59 | 8 8 X
60 | 16 8 Y
61 | 24 8 sizeof(newfile)
62 | 32 X bzip2(control block)
63 | 32+X Y bzip2(diff block)
64 | 32+X+Y ??? bzip2(extra block)
65 | with control block a set of triples (x,y,z) meaning "add x bytes
66 | from oldfile to x bytes from the diff block; copy y bytes from the
67 | extra block; seek forwards in oldfile by z bytes".
68 | */
69 |
70 | /* Read header */
71 | if (fread(header, 1, 32, f) < 32) {
72 | if (feof(f))
73 | errx(1, "Corrupt patch\n");
74 | err(1, "fread(%s)", argv[3]);
75 | }
76 |
77 | /* Check for appropriate magic */
78 | if (memcmp(header, "BSDIFF40", 8) != 0)
79 | errx(1, "Corrupt patch\n");
80 |
81 | /* Read lengths from header */
82 | bzctrllen = offtin(header + 8);
83 | bzdatalen = offtin(header + 16);
84 | newsize = offtin(header + 24);
85 | if ((bzctrllen < 0) || (bzdatalen < 0) || (newsize < 0))
86 | errx(1, "Corrupt patch\n");
87 |
88 | /* Close patch file and re-open it via libbzip2 at the right places */
89 | if (fclose(f))
90 | err(1, "fclose(%s)", argv[3]);
91 | if ((cpf = fopen(argv[3], "rb")) == NULL)
92 | err(1, "fopen(%s)", argv[3]);
93 | if (fseek(cpf, 32, SEEK_SET))
94 | err(1, "fseeko(%s, %lld)", argv[3],
95 | (long long)32);
96 | if ((cpfbz2 = BZ2_bzReadOpen(&cbz2err, cpf, 0, 0, NULL, 0)) == NULL)
97 | errx(1, "BZ2_bzReadOpen, bz2err = %d", cbz2err);
98 | if ((dpf = fopen(argv[3], "rb")) == NULL)
99 | err(1, "fopen(%s)", argv[3]);
100 | if (fseek(dpf, 32 + bzctrllen, SEEK_SET))
101 | err(1, "fseeko(%s, %lld)", argv[3],
102 | (long long)(32 + bzctrllen));
103 | if ((dpfbz2 = BZ2_bzReadOpen(&dbz2err, dpf, 0, 0, NULL, 0)) == NULL)
104 | errx(1, "BZ2_bzReadOpen, bz2err = %d", dbz2err);
105 | if ((epf = fopen(argv[3], "rb")) == NULL)
106 | err(1, "fopen(%s)", argv[3]);
107 | if (fseek(epf, 32 + bzctrllen + bzdatalen, SEEK_SET))
108 | err(1, "fseeko(%s, %lld)", argv[3],
109 | (long long)(32 + bzctrllen + bzdatalen));
110 | if ((epfbz2 = BZ2_bzReadOpen(&ebz2err, epf, 0, 0, NULL, 0)) == NULL)
111 | errx(1, "BZ2_bzReadOpen, bz2err = %d", ebz2err);
112 |
113 | fs = fopen(argv[1], "rb");
114 | if (fs == NULL)err(1, "Open failed :%s", argv[1]);
115 | if (fseek(fs, 0, SEEK_END) != 0)err(1, "Seek failed :%s", argv[1]);
116 | oldsize = ftell(fs);
117 | pold = (u_char *)malloc(oldsize + 1);
118 | if (pold == NULL) err(1, "Malloc failed :%s", argv[1]);
119 | fseek(fs, 0, SEEK_SET);
120 | if (fread(pold, 1, oldsize, fs) == -1) err(1, "Read failed :%s", argv[1]);
121 | if (fclose(fs) == -1) err(1, "Close failed :%s", argv[1]);
122 |
123 | pnew = malloc(newsize + 1);
124 | if (pnew == NULL)err(1, NULL);
125 |
126 | oldpos = 0;newpos = 0;
127 | while (newpos < newsize) {
128 | /* Read control data */
129 | for (i = 0;i <= 2;i++) {
130 | lenread = BZ2_bzRead(&cbz2err, cpfbz2, buf, 8);
131 | if ((lenread < 8) || ((cbz2err != BZ_OK) &&
132 | (cbz2err != BZ_STREAM_END)))
133 | errx(1, "Corrupt patch\n");
134 | ctrl[i] = offtin(buf);
135 | };
136 |
137 | /* Sanity-check */
138 | if (newpos + ctrl[0] > newsize)
139 | errx(1, "Corrupt patch\n");
140 |
141 | /* Read diff string */
142 | lenread = BZ2_bzRead(&dbz2err, dpfbz2, pnew + newpos, ctrl[0]);
143 | if ((lenread < ctrl[0]) ||
144 | ((dbz2err != BZ_OK) && (dbz2err != BZ_STREAM_END)))
145 | errx(1, "Corrupt patch\n");
146 |
147 | /* Add pold data to diff string */
148 | for (i = 0;i < ctrl[0];i++)
149 | if ((oldpos + i >= 0) && (oldpos + i < oldsize))
150 | pnew[newpos + i] += pold[oldpos + i];
151 |
152 | /* Adjust pointers */
153 | newpos += ctrl[0];
154 | oldpos += ctrl[0];
155 |
156 | /* Sanity-check */
157 | if (newpos + ctrl[1] > newsize)
158 | errx(1, "Corrupt patch\n");
159 |
160 | /* Read extra string */
161 | lenread = BZ2_bzRead(&ebz2err, epfbz2, pnew + newpos, ctrl[1]);
162 | if ((lenread < ctrl[1]) ||
163 | ((ebz2err != BZ_OK) && (ebz2err != BZ_STREAM_END)))
164 | errx(1, "Corrupt patch\n");
165 |
166 | /* Adjust pointers */
167 | newpos += ctrl[1];
168 | oldpos += ctrl[2];
169 | };
170 |
171 | /* Clean up the bzip2 reads */
172 | BZ2_bzReadClose(&cbz2err, cpfbz2);
173 | BZ2_bzReadClose(&dbz2err, dpfbz2);
174 | BZ2_bzReadClose(&ebz2err, epfbz2);
175 | if (fclose(cpf) || fclose(dpf) || fclose(epf))
176 | err(1, "fclose(%s)", argv[3]);
177 |
178 | /* Write the pnew file */
179 | fs = fopen(argv[2], "wb");
180 | if (fs == NULL)err(1, "Create failed :%s", argv[2]);
181 | if (fwrite(pnew, 1, newsize, fs) == -1)err(1, "Write failed :%s", argv[2]);
182 | if (fclose(fs) == -1)err(1, "Close failed :%s", argv[2]);
183 |
184 | free(pnew);
185 | free(pold);
186 |
187 | return 0;
188 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/thjolin/ui/DefaultActivityController.java:
--------------------------------------------------------------------------------
1 | package com.thjolin.ui;
2 |
3 | import android.annotation.TargetApi;
4 | import android.app.Notification;
5 | import android.app.NotificationChannel;
6 | import android.app.NotificationManager;
7 | import android.content.Context;
8 | import android.os.Build;
9 | import android.widget.RemoteViews;
10 |
11 | import androidx.annotation.NonNull;
12 | import androidx.core.app.NotificationCompat;
13 |
14 | import com.thjolin.install.InstallApkActivity;
15 | import com.thjolin.install.InstallHelper;
16 | import com.thjolin.update.R;
17 | import com.thjolin.update.operate.listener.UiListener;
18 | import com.thjolin.download.util.Logl;
19 |
20 | import java.io.File;
21 |
22 | /**
23 | * Created by th on 2021/7/1
24 | */
25 | public class DefaultActivityController implements UiListener {
26 |
27 | PDialog.OnDialogClick onDialogClick;
28 |
29 | public final static String UPGRADE_CHANNEL = "com.thjolin.upgrade";
30 | public final static int UPGRADE_NOTIFICATION_ID = 0X9527;
31 | private NotificationChannel mChannel;
32 | private Notification notification;
33 | private NotificationManager nm;
34 | private boolean showNotification;
35 | private boolean needCompose;
36 | private InstallApkActivity activity;
37 | private InstallApkActivity.OnDialogClick onRightClick;
38 |
39 | static DefaultActivityController instance = new DefaultActivityController();
40 |
41 | private DefaultActivityController() {
42 | }
43 |
44 | public static DefaultActivityController getInstance() {
45 | return instance;
46 | }
47 |
48 | public void setActivity(InstallApkActivity activity) {
49 | this.activity = activity;
50 | if (activity != null) {
51 | activity.setOnDialogClick(onRightClick);
52 | }
53 | }
54 |
55 |
56 | @Override
57 | public void show(boolean showNotification, boolean forceUpdate, boolean needDownload, boolean needCompose, String apkPath, String fileName) {
58 | Logl.e("show========");
59 | InstallHelper.showDialogActivity(showNotification, forceUpdate, needDownload, needCompose, apkPath, fileName);
60 | }
61 |
62 | @Override
63 | public void showNotification() {
64 | if (activity == null) return;
65 | showNotification = true;
66 | showNotification(activity, "");
67 | }
68 |
69 | public void progress(int pro) {
70 | if (showNotification) {
71 | showNotificationProgress(pro);
72 | return;
73 | }
74 | if (activity == null) return;
75 | activity.progress(pro);
76 | }
77 |
78 | @Override
79 | public void downloadSuccess(String path) {
80 | if (activity != null && !activity.isFinishing()) {
81 | activity.setDownloadSuccess(path);
82 | InstallHelper.installApkWithIntent(activity, new File(path));
83 | } else {
84 | InstallHelper.installWithActivity(path);
85 | }
86 | }
87 |
88 | @Override
89 | public void failed(String msg) {
90 | if (activity == null) return;
91 | activity.setError(msg);
92 | }
93 |
94 | @Override
95 | public void setOnRightClick(InstallApkActivity.OnDialogClick onRightClick) {
96 | this.onRightClick = onRightClick;
97 | }
98 |
99 | public void setOnDialogClick(PDialog.OnDialogClick onDialogClick) {
100 | this.onDialogClick = onDialogClick;
101 | }
102 |
103 | /**
104 | * 显示通知栏
105 | *
106 | * @param context 上下文对象
107 | */
108 | public void showNotification(Context context, String title) {
109 | Logl.e("showNotification");
110 | if (activity == null) return;
111 | nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
112 | // 兼容 8.0 系统
113 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
114 | createNotificationChannel(context, nm);
115 | }
116 | NotificationCompat.Builder builder = createNotificationCompatBuilder(context, title);
117 | notification = builder.build();
118 | notification.contentView = new RemoteViews(activity.getApplicationContext()
119 | .getPackageName(), R.layout.custom_download_notification);
120 | showNotificationProgress(0);
121 | }
122 |
123 | public void showNotificationProgress(int progress) {
124 | Logl.e("通知下载进度:" + progress);
125 | notification.contentView.setProgressBar(R.id.progress_bar, 100 + (needCompose ? 10 : 0), progress, false);
126 | notification.contentView.setTextViewText(R.id.tv_progress, progress + "%");
127 | if (progress == 100) {
128 | if (needCompose) {
129 | notification.contentView.setTextViewText(R.id.tv_progress, "合成中");
130 | } else {
131 | nm.cancel(UPGRADE_NOTIFICATION_ID);
132 | }
133 | }
134 | if (progress == 110) {
135 | nm.cancel(UPGRADE_NOTIFICATION_ID);
136 | }
137 | nm.notify(UPGRADE_NOTIFICATION_ID, notification);
138 | Logl.e("处理通知完成:");
139 | }
140 |
141 | @NonNull
142 | private NotificationCompat.Builder createNotificationCompatBuilder(Context context, String title) {
143 | Logl.e("createNotificationCompatBuilder");
144 | NotificationCompat.Builder builder = new NotificationCompat.Builder(context, UPGRADE_CHANNEL);
145 | builder.setSmallIcon(R.drawable.tang_close);
146 | builder.setContentTitle(title);
147 | builder.setAutoCancel(true);
148 | builder.setDefaults(Notification.DEFAULT_ALL);
149 | return builder;
150 | }
151 |
152 | @TargetApi(Build.VERSION_CODES.O)
153 | private void createNotificationChannel(Context context, NotificationManager notificationManager) {
154 | // 通知渠道
155 | if (mChannel != null) {
156 | return;
157 | }
158 | mChannel = new NotificationChannel(UPGRADE_CHANNEL, activity.getString(R.string.uu_download_name), NotificationManager.IMPORTANCE_DEFAULT);
159 | // 开启指示灯,如果设备有的话。
160 | mChannel.enableLights(false);
161 | // 开启震动
162 | mChannel.enableVibration(false);
163 | mChannel.setSound(null, null);
164 | // 设置是否应在锁定屏幕上显示此频道的通知
165 | mChannel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
166 | // 设置是否显示角标
167 | mChannel.setShowBadge(false);
168 | // 设置绕过免打扰模式
169 | mChannel.setBypassDnd(false);
170 | //最后在notificationmanager中创建该通知渠道
171 | notificationManager.createNotificationChannel(mChannel);
172 | }
173 |
174 | }
--------------------------------------------------------------------------------
/uudownload/src/main/java/com/thjolin/download/dispatcher/TaskDispatcher.java:
--------------------------------------------------------------------------------
1 | package com.thjolin.download.dispatcher;
2 |
3 | import android.os.Handler;
4 | import android.os.Looper;
5 | import android.text.TextUtils;
6 |
7 | import com.thjolin.download.constant.Lifecycle;
8 | import com.thjolin.download.constant.Status;
9 | import com.thjolin.download.listener.DownloadListener;
10 | import com.thjolin.download.listener.MultiDownloadListener;
11 | import com.thjolin.download.task.DownloadTask;
12 | import com.thjolin.download.task.TaskCall;
13 | import com.thjolin.download.util.Logl;
14 |
15 | import java.util.ArrayList;
16 | import java.util.LinkedList;
17 | import java.util.List;
18 | import java.util.concurrent.ExecutorService;
19 | import java.util.concurrent.SynchronousQueue;
20 | import java.util.concurrent.ThreadPoolExecutor;
21 | import java.util.concurrent.TimeUnit;
22 |
23 | /**
24 | * Created by th on 2021/5/27
25 | */
26 | public class TaskDispatcher implements Lifecycle {
27 |
28 | private static final int RUNNING_SIZE = 3;
29 | private static volatile TaskDispatcher sDownloadDispatcher;
30 | private ExecutorService mExecutorService;
31 | private Handler mainHandler = new Handler(Looper.getMainLooper());
32 | private List taskList;
33 | private LinkedList runningTaskCall;
34 | private LinkedList waitTaskCall;
35 | private MultiDownloadListener multiDownloadListener;
36 |
37 | private TaskDispatcher() {
38 | init();
39 | }
40 |
41 | @Override
42 | public void init() {
43 | mExecutorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
44 | new SynchronousQueue<>(), r -> {
45 | Thread thread = new Thread(r);
46 | thread.setDaemon(false);
47 | return thread;
48 | });
49 | taskList = new ArrayList<>();
50 | }
51 |
52 | @Override
53 | public synchronized boolean prepare(DownloadTask task) {
54 | if (task == null) {
55 | return false;
56 | }
57 | if (TextUtils.isEmpty(task.getUrl())) {
58 | task.cancel(Status.CHECK_URL);
59 | return false;
60 | }
61 | if (taskExist(task.getUrl())) {
62 | return false;
63 | }
64 | return true;
65 | }
66 |
67 | @Override
68 | public synchronized void start(DownloadTask task, DownloadListener downloadListener) {
69 | task.setDownloadListener(downloadListener);
70 | if (!prepare(task)) {
71 | task.setStatus(Status.ERRO);
72 | task.getStatus().setMsg(Status.TASK_EXIST);
73 | task.dealFailedListener(Status.TASK_EXIST);
74 | return;
75 | }
76 | taskList.add(task);
77 | if (runningTaskCall == null) {
78 | runningTaskCall = new LinkedList<>();
79 | waitTaskCall = new LinkedList<>();
80 | }
81 | TaskCall taskCall = new TaskCall(task);
82 | if (runningTaskCall.size() < RUNNING_SIZE) {
83 | Logl.e("直接执行");
84 | runningTaskCall.add(taskCall);
85 | mExecutorService.submit(taskCall);
86 | } else {
87 | Logl.e("等待");
88 | waitTaskCall.add(taskCall);
89 | }
90 | }
91 |
92 | @Override
93 | public void destroy() {
94 | for (DownloadTask task : taskList) {
95 | task.cancel();
96 | }
97 | }
98 |
99 | public void setMultiDownloadListener(MultiDownloadListener multiDownloadListener) {
100 | this.multiDownloadListener = multiDownloadListener;
101 | }
102 |
103 | public synchronized void executeNextTaskCall() {
104 | Logl.e("executeNextTaskCall: " + waitTaskCall.size());
105 | if (waitTaskCall == null) return;
106 | TaskCall taskCall = waitTaskCall.poll();
107 | if (taskCall == null) {
108 | return;
109 | }
110 | runningTaskCall.add(taskCall);
111 | mExecutorService.submit(taskCall);
112 | Logl.e("executeNextTaskCall执行:" + taskCall.getTask().getUrl());
113 | }
114 |
115 | public ExecutorService getmExecutorService() {
116 | return mExecutorService;
117 | }
118 |
119 | public static TaskDispatcher getInstance() {
120 | if (sDownloadDispatcher == null) {
121 | synchronized (TaskDispatcher.class) {
122 | if (sDownloadDispatcher == null) {
123 | sDownloadDispatcher = new TaskDispatcher();
124 | }
125 | }
126 | }
127 | return sDownloadDispatcher;
128 | }
129 |
130 | public synchronized void removeTask(String url) {
131 | removeTask(url, false);
132 | }
133 |
134 | public synchronized void removeTask(String url, boolean success) {
135 | Logl.e("removeTask url " + url);
136 | for (int i = 0; i < taskList.size(); i++) {
137 | if (taskList.get(i).getUrl().equals(url)) {
138 | if (multiDownloadListener != null) {
139 | if (success) {
140 | multiDownloadListener.onSuccess(url, taskList.get(i).getFinalFilePath());
141 | } else {
142 | multiDownloadListener.onFailed(url);
143 | }
144 | if (taskList.size() == 1) {
145 | multiDownloadListener.onFinish();
146 | }
147 | }
148 | taskList.remove(i);
149 | Logl.e("taskList return " + taskList.toString());
150 | break;
151 | }
152 | }
153 | for (int i = 0; i < runningTaskCall.size(); i++) {
154 | if (runningTaskCall.get(i).getTask().getUrl().equals(url)) {
155 | runningTaskCall.remove(i);
156 | executeNextTaskCall();
157 | return;
158 | }
159 | }
160 | }
161 |
162 | public boolean taskExist(String url) {
163 | Logl.e("taskExist url " + url);
164 | Logl.e("taskList " + taskList.toString());
165 | if (taskList == null) return false;
166 | for (int i = 0; i < taskList.size(); i++) {
167 | if (taskList.get(i).getUrl().equals(url)) {
168 | return true;
169 | }
170 | }
171 | return false;
172 | }
173 |
174 | public void moveToMainThread(Runnable runnable) {
175 | mainHandler.post(runnable);
176 | }
177 |
178 | public void inspectRunningAndWait() {
179 | Logl.e("running: " + runningTaskCall.size());
180 | Logl.e("wait: " + waitTaskCall.size());
181 | for (TaskCall call : runningTaskCall) {
182 | Logl.e("Running: " + call.getTask().getUrl());
183 | }
184 | for (TaskCall call : waitTaskCall) {
185 | Logl.e("waitTaskCall: " + call.getTask().getUrl());
186 | }
187 | }
188 |
189 | }
--------------------------------------------------------------------------------
/library/src/main/cpp/bzip2/bzlib.h:
--------------------------------------------------------------------------------
1 |
2 | /*-------------------------------------------------------------*/
3 | /*--- Public header file for the library. ---*/
4 | /*--- bzlib.h ---*/
5 | /*-------------------------------------------------------------*/
6 |
7 | /* ------------------------------------------------------------------
8 | This file is part of bzip2/libbzip2, a program and library for
9 | lossless, block-sorting data compression.
10 |
11 | bzip2/libbzip2 version 1.0.6 of 6 September 2010
12 | Copyright (C) 1996-2010 Julian Seward
13 |
14 | Please read the WARNING, DISCLAIMER and PATENTS sections in the
15 | README file.
16 |
17 | This program is released under the terms of the license contained
18 | in the file LICENSE.
19 | ------------------------------------------------------------------ */
20 |
21 |
22 | #ifndef _BZLIB_H
23 | #define _BZLIB_H
24 |
25 | #ifdef __cplusplus
26 | extern "C" {
27 | #endif
28 |
29 | #define BZ_RUN 0
30 | #define BZ_FLUSH 1
31 | #define BZ_FINISH 2
32 |
33 | #define BZ_OK 0
34 | #define BZ_RUN_OK 1
35 | #define BZ_FLUSH_OK 2
36 | #define BZ_FINISH_OK 3
37 | #define BZ_STREAM_END 4
38 | #define BZ_SEQUENCE_ERROR (-1)
39 | #define BZ_PARAM_ERROR (-2)
40 | #define BZ_MEM_ERROR (-3)
41 | #define BZ_DATA_ERROR (-4)
42 | #define BZ_DATA_ERROR_MAGIC (-5)
43 | #define BZ_IO_ERROR (-6)
44 | #define BZ_UNEXPECTED_EOF (-7)
45 | #define BZ_OUTBUFF_FULL (-8)
46 | #define BZ_CONFIG_ERROR (-9)
47 |
48 | typedef
49 | struct {
50 | char *next_in;
51 | unsigned int avail_in;
52 | unsigned int total_in_lo32;
53 | unsigned int total_in_hi32;
54 |
55 | char *next_out;
56 | unsigned int avail_out;
57 | unsigned int total_out_lo32;
58 | unsigned int total_out_hi32;
59 |
60 | void *state;
61 |
62 | void *(*bzalloc)(void *,int,int);
63 | void (*bzfree)(void *,void *);
64 | void *opaque;
65 | }
66 | bz_stream;
67 |
68 |
69 | #ifndef BZ_IMPORT
70 | #define BZ_EXPORT
71 | #endif
72 |
73 | #ifndef BZ_NO_STDIO
74 | /* Need a definitition for FILE */
75 | #include
76 | #endif
77 |
78 | #ifdef _WIN32
79 | # include
80 | # ifdef small
81 | /* windows.h define small to char */
82 | # undef small
83 | # endif
84 | # ifdef BZ_EXPORT
85 | # define BZ_API(func) WINAPI func
86 | # define BZ_EXTERN extern
87 | # else
88 | /* import windows dll dynamically */
89 | # define BZ_API(func) (WINAPI * func)
90 | # define BZ_EXTERN
91 | # endif
92 | #else
93 | # define BZ_API(func) func
94 | # define BZ_EXTERN extern
95 | #endif
96 |
97 |
98 | /*-- Core (low-level) library functions --*/
99 |
100 | BZ_EXTERN int BZ_API(BZ2_bzCompressInit) (
101 | bz_stream* strm,
102 | int blockSize100k,
103 | int verbosity,
104 | int workFactor
105 | );
106 |
107 | BZ_EXTERN int BZ_API(BZ2_bzCompress) (
108 | bz_stream* strm,
109 | int action
110 | );
111 |
112 | BZ_EXTERN int BZ_API(BZ2_bzCompressEnd) (
113 | bz_stream* strm
114 | );
115 |
116 | BZ_EXTERN int BZ_API(BZ2_bzDecompressInit) (
117 | bz_stream *strm,
118 | int verbosity,
119 | int small
120 | );
121 |
122 | BZ_EXTERN int BZ_API(BZ2_bzDecompress) (
123 | bz_stream* strm
124 | );
125 |
126 | BZ_EXTERN int BZ_API(BZ2_bzDecompressEnd) (
127 | bz_stream *strm
128 | );
129 |
130 |
131 |
132 | /*-- High(er) level library functions --*/
133 |
134 | #ifndef BZ_NO_STDIO
135 | #define BZ_MAX_UNUSED 5000
136 |
137 | typedef void BZFILE;
138 |
139 | BZ_EXTERN BZFILE* BZ_API(BZ2_bzReadOpen) (
140 | int* bzerror,
141 | FILE* f,
142 | int verbosity,
143 | int small,
144 | void* unused,
145 | int nUnused
146 | );
147 |
148 | BZ_EXTERN void BZ_API(BZ2_bzReadClose) (
149 | int* bzerror,
150 | BZFILE* b
151 | );
152 |
153 | BZ_EXTERN void BZ_API(BZ2_bzReadGetUnused) (
154 | int* bzerror,
155 | BZFILE* b,
156 | void** unused,
157 | int* nUnused
158 | );
159 |
160 | BZ_EXTERN int BZ_API(BZ2_bzRead) (
161 | int* bzerror,
162 | BZFILE* b,
163 | void* buf,
164 | int len
165 | );
166 |
167 | BZ_EXTERN BZFILE* BZ_API(BZ2_bzWriteOpen) (
168 | int* bzerror,
169 | FILE* f,
170 | int blockSize100k,
171 | int verbosity,
172 | int workFactor
173 | );
174 |
175 | BZ_EXTERN void BZ_API(BZ2_bzWrite) (
176 | int* bzerror,
177 | BZFILE* b,
178 | void* buf,
179 | int len
180 | );
181 |
182 | BZ_EXTERN void BZ_API(BZ2_bzWriteClose) (
183 | int* bzerror,
184 | BZFILE* b,
185 | int abandon,
186 | unsigned int* nbytes_in,
187 | unsigned int* nbytes_out
188 | );
189 |
190 | BZ_EXTERN void BZ_API(BZ2_bzWriteClose64) (
191 | int* bzerror,
192 | BZFILE* b,
193 | int abandon,
194 | unsigned int* nbytes_in_lo32,
195 | unsigned int* nbytes_in_hi32,
196 | unsigned int* nbytes_out_lo32,
197 | unsigned int* nbytes_out_hi32
198 | );
199 | #endif
200 |
201 |
202 | /*-- Utility functions --*/
203 |
204 | BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffCompress) (
205 | char* dest,
206 | unsigned int* destLen,
207 | char* source,
208 | unsigned int sourceLen,
209 | int blockSize100k,
210 | int verbosity,
211 | int workFactor
212 | );
213 |
214 | BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffDecompress) (
215 | char* dest,
216 | unsigned int* destLen,
217 | char* source,
218 | unsigned int sourceLen,
219 | int small,
220 | int verbosity
221 | );
222 |
223 |
224 | /*--
225 | Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp)
226 | to support better zlib compatibility.
227 | This code is not _officially_ part of libbzip2 (yet);
228 | I haven't tested it, documented it, or considered the
229 | threading-safeness of it.
230 | If this code breaks, please contact both Yoshioka and me.
231 | --*/
232 |
233 | BZ_EXTERN const char * BZ_API(BZ2_bzlibVersion) (
234 | void
235 | );
236 |
237 | #ifndef BZ_NO_STDIO
238 | BZ_EXTERN BZFILE * BZ_API(BZ2_bzopen) (
239 | const char *path,
240 | const char *mode
241 | );
242 |
243 | BZ_EXTERN BZFILE * BZ_API(BZ2_bzdopen) (
244 | int fd,
245 | const char *mode
246 | );
247 |
248 | BZ_EXTERN int BZ_API(BZ2_bzread) (
249 | BZFILE* b,
250 | void* buf,
251 | int len
252 | );
253 |
254 | BZ_EXTERN int BZ_API(BZ2_bzwrite) (
255 | BZFILE* b,
256 | void* buf,
257 | int len
258 | );
259 |
260 | BZ_EXTERN int BZ_API(BZ2_bzflush) (
261 | BZFILE* b
262 | );
263 |
264 | BZ_EXTERN void BZ_API(BZ2_bzclose) (
265 | BZFILE* b
266 | );
267 |
268 | BZ_EXTERN const char * BZ_API(BZ2_bzerror) (
269 | BZFILE *b,
270 | int *errnum
271 | );
272 | #endif
273 |
274 | #ifdef __cplusplus
275 | }
276 | #endif
277 |
278 | #endif
279 |
280 | /*-------------------------------------------------------------*/
281 | /*--- end bzlib.h ---*/
282 | /*-------------------------------------------------------------*/
283 |
--------------------------------------------------------------------------------
/library/src/main/java/com/thjolin/update/configer/UpgraderConfiger.java:
--------------------------------------------------------------------------------
1 | package com.thjolin.update.configer;
2 |
3 | import androidx.annotation.IntDef;
4 | import androidx.annotation.NonNull;
5 |
6 | import com.thjolin.ui.DefaultActivityController;
7 | import com.thjolin.update.operate.listener.ForceExitListener;
8 | import com.thjolin.update.operate.listener.LifeCycleListener;
9 | import com.thjolin.update.operate.listener.SelfInstallListener;
10 | import com.thjolin.update.operate.listener.UiListener;
11 | import com.thjolin.download.util.Logl;
12 |
13 | import java.lang.annotation.Retention;
14 | import java.lang.annotation.RetentionPolicy;
15 |
16 | import okhttp3.OkHttpClient;
17 |
18 | /**
19 | * Created by th on 2021/6/11
20 | */
21 | public class UpgraderConfiger {
22 |
23 | public final static int PATCH_UPDATE = 1; // 增量更新
24 | public final static int COMPLETE_UPDATE = 2; // 完整apk更新
25 | public final static int MARKET_UPDATE = 3; // 跳转应用市场
26 | /**
27 | * 是否静默下载
28 | */
29 | public boolean silent;
30 | /**
31 | * 是否显示下载进度
32 | */
33 | public boolean showDownloadProgress;
34 | /**
35 | * 是否强制更新,可配合 ForceExitListener 使用
36 | */
37 | public boolean forceUpdate;
38 | /**
39 | * 是否显示通知栏
40 | */
41 | public boolean needNotification;
42 | /**
43 | * 更新生命周期回调
44 | */
45 | public LifeCycleListener lifeCycleListener;
46 | /**
47 | * 下载过程UI回调,可自定义UI。本框架也会默认UI,可作参考
48 | */
49 | public UiListener uiListener;
50 | /**
51 | * 强制更新,点击关闭时的回调
52 | */
53 | public ForceExitListener forceExitListener;
54 | /**
55 | * 透传到下载框架Uudownloader的okHttpClient
56 | */
57 | public OkHttpClient downloadOkHttpClient;
58 | /**
59 | * 关闭UI
60 | */
61 | public boolean closeUi;
62 | /**
63 | * 自主处理更新接口,适用已定制设备等,可自主采用厂商更新方式
64 | */
65 | public SelfInstallListener selfInstallListener;
66 | /**
67 | * 更新方式
68 | */
69 | public int updateMethod; // 0 for no value,-1 for no need update, 1、for patch,
70 | // 2 for completeApk, 3 for market, -2 for wrong type
71 |
72 | @IntDef({PATCH_UPDATE, COMPLETE_UPDATE, MARKET_UPDATE})
73 | @Retention(RetentionPolicy.SOURCE)
74 | public @interface UpdateMethod {
75 | }
76 |
77 |
78 | public static UpgraderConfiger createDefaultConfiger() {
79 | return new UpgraderConfiger(true, false, true, false,
80 | DefaultActivityController.getInstance(), false, 0
81 | , null, null, new LifeCycleListener() {
82 | @Override
83 | public boolean onCheck() {
84 | Logl.e("onCheck");
85 | return false;
86 | }
87 |
88 | @Override
89 | public void onStart() {
90 | Logl.e("onStart");
91 | }
92 |
93 | @Override
94 | public void onDownload() {
95 | Logl.e("onDownload");
96 | }
97 |
98 | @Override
99 | public void onDownloadProgress() {
100 | Logl.e("onDownloadProgress");
101 | }
102 |
103 | @Override
104 | public void onCompose() {
105 | Logl.e("onCompose");
106 | }
107 |
108 | @Override
109 | public void onInstall() {
110 | Logl.e("onInstall");
111 | }
112 |
113 | @Override
114 | public void onError() {
115 | Logl.e("onError");
116 | }
117 |
118 | @Override
119 | public void onFinish() {
120 | Logl.e("onFinish");
121 | }
122 | });
123 | }
124 |
125 | public UpgraderConfiger(boolean showDownloadProgress, boolean silent, boolean forceUpdate,
126 | boolean needNotification, UiListener uiListener,
127 | boolean closeUi, int updateMethod,
128 | ForceExitListener forceExitListener,
129 | SelfInstallListener selfInstallListener, LifeCycleListener lifeCycleListener
130 | ) {
131 | this.showDownloadProgress = showDownloadProgress;
132 | this.silent = silent;
133 | this.forceUpdate = forceUpdate;
134 | this.uiListener = uiListener;
135 | this.updateMethod = updateMethod;
136 | this.lifeCycleListener = lifeCycleListener;
137 | this.needNotification = needNotification;
138 | this.forceExitListener = forceExitListener;
139 | this.closeUi = closeUi;
140 | this.selfInstallListener = selfInstallListener;
141 | }
142 |
143 | public static class Builder {
144 | private boolean silent;
145 | private boolean showDownladProgress;
146 | private boolean forceUpdate;
147 | private boolean needNotifycation;
148 | private UiListener uiListener;
149 | private ForceExitListener forceExitListener;
150 | private OkHttpClient downloadOkHttpClient;
151 | private LifeCycleListener lifeCycleListener;
152 | private boolean closeUi;
153 | private SelfInstallListener selfInstallListener;
154 | private int updateMethod; // 0 for no need update, 1、for patch, 2 for completeApk,
155 | // 3 for marcket, 4 for 插件化更新, -1 for wrong type
156 |
157 | public Builder silent(boolean silent) {
158 | this.silent = silent;
159 | return this;
160 | }
161 |
162 | public Builder showDownladProgress(boolean showDownladProgress) {
163 | this.showDownladProgress = showDownladProgress;
164 | return this;
165 | }
166 |
167 | public Builder forceUpdate(boolean forceUpdate) {
168 | this.forceUpdate = forceUpdate;
169 | return this;
170 | }
171 |
172 | public Builder uiListener(@NonNull UiListener uiListener) {
173 | this.uiListener = uiListener;
174 | return this;
175 | }
176 |
177 | public Builder updateMethod(@UpdateMethod int updateMethod) {
178 | this.updateMethod = updateMethod;
179 | return this;
180 | }
181 |
182 | public Builder downloadOkHttpClient(OkHttpClient downloadOkHttpClient) {
183 | this.downloadOkHttpClient = downloadOkHttpClient;
184 | return this;
185 | }
186 |
187 | public Builder needNotifycation(boolean needNotifycation) {
188 | this.needNotifycation = needNotifycation;
189 | return this;
190 | }
191 |
192 | public Builder forceExitListener(ForceExitListener forceExitListener) {
193 | this.forceExitListener = forceExitListener;
194 | return this;
195 | }
196 |
197 | public Builder lifeCycleListener(LifeCycleListener lifeCycleListener) {
198 | this.lifeCycleListener = lifeCycleListener;
199 | return this;
200 | }
201 |
202 | public Builder closeUi(boolean closeUi) {
203 | this.closeUi = closeUi;
204 | return this;
205 | }
206 |
207 | public Builder selfInstallListener(SelfInstallListener selfInstallListener) {
208 | this.selfInstallListener = selfInstallListener;
209 | return this;
210 | }
211 |
212 | public UpgraderConfiger build() {
213 | return new UpgraderConfiger(showDownladProgress,
214 | silent, forceUpdate, needNotifycation, uiListener, closeUi,
215 | updateMethod, forceExitListener, selfInstallListener, lifeCycleListener);
216 | }
217 | }
218 | }
--------------------------------------------------------------------------------