1
+ /*
2
+ * Licensed to the Apache Software Foundation (ASF) under one
3
+ * or more contributor license agreements. See the NOTICE file
4
+ * distributed with this work for additional information
5
+ * regarding copyright ownership. The ASF licenses this file
6
+ * to you under the Apache License, Version 2.0 (the
7
+ * "License"); you may not use this file except in compliance
8
+ * with the License. You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing,
13
+ * software distributed under the License is distributed on an
14
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ * KIND, either express or implied. See the License for the
16
+ * specific language governing permissions and limitations
17
+ * under the License.
18
+ */
19
+
20
+ package com .bald .uriah .baldphone .activities ;
21
+
22
+ import android .app .DownloadManager ;
23
+ import android .content .*;
24
+ import android .database .Cursor ;
25
+ import android .media .MediaScannerConnection ;
26
+ import android .net .ConnectivityManager ;
27
+ import android .net .NetworkInfo ;
28
+ import android .net .Uri ;
29
+ import android .os .Build ;
30
+ import android .os .Bundle ;
31
+ import android .os .Environment ;
32
+ import android .os .Handler ;
33
+ import android .view .View ;
34
+ import android .widget .ProgressBar ;
35
+ import android .widget .TextView ;
36
+ import androidx .annotation .Nullable ;
37
+ import com .bald .uriah .baldphone .BuildConfig ;
38
+ import com .bald .uriah .baldphone .R ;
39
+ import com .bald .uriah .baldphone .utils .*;
40
+
41
+ import java .io .File ;
42
+
43
+ import static com .bald .uriah .baldphone .utils .UpdatingUtil .*;
44
+
45
+ public class UpdatesActivity extends BaldActivity {
46
+ public static final String EXTRA_BALD_UPDATE_OBJECT = "EXTRA_BALD_UPDATE_OBJECT" ;
47
+ private static final int PROGRESS_DELAY = 200 * D .MILLISECOND ;
48
+ private BaldUpdateObject baldUpdateObject ;
49
+ private DownloadManager manager ;
50
+ private long downloadId = -1 ;
51
+ private Handler handler = new Handler ();
52
+ private boolean isProgressCheckerRunning = false ;
53
+ private BaldToast notConnectedToast , couldNotStartDownloadToast , downloadFinishedToast , downloadingToast , downloadedFileCouldNotBeDeletedToast , tryNowToast , pleaseBePateint ;
54
+ private TextView tv_new_version , tv_current_version , tv_change_log , bt , tv_download_progress , bt_re ;
55
+ private ProgressBar pb ;
56
+ private final Runnable progressChecker = new Runnable () {
57
+ @ Override
58
+ public void run () {
59
+ try {
60
+ checkProgress ();
61
+ } finally {
62
+ handler .postDelayed (progressChecker , PROGRESS_DELAY );
63
+ }
64
+ }
65
+ };
66
+ private BroadcastReceiver downloadFinishedReceiver = new BroadcastReceiver () {
67
+ @ Override
68
+ public void onReceive (Context context , Intent intent ) {
69
+ if (downloadId == intent .getLongExtra (DownloadManager .EXTRA_DOWNLOAD_ID , -2 )) {
70
+ handler .postDelayed (() -> {
71
+ downloadFinishedToast .show ();
72
+ stopProgressChecker ();
73
+ apply ();
74
+ }, 50 * D .MILLISECOND );
75
+ }
76
+ }
77
+ };
78
+
79
+ public static void removeUpdatesInfo (Context context ) {
80
+ BPrefs .get (context )
81
+ .edit ()
82
+ .remove (BPrefs .LAST_APK_VERSION_KEY )
83
+ .remove (BPrefs .LAST_DOWNLOAD_MANAGER_REQUEST_VERSION_NUMBER )
84
+ .remove (BPrefs .LAST_UPDATE_ASKED_VERSION_KEY )
85
+ .remove (BPrefs .LAST_DOWNLOAD_MANAGER_REQUEST_ID )
86
+ .apply ();
87
+ }
88
+
89
+ @ Override
90
+ protected void onCreate (@ Nullable Bundle savedInstanceState ) {
91
+ super .onCreate (savedInstanceState );
92
+ setContentView (R .layout .activity_update );
93
+ if (!checkPermissions (this , requiredPermissions ()))
94
+ return ;
95
+ baldUpdateObject = getIntent ().getParcelableExtra (EXTRA_BALD_UPDATE_OBJECT );
96
+ if (baldUpdateObject == null ) {
97
+ BaldToast .error (this );
98
+ finish ();
99
+ return ;
100
+ }
101
+
102
+ manager = (DownloadManager ) this .getSystemService (Context .DOWNLOAD_SERVICE );
103
+ tv_new_version = findViewById (R .id .tv_new_version );
104
+ tv_current_version = findViewById (R .id .tv_current_version );
105
+ tv_change_log = findViewById (R .id .tv_change_log );
106
+ tv_download_progress = findViewById (R .id .tv_download_progress );
107
+ bt_re = findViewById (R .id .bt_re );
108
+ pb = findViewById (R .id .pb );
109
+ bt = findViewById (R .id .bt );
110
+
111
+ notConnectedToast = BaldToast .from (this ).setType (BaldToast .TYPE_ERROR ).setText (R .string .could_not_connect_to_internet );
112
+ couldNotStartDownloadToast = BaldToast .from (this ).setType (BaldToast .TYPE_ERROR ).setText (R .string .could_not_start_the_download );
113
+ downloadFinishedToast = BaldToast .from (UpdatesActivity .this ).setText (R .string .download_finished ).setLength (1 );
114
+ downloadingToast = BaldToast .from (this ).setText (R .string .downloading );
115
+ downloadedFileCouldNotBeDeletedToast = BaldToast .from (this ).setType (BaldToast .TYPE_ERROR ).setText (R .string .downloaded_update_file_could_not_be_deleted );
116
+ tryNowToast = BaldToast .from (this ).setLength (1 ).setText (R .string .try_now ).setBig (true );
117
+
118
+ this .registerReceiver (downloadFinishedReceiver , new IntentFilter (DownloadManager .ACTION_DOWNLOAD_COMPLETE ));
119
+ }
120
+
121
+ @ Override
122
+ protected void onStart () {
123
+ super .onStart ();
124
+ apply ();
125
+ }
126
+
127
+ @ Override
128
+ protected void onDestroy () {
129
+ try {
130
+ unregisterReceiver (downloadFinishedReceiver );
131
+ } catch (Exception ignore ) {
132
+ }
133
+ stopProgressChecker ();
134
+ super .onDestroy ();
135
+ }
136
+
137
+ public void apply () {
138
+ if (isDestroyed ())
139
+ return ;
140
+ tv_new_version .setText (String .format ("%s%s" , getString (R .string .new_version ), baldUpdateObject .versionName ));
141
+ tv_current_version .setText (String .format ("%s%s" , getString (R .string .current_version ), BuildConfig .VERSION_NAME ));
142
+ tv_change_log .setText (baldUpdateObject .changeLog );
143
+ final SharedPreferences sharedPreferences = BPrefs .get (this );
144
+ final int downloadedVersion = BPrefs .get (this ).getInt (BPrefs .LAST_APK_VERSION_KEY , -1 );
145
+ final int newVersion = baldUpdateObject .versionCode ;
146
+ final boolean downloading = sharedPreferences .contains (BPrefs .LAST_DOWNLOAD_MANAGER_REQUEST_ID ) && sharedPreferences .contains (BPrefs .LAST_DOWNLOAD_MANAGER_REQUEST_VERSION_NUMBER );
147
+ final boolean downloaded = downloadedVersion == newVersion && getDownloadedFile ().exists ();
148
+ assert true ;
149
+ if (downloaded ) {
150
+ pb .setVisibility (View .GONE );
151
+ tv_download_progress .setVisibility (View .GONE );
152
+ bt_re .setVisibility (View .VISIBLE );
153
+ bt_re .setOnClickListener (v -> {
154
+ removeUpdatesInfo (this );
155
+ tryNowToast .show ();
156
+ bt_re .setVisibility (View .GONE );
157
+ bt_re .setOnClickListener (null );
158
+ apply ();
159
+ });
160
+ bt .setOnClickListener (v -> {
161
+ install ();
162
+ });
163
+ bt .setText (R .string .install );
164
+ } else if (downloading ) {
165
+ bt .setText (R .string .downloading );
166
+ bt .setOnClickListener (D .EMPTY_CLICK_LISTENER );
167
+ pb .setVisibility (View .VISIBLE );
168
+ tv_download_progress .setVisibility (View .VISIBLE );
169
+ startProgressChecker ();
170
+ } else {
171
+ pb .setVisibility (View .GONE );
172
+ tv_download_progress .setVisibility (View .GONE );
173
+ bt .setText (R .string .download );
174
+ bt .setOnClickListener (v -> {
175
+ final ConnectivityManager connectivityManager = (ConnectivityManager ) getSystemService (CONNECTIVITY_SERVICE );
176
+ if (connectivityManager != null ) {
177
+ final NetworkInfo networkInfo = connectivityManager .getNetworkInfo (ConnectivityManager .TYPE_WIFI );
178
+ if (networkInfo != null ) {
179
+ if (networkInfo .isConnected ()) {
180
+ onDownloadButtonClick (newVersion );
181
+ } else {
182
+ BDB .from (this )
183
+ .setTitle (R .string .data_warning )
184
+ .setSubText (R .string .data_warning_subtext )
185
+ .addFlag (BDialog .FLAG_YES | BDialog .FLAG_CANCEL )
186
+ .setPositiveButtonListener (params -> {
187
+ onDownloadButtonClick (newVersion );
188
+ return true ;
189
+ })
190
+ .show ();
191
+ }
192
+ } else {
193
+ notConnectedToast .show ();
194
+ }
195
+ } else {
196
+ notConnectedToast .show ();
197
+ }
198
+ });
199
+ }
200
+ }
201
+
202
+ private void onDownloadButtonClick (final int newVersion ) {
203
+ if (downloadApk (newVersion )) {
204
+ apply ();
205
+ } else {
206
+ couldNotStartDownloadToast .show ();
207
+ }
208
+ }
209
+
210
+ /**
211
+ * @param versionNumber version number
212
+ * @return true if download was started;
213
+ */
214
+ public boolean downloadApk (final int versionNumber ) {
215
+ if (manager == null )
216
+ return false ;
217
+
218
+ downloadingToast .show ();
219
+ deleteCurrentUpdateFile ();
220
+
221
+ final Uri uri =
222
+ Uri .parse (baldUpdateObject .apkUrl );
223
+ final DownloadManager .Request request =
224
+ new DownloadManager .Request (uri )
225
+ .setDestinationInExternalPublicDir (Environment .DIRECTORY_DOWNLOADS , FILENAME )
226
+ .setAllowedOverRoaming (true )
227
+ .setAllowedOverMetered (true )
228
+ .setDescription (getText (R .string .downloading_updates ));
229
+
230
+ downloadId = manager .enqueue (request );
231
+
232
+ BPrefs .get (this ).edit ().putLong (BPrefs .LAST_DOWNLOAD_MANAGER_REQUEST_ID , downloadId ).apply ();
233
+ BPrefs .get (this ).edit ().putInt (BPrefs .LAST_DOWNLOAD_MANAGER_REQUEST_VERSION_NUMBER , versionNumber ).apply ();
234
+ apply ();
235
+ return true ;
236
+ }
237
+
238
+ /**
239
+ * @return true if progress was checked successfully
240
+ */
241
+
242
+ private boolean checkProgress () {
243
+ final Cursor cursor = manager .query (new DownloadManager .Query ());
244
+ if (!cursor .moveToFirst ()) {
245
+ cursor .close ();
246
+ return false ;
247
+ }
248
+ if (downloadId == -1 )
249
+ downloadId = BPrefs .get (this ).getLong (BPrefs .LAST_DOWNLOAD_MANAGER_REQUEST_ID , -1 );
250
+ if (downloadId == -1 )
251
+ return false ;
252
+ do {
253
+ final long reference = cursor .getLong (cursor .getColumnIndex (DownloadManager .COLUMN_ID ));
254
+ if (reference == downloadId ) {
255
+ final int status = cursor .getInt (cursor .getColumnIndex (DownloadManager .COLUMN_STATUS ));
256
+ if (status == DownloadManager .STATUS_SUCCESSFUL )
257
+ return true ;
258
+ final long progress = cursor .getLong (cursor .getColumnIndex (DownloadManager .COLUMN_BYTES_DOWNLOADED_SO_FAR ));
259
+ final long progressMax = cursor .getLong (cursor .getColumnIndex (DownloadManager .COLUMN_TOTAL_SIZE_BYTES ));
260
+ final int intProgress = (int ) ((progress * 100.0 ) / ((double ) progressMax ));
261
+ pb .setProgress (intProgress );
262
+ return true ;
263
+ }
264
+
265
+ } while (cursor .moveToNext ());
266
+ cursor .close ();
267
+
268
+ return false ;
269
+ }
270
+
271
+ private void startProgressChecker () {
272
+ if (!isProgressCheckerRunning ) {
273
+ progressChecker .run ();
274
+ isProgressCheckerRunning = true ;
275
+ }
276
+ }
277
+
278
+ private void stopProgressChecker () {
279
+ handler .removeCallbacks (progressChecker );
280
+ isProgressCheckerRunning = false ;
281
+ }
282
+
283
+ public void install () {
284
+ final File downloadedFile = getDownloadedFile ();
285
+ final Uri apkUri = S .fileToUriCompat (downloadedFile , this );
286
+ final Intent intent =
287
+ Build .VERSION .SDK_INT >= Build .VERSION_CODES .N ?
288
+ new Intent (Intent .ACTION_INSTALL_PACKAGE )
289
+ .setData (apkUri )
290
+ .setFlags (Intent .FLAG_GRANT_READ_URI_PERMISSION ) :
291
+ new Intent (Intent .ACTION_VIEW )
292
+ .setDataAndType (apkUri , "application/vnd.android.package-archive" )
293
+ .setFlags (Intent .FLAG_ACTIVITY_NEW_TASK );
294
+ this .startActivity (intent );
295
+ }
296
+
297
+ public void deleteCurrentUpdateFile () {
298
+ final File bp = getDownloadedFile ();
299
+ if (bp .exists ()) {
300
+ if (bp .delete ()) {
301
+ MediaScannerConnection .scanFile (this , new String []{bp .getAbsolutePath ()}, null , null );
302
+ } else
303
+ downloadedFileCouldNotBeDeletedToast .show ();
304
+
305
+ }
306
+ }
307
+
308
+ @ Override
309
+ protected int requiredPermissions () {
310
+ return PERMISSION_REQUEST_INSTALL_PACKAGES | PERMISSION_WRITE_EXTERNAL_STORAGE ;
311
+ }
312
+ }
0 commit comments