Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
M
Magisk
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
Magisk
Commits
6dbd8baa
Commit
6dbd8baa
authored
Nov 07, 2021
by
topjohnwu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Cleanup DownloadService
parent
e660fabc
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
126 additions
and
210 deletions
+126
-210
Const.kt
app/src/main/java/com/topjohnwu/magisk/core/Const.kt
+0
-2
DownloadService.kt
...ava/com/topjohnwu/magisk/core/download/DownloadService.kt
+48
-99
ManagerHandler.kt
...java/com/topjohnwu/magisk/core/download/ManagerHandler.kt
+14
-24
ModuleProcessor.kt
...ava/com/topjohnwu/magisk/core/download/ModuleProcessor.kt
+0
-43
Subject.kt
...c/main/java/com/topjohnwu/magisk/core/download/Subject.kt
+33
-13
ProgressInputStream.kt
...va/com/topjohnwu/magisk/core/utils/ProgressInputStream.kt
+6
-1
ModuleInstallDialog.kt
...com/topjohnwu/magisk/events/dialog/ModuleInstallDialog.kt
+2
-2
XJava.kt
app/src/main/java/com/topjohnwu/magisk/ktx/XJava.kt
+8
-10
FlashFragment.kt
.../main/java/com/topjohnwu/magisk/ui/flash/FlashFragment.kt
+2
-4
FlashViewModel.kt
...main/java/com/topjohnwu/magisk/ui/flash/FlashViewModel.kt
+1
-4
HomeFragment.kt
...rc/main/java/com/topjohnwu/magisk/ui/home/HomeFragment.kt
+4
-0
Notifications.kt
app/src/main/java/com/topjohnwu/magisk/view/Notifications.kt
+8
-3
main.xml
app/src/main/res/navigation/main.xml
+0
-5
No files found.
app/src/main/java/com/topjohnwu/magisk/core/Const.kt
View file @
6dbd8baa
...
...
@@ -39,8 +39,6 @@ object Const {
}
object
ID
{
// notifications
const
val
APK_UPDATE_NOTIFICATION_ID
=
5
const
val
JOB_SERVICE_ID
=
7
const
val
UPDATE_NOTIFICATION_CHANNEL
=
"update"
const
val
PROGRESS_NOTIFICATION_CHANNEL
=
"progress"
...
...
app/src/main/java/com/topjohnwu/magisk/core/download/DownloadService.kt
View file @
6dbd8baa
...
...
@@ -3,66 +3,47 @@ package com.topjohnwu.magisk.core.download
import
android.annotation.SuppressLint
import
android.app.Notification
import
android.app.PendingIntent
import
android.app.PendingIntent.*
import
android.content.Context
import
android.content.Intent
import
android.os.Build
import
android.os.IBinder
import
androidx.core.net.toFile
import
androidx.lifecycle.LifecycleOwner
import
androidx.lifecycle.MutableLiveData
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.arch.BaseUIActivity
import
com.topjohnwu.magisk.core.ForegroundTracker
import
com.topjohnwu.magisk.core.base.BaseService
import
com.topjohnwu.magisk.core.download.Action.Flash
import
com.topjohnwu.magisk.core.download.Subject.Manager
import
com.topjohnwu.magisk.core.download.Subject.Module
import
com.topjohnwu.magisk.core.intent
import
com.topjohnwu.magisk.core.utils.MediaStoreUtils.outputStream
import
com.topjohnwu.magisk.core.utils.ProgressInputStream
import
com.topjohnwu.magisk.di.ServiceLocator
import
com.topjohnwu.magisk.
ui.flash.FlashFragment
import
com.topjohnwu.magisk.
utils.APKInstall
import
com.topjohnwu.magisk.
ktx.copyAndClose
import
com.topjohnwu.magisk.
ktx.synchronized
import
com.topjohnwu.magisk.view.Notifications
import
com.topjohnwu.superuser.internal.UiThreadHandler
import
kotlinx.coroutines.CoroutineScope
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.cancel
import
kotlinx.coroutines.launch
import
com.topjohnwu.magisk.view.Notifications.mgr
import
kotlinx.coroutines.*
import
okhttp3.ResponseBody
import
timber.log.Timber
import
java.io.IOException
import
java.io.InputStream
import
java.util.*
import
kotlin.collections.HashMap
import
kotlin.random.Random.Default.nextInt
class
DownloadService
:
BaseService
()
{
private
val
context
get
()
=
this
private
val
hasNotifications
get
()
=
notifications
.
isNotEmpty
()
private
val
notifications
=
Collections
.
synchronizedMap
(
HashMap
<
Int
,
Notification
.
Builder
>()
)
private
val
coroutineScope
=
CoroutineScope
(
Dispatchers
.
IO
)
private
val
notifications
=
HashMap
<
Int
,
Notification
.
Builder
>().
synchronized
(
)
private
val
job
=
Job
(
)
val
service
get
()
=
ServiceLocator
.
networkService
private
val
mgr
get
()
=
Notifications
.
mgr
// -- Service overrides
override
fun
onBind
(
intent
:
Intent
?):
IBinder
?
=
null
override
fun
onStartCommand
(
intent
:
Intent
,
flags
:
Int
,
startId
:
Int
):
Int
{
intent
.
getParcelableExtra
<
Subject
>(
SUBJECT_KEY
)
?.
let
{
subject
->
update
(
subject
.
notifyID
())
coroutineScope
.
launch
{
try
{
subject
.
startDownload
()
}
catch
(
e
:
IOException
)
{
Timber
.
e
(
e
)
notifyFail
(
subject
)
}
}
}
return
START_REDELIVER_INTENT
intent
.
getParcelableExtra
<
Subject
>(
SUBJECT_KEY
)
?.
let
{
doDownload
(
it
)
}
return
START_NOT_STICKY
}
override
fun
onTaskRemoved
(
rootIntent
:
Intent
?)
{
...
...
@@ -73,29 +54,40 @@ class DownloadService : BaseService() {
override
fun
onDestroy
()
{
super
.
onDestroy
()
coroutineScope
.
cancel
()
job
.
cancel
()
}
// -- Download logic
private
suspend
fun
Subject
.
startDownload
()
{
val
stream
=
service
.
fetchFile
(
url
).
toProgressStream
(
this
)
when
(
this
)
{
is
Module
->
// Download and process on-the-fly
stream
.
toModule
(
file
,
service
.
fetchInstaller
().
byteStream
())
is
Manager
->
handleAPK
(
this
,
stream
)
private
fun
doDownload
(
subject
:
Subject
)
{
update
(
subject
.
notifyId
)
val
coroutineScope
=
CoroutineScope
(
job
+
Dispatchers
.
IO
)
coroutineScope
.
launch
{
try
{
val
stream
=
service
.
fetchFile
(
subject
.
url
).
toProgressStream
(
subject
)
when
(
subject
)
{
is
Subject
.
Manager
->
handleAPK
(
subject
,
stream
)
else
->
stream
.
copyAndClose
(
subject
.
file
.
outputStream
())
}
if
(
ForegroundTracker
.
hasForeground
)
{
remove
(
subject
.
notifyId
)
subject
.
pendingIntent
(
this
@DownloadService
).
send
()
}
else
{
notifyFinish
(
subject
)
}
if
(!
hasNotifications
)
stopSelf
()
}
catch
(
e
:
IOException
)
{
Timber
.
e
(
e
)
notifyFail
(
subject
)
}
}
val
newId
=
notifyFinish
(
this
)
if
(
ForegroundTracker
.
hasForeground
)
onFinish
(
this
,
newId
)
if
(!
hasNotifications
)
stopSelf
()
}
private
fun
ResponseBody
.
toProgressStream
(
subject
:
Subject
):
InputStream
{
val
max
=
contentLength
()
val
total
=
max
.
toFloat
()
/
1048576
val
id
=
subject
.
notifyI
D
()
val
id
=
subject
.
notifyI
d
update
(
id
)
{
it
.
setContentTitle
(
subject
.
title
)
}
...
...
@@ -115,18 +107,18 @@ class DownloadService : BaseService() {
}
}
// --- Notification
s
// --- Notification
management
private
fun
notifyFail
(
subject
:
Subject
)
=
finalNotify
(
subject
.
notifyI
D
()
)
{
private
fun
notifyFail
(
subject
:
Subject
)
=
finalNotify
(
subject
.
notifyI
d
)
{
broadcast
(-
2f
,
subject
)
it
.
setContentText
(
getString
(
R
.
string
.
download_file_error
))
.
setSmallIcon
(
android
.
R
.
drawable
.
stat_notify_error
)
.
setOngoing
(
false
)
}
private
fun
notifyFinish
(
subject
:
Subject
)
=
finalNotify
(
subject
.
notifyI
D
()
)
{
private
fun
notifyFinish
(
subject
:
Subject
)
=
finalNotify
(
subject
.
notifyI
d
)
{
broadcast
(
1f
,
subject
)
it
.
set
Intent
(
subject
)
it
.
set
ContentIntent
(
subject
.
pendingIntent
(
this
)
)
.
setContentTitle
(
subject
.
title
)
.
setContentText
(
getString
(
R
.
string
.
download_complete
))
.
setSmallIcon
(
android
.
R
.
drawable
.
stat_sys_download_done
)
...
...
@@ -135,17 +127,14 @@ class DownloadService : BaseService() {
.
setAutoCancel
(
true
)
}
private
fun
finalNotify
(
id
:
Int
,
editor
:
(
Notification
.
Builder
)
->
Notification
.
Builder
)
:
Int
{
val
notification
=
remove
(
id
)
?.
run
(
editor
)
?:
return
-
1
val
newId
=
nextInt
()
private
fun
finalNotify
(
id
:
Int
,
editor
:
(
Notification
.
Builder
)
->
Unit
):
Int
{
val
notification
=
remove
(
id
)
?.
also
(
editor
)
?:
return
-
1
val
newId
=
Notifications
.
nextId
()
mgr
.
notify
(
newId
,
notification
.
build
())
return
newId
}
fun
create
()
=
Notifications
.
progress
(
this
,
""
)
private
fun
create
()
=
Notifications
.
progress
(
this
,
""
)
fun
update
(
id
:
Int
,
editor
:
(
Notification
.
Builder
)
->
Unit
=
{})
{
val
wasEmpty
=
!
hasNotifications
...
...
@@ -171,49 +160,9 @@ class DownloadService : BaseService() {
}
}
private
fun
Notification
.
Builder
.
setIntent
(
subject
:
Subject
)
=
when
(
subject
)
{
is
Module
->
setIntent
(
subject
)
is
Manager
->
setIntent
(
subject
)
}
private
fun
Notification
.
Builder
.
setIntent
(
subject
:
Module
)
=
when
(
subject
.
action
)
{
Flash
->
setContentIntent
(
FlashFragment
.
installIntent
(
context
,
subject
.
file
))
else
->
setContentIntent
(
Intent
())
}
private
fun
Notification
.
Builder
.
setIntent
(
subject
:
Manager
)
=
setContentIntent
(
APKInstall
.
installIntent
(
context
,
subject
.
file
.
toFile
()))
@SuppressLint
(
"InlinedApi"
)
private
fun
Notification
.
Builder
.
setContentIntent
(
intent
:
Intent
)
=
setContentIntent
(
PendingIntent
.
getActivity
(
context
,
nextInt
(),
intent
,
PendingIntent
.
FLAG_IMMUTABLE
or
PendingIntent
.
FLAG_ONE_SHOT
))
// -- Post download processing
private
fun
onFinish
(
subject
:
Subject
,
id
:
Int
)
=
when
(
subject
)
{
is
Module
->
subject
.
onFinish
(
id
)
is
Manager
->
subject
.
onFinish
(
id
)
}
private
fun
Module
.
onFinish
(
id
:
Int
)
=
when
(
action
)
{
Flash
->
{
UiThreadHandler
.
run
{
(
ForegroundTracker
.
foreground
as
?
BaseUIActivity
<*,
*>)
?.
navigation
?.
navigate
(
FlashFragment
.
install
(
file
,
id
))
}
}
else
->
Unit
}
private
fun
Manager
.
onFinish
(
id
:
Int
)
{
remove
(
id
)
APKInstall
.
install
(
context
,
file
.
toFile
())
}
companion
object
{
private
const
val
SUBJECT_KEY
=
"download_subject"
private
const
val
REQUEST_CODE
=
1
private
val
progressBroadcast
=
MutableLiveData
<
Pair
<
Float
,
Subject
>?>()
...
...
@@ -233,13 +182,13 @@ class DownloadService : BaseService() {
context
.
intent
<
DownloadService
>().
putExtra
(
SUBJECT_KEY
,
subject
)
@SuppressLint
(
"InlinedApi"
)
fun
pendingIntent
(
context
:
Context
,
subject
:
Subject
):
PendingIntent
{
fun
getPendingIntent
(
context
:
Context
,
subject
:
Subject
):
PendingIntent
{
val
flag
=
FLAG_IMMUTABLE
or
FLAG_UPDATE_CURRENT
or
FLAG_ONE_SHOT
val
intent
=
intent
(
context
,
subject
)
return
if
(
Build
.
VERSION
.
SDK_INT
>=
26
)
{
PendingIntent
.
getForegroundService
(
context
,
nextInt
(),
intent
(
context
,
subject
),
PendingIntent
.
FLAG_IMMUTABLE
or
PendingIntent
.
FLAG_UPDATE_CURRENT
)
getForegroundService
(
context
,
REQUEST_CODE
,
intent
,
flag
)
}
else
{
PendingIntent
.
getService
(
context
,
nextInt
(),
intent
(
context
,
subject
),
PendingIntent
.
FLAG_IMMUTABLE
or
PendingIntent
.
FLAG_UPDATE_CURRENT
)
getService
(
context
,
REQUEST_CODE
,
intent
,
flag
)
}
}
...
...
app/src/main/java/com/topjohnwu/magisk/core/download/ManagerHandler.kt
View file @
6dbd8baa
package
com.topjohnwu.magisk.core.download
import
android.content.Context
import
androidx.core.net.toFile
import
com.topjohnwu.magisk.DynAPK
import
com.topjohnwu.magisk.R
...
...
@@ -8,29 +7,14 @@ import com.topjohnwu.magisk.core.Info
import
com.topjohnwu.magisk.core.isRunningAsStub
import
com.topjohnwu.magisk.core.tasks.HideAPK
import
com.topjohnwu.magisk.core.utils.MediaStoreUtils.outputStream
import
com.topjohnwu.magisk.ktx.copyAndClose
import
com.topjohnwu.magisk.ktx.relaunchApp
import
com.topjohnwu.magisk.ktx.withStreams
import
com.topjohnwu.magisk.ktx.writeTo
import
java.io.File
import
java.io.InputStream
import
java.io.OutputStream
private
fun
Context
.
patch
(
apk
:
File
)
{
val
patched
=
File
(
apk
.
parent
,
"patched.apk"
)
HideAPK
.
patch
(
this
,
apk
,
patched
,
packageName
,
applicationInfo
.
nonLocalizedLabel
)
apk
.
delete
()
patched
.
renameTo
(
apk
)
}
private
fun
DownloadService
.
notifyHide
(
id
:
Int
)
{
update
(
id
)
{
it
.
setProgress
(
0
,
0
,
true
)
.
setContentTitle
(
getString
(
R
.
string
.
hide_app_title
))
.
setContentText
(
""
)
}
}
private
class
DupOutputStream
(
private
class
TeeOutputStream
(
private
val
o1
:
OutputStream
,
private
val
o2
:
OutputStream
)
:
OutputStream
()
{
...
...
@@ -50,20 +34,26 @@ private class DupOutputStream(
suspend
fun
DownloadService
.
handleAPK
(
subject
:
Subject
.
Manager
,
stream
:
InputStream
)
{
fun
write
(
output
:
OutputStream
)
{
val
ext
=
subject
.
externalFile
.
outputStream
()
val
o
=
DupOutputStream
(
ext
,
output
)
withStreams
(
stream
,
o
)
{
src
,
out
->
src
.
copyTo
(
out
)
}
val
external
=
subject
.
externalFile
.
outputStream
()
stream
.
copyAndClose
(
TeeOutputStream
(
external
,
output
))
}
if
(
isRunningAsStub
)
{
val
apk
=
subject
.
file
.
toFile
()
val
id
=
subject
.
notifyI
D
()
val
id
=
subject
.
notifyI
d
write
(
DynAPK
.
update
(
this
).
outputStream
())
if
(
Info
.
stub
!!
.
version
<
subject
.
stub
.
versionCode
)
{
// Also upgrade stub
notifyHide
(
id
)
update
(
id
)
{
it
.
setProgress
(
0
,
0
,
true
)
.
setContentTitle
(
getString
(
R
.
string
.
hide_app_title
))
.
setContentText
(
""
)
}
service
.
fetchFile
(
subject
.
stub
.
link
).
byteStream
().
writeTo
(
apk
)
patch
(
apk
)
val
patched
=
File
(
apk
.
parent
,
"patched.apk"
)
HideAPK
.
patch
(
this
,
apk
,
patched
,
packageName
,
applicationInfo
.
nonLocalizedLabel
)
apk
.
delete
()
patched
.
renameTo
(
apk
)
}
else
{
// Simply relaunch the app
stopSelf
()
...
...
app/src/main/java/com/topjohnwu/magisk/core/download/ModuleProcessor.kt
deleted
100644 → 0
View file @
e660fabc
package
com.topjohnwu.magisk.core.download
import
android.net.Uri
import
com.topjohnwu.magisk.core.utils.MediaStoreUtils.outputStream
import
com.topjohnwu.magisk.ktx.forEach
import
com.topjohnwu.magisk.ktx.withStreams
import
java.io.InputStream
import
java.util.zip.ZipEntry
import
java.util.zip.ZipInputStream
import
java.util.zip.ZipOutputStream
fun
InputStream
.
toModule
(
file
:
Uri
,
installer
:
InputStream
)
{
val
input
=
ZipInputStream
(
buffered
())
val
output
=
ZipOutputStream
(
file
.
outputStream
().
buffered
())
withStreams
(
input
,
output
)
{
zin
,
zout
->
zout
.
putNextEntry
(
ZipEntry
(
"META-INF/"
))
zout
.
putNextEntry
(
ZipEntry
(
"META-INF/com/"
))
zout
.
putNextEntry
(
ZipEntry
(
"META-INF/com/google/"
))
zout
.
putNextEntry
(
ZipEntry
(
"META-INF/com/google/android/"
))
zout
.
putNextEntry
(
ZipEntry
(
"META-INF/com/google/android/update-binary"
))
installer
.
copyTo
(
zout
)
zout
.
putNextEntry
(
ZipEntry
(
"META-INF/com/google/android/updater-script"
))
zout
.
write
(
"#MAGISK\n"
.
toByteArray
(
charset
(
"UTF-8"
)))
var
off
=
-
1
zin
.
forEach
{
entry
->
if
(
off
<
0
)
{
off
=
entry
.
name
.
indexOf
(
'/'
)
+
1
}
val
path
=
entry
.
name
.
substring
(
off
)
if
(
path
.
isNotEmpty
()
&&
!
path
.
startsWith
(
"META-INF"
))
{
zout
.
putNextEntry
(
ZipEntry
(
path
))
if
(!
entry
.
isDirectory
)
{
zin
.
copyTo
(
zout
)
}
}
}
}
}
app/src/main/java/com/topjohnwu/magisk/core/download/Subject.kt
View file @
6dbd8baa
package
com.topjohnwu.magisk.core.download
import
android.annotation.SuppressLint
import
android.app.PendingIntent
import
android.content.Context
import
android.content.Intent
import
android.net.Uri
import
android.os.Parcelable
import
androidx.core.net.toFile
import
androidx.core.net.toUri
import
com.topjohnwu.magisk.core.Info
import
com.topjohnwu.magisk.core.model.MagiskJson
...
...
@@ -10,22 +15,33 @@ import com.topjohnwu.magisk.core.model.module.OnlineModule
import
com.topjohnwu.magisk.core.utils.MediaStoreUtils
import
com.topjohnwu.magisk.di.AppContext
import
com.topjohnwu.magisk.ktx.cachedFile
import
com.topjohnwu.magisk.ui.flash.FlashFragment
import
com.topjohnwu.magisk.utils.APKInstall
import
com.topjohnwu.magisk.view.Notifications
import
kotlinx.parcelize.IgnoredOnParcel
import
kotlinx.parcelize.Parcelize
private
fun
cachedFile
(
name
:
String
)
=
AppContext
.
cachedFile
(
name
).
apply
{
delete
()
}.
toUri
()
enum
class
Action
{
Flash
,
Download
}
sealed
class
Subject
:
Parcelable
{
abstract
val
url
:
String
abstract
val
file
:
Uri
abstract
val
action
:
Action
abstract
val
title
:
String
abstract
val
notifyId
:
Int
abstract
fun
pendingIntent
(
context
:
Context
):
PendingIntent
@Parcelize
class
Module
(
val
module
:
OnlineModule
,
override
val
action
:
Action
val
action
:
Action
,
override
val
notifyId
:
Int
=
Notifications
.
nextId
()
)
:
Subject
()
{
override
val
url
:
String
get
()
=
module
.
zip_url
override
val
title
:
String
get
()
=
module
.
downloadFilename
...
...
@@ -34,14 +50,19 @@ sealed class Subject : Parcelable {
override
val
file
by
lazy
{
MediaStoreUtils
.
getFile
(
title
).
uri
}
override
fun
pendingIntent
(
context
:
Context
)
=
when
(
action
)
{
Action
.
Flash
->
FlashFragment
.
installIntent
(
context
,
file
)
else
->
Intent
().
toPending
(
context
)
}
}
@Parcelize
class
Manager
(
private
val
json
:
MagiskJson
=
Info
.
remote
.
magisk
,
val
stub
:
StubJson
=
Info
.
remote
.
stub
val
stub
:
StubJson
=
Info
.
remote
.
stub
,
override
val
notifyId
:
Int
=
Notifications
.
nextId
()
)
:
Subject
()
{
override
val
action
get
()
=
Action
.
Download
override
val
title
:
String
get
()
=
"Magisk-${json.version}(${json.versionCode})"
override
val
url
:
String
get
()
=
json
.
link
...
...
@@ -51,15 +72,14 @@ sealed class Subject : Parcelable {
}
val
externalFile
get
()
=
MediaStoreUtils
.
getFile
(
"$title.apk"
).
uri
}
fun
notifyID
()
=
hashCode
()
}
sealed
class
Action
:
Parcelable
{
@Parcelize
object
Flash
:
Action
()
override
fun
pendingIntent
(
context
:
Context
)
=
APKInstall
.
installIntent
(
context
,
file
.
toFile
()).
toPending
(
context
)
}
@Parcelize
object
Download
:
Action
()
@SuppressLint
(
"InlinedApi"
)
protected
fun
Intent
.
toPending
(
context
:
Context
):
PendingIntent
{
return
PendingIntent
.
getActivity
(
context
,
notifyId
,
this
,
PendingIntent
.
FLAG_IMMUTABLE
or
PendingIntent
.
FLAG_ONE_SHOT
)
}
}
app/src/main/java/com/topjohnwu/magisk/core/utils/ProgressInputStream.kt
View file @
6dbd8baa
...
...
@@ -5,7 +5,7 @@ import java.io.InputStream
class
ProgressInputStream
(
base
:
InputStream
,
val
progressEmitter
:
(
Long
)
->
Unit
=
{}
val
progressEmitter
:
(
Long
)
->
Unit
)
:
FilterInputStream
(
base
)
{
private
var
bytesRead
=
0L
...
...
@@ -40,4 +40,9 @@ class ProgressInputStream(
}
return
sz
}
override
fun
close
()
{
super
.
close
()
progressEmitter
(
bytesRead
)
}
}
app/src/main/java/com/topjohnwu/magisk/events/dialog/ModuleInstallDialog.kt
View file @
6dbd8baa
...
...
@@ -14,8 +14,8 @@ class ModuleInstallDialog(private val item: OnlineModule) : DialogEvent() {
with
(
dialog
)
{
fun
download
(
install
:
Boolean
)
{
val
config
=
if
(
install
)
Action
.
Flash
else
Action
.
Download
val
subject
=
Subject
.
Module
(
item
,
config
)
val
action
=
if
(
install
)
Action
.
Flash
else
Action
.
Download
val
subject
=
Subject
.
Module
(
item
,
action
)
DownloadService
.
start
(
context
,
subject
)
}
...
...
app/src/main/java/com/topjohnwu/magisk/ktx/XJava.kt
View file @
6dbd8baa
...
...
@@ -19,9 +19,6 @@ inline fun ZipInputStream.forEach(callback: (ZipEntry) -> Unit) {
}
}
fun
InputStream
.
writeTo
(
file
:
File
)
=
withStreams
(
this
,
file
.
outputStream
())
{
reader
,
writer
->
reader
.
copyTo
(
writer
)
}
inline
fun
<
In
:
InputStream
,
Out
:
OutputStream
>
withStreams
(
inStream
:
In
,
outStream
:
Out
,
...
...
@@ -34,18 +31,19 @@ inline fun <In : InputStream, Out : OutputStream> withStreams(
}
}
fun
<
T
>
MutableList
<
T
>.
update
(
newList
:
List
<
T
>)
{
clear
()
addAll
(
newList
)
}
fun
InputStream
.
copyAndClose
(
out
:
OutputStream
)
=
withStreams
(
this
,
out
)
{
i
,
o
->
i
.
copyTo
(
o
)
}
fun
InputStream
.
writeTo
(
file
:
File
)
=
copyAndClose
(
file
.
outputStream
())
operator
fun
<
E
>
SparseArrayCompat
<
E
>.
set
(
key
:
Int
,
value
:
E
)
{
put
(
key
,
value
)
}
fun
<
T
>
MutableList
<
T
>.
synchronized
()
=
Collections
.
synchronizedList
(
this
)
fun
<
T
>
MutableSet
<
T
>.
synchronized
()
=
Collections
.
synchronizedSet
(
this
)
fun
<
K
,
V
>
MutableMap
<
K
,
V
>.
synchronized
()
=
Collections
.
synchronizedMap
(
this
)
fun
<
T
>
MutableList
<
T
>.
synchronized
():
MutableList
<
T
>
=
Collections
.
synchronizedList
(
this
)
fun
<
T
>
MutableSet
<
T
>.
synchronized
():
MutableSet
<
T
>
=
Collections
.
synchronizedSet
(
this
)
fun
<
K
,
V
>
MutableMap
<
K
,
V
>.
synchronized
():
MutableMap
<
K
,
V
>
=
Collections
.
synchronizedMap
(
this
)
fun
SimpleDateFormat
.
parseOrNull
(
date
:
String
)
=
runCatching
{
parse
(
date
)
}.
onFailure
{
Timber
.
e
(
it
)
}.
getOrNull
()
...
...
app/src/main/java/com/topjohnwu/magisk/ui/flash/FlashFragment.kt
View file @
6dbd8baa
...
...
@@ -111,16 +111,14 @@ class FlashFragment : BaseUIFragment<FlashViewModel, FragmentFlashMd2Binding>()
/* Installing is understood as flashing modules / zips */
fun
installIntent
(
context
:
Context
,
file
:
Uri
,
id
:
Int
=
-
1
)
=
FlashFragmentArgs
(
fun
installIntent
(
context
:
Context
,
file
:
Uri
)
=
FlashFragmentArgs
(
action
=
Const
.
Value
.
FLASH_ZIP
,
additionalData
=
file
,
dismissId
=
id
).
let
{
createIntent
(
context
,
it
)
}
fun
install
(
file
:
Uri
,
id
:
Int
)
=
MainDirections
.
actionFlashFragment
(
fun
install
(
file
:
Uri
)
=
MainDirections
.
actionFlashFragment
(
action
=
Const
.
Value
.
FLASH_ZIP
,
additionalData
=
file
,
dismissId
=
id
)
}
...
...
app/src/main/java/com/topjohnwu/magisk/ui/flash/FlashViewModel.kt
View file @
6dbd8baa
...
...
@@ -20,7 +20,6 @@ import com.topjohnwu.magisk.databinding.itemBindingOf
import
com.topjohnwu.magisk.databinding.set
import
com.topjohnwu.magisk.events.SnackbarEvent
import
com.topjohnwu.magisk.ktx.*
import
com.topjohnwu.magisk.view.Notifications
import
com.topjohnwu.superuser.CallbackList
import
com.topjohnwu.superuser.Shell
import
kotlinx.coroutines.Dispatchers
...
...
@@ -50,9 +49,7 @@ class FlashViewModel : BaseViewModel() {
}
fun
startFlashing
()
{
val
(
action
,
uri
,
id
)
=
args
if
(
id
!=
-
1
)
Notifications
.
mgr
.
cancel
(
id
)
val
(
action
,
uri
)
=
args
viewModelScope
.
launch
{
val
result
=
when
(
action
)
{
...
...
app/src/main/java/com/topjohnwu/magisk/ui/home/HomeFragment.kt
View file @
6dbd8baa
...
...
@@ -70,4 +70,8 @@ class HomeFragment : BaseUIFragment<HomeViewModel, FragmentHomeMd2Binding>() {
return
true
}
override
fun
onResume
()
{
super
.
onResume
()
viewModel
.
stateManagerProgress
=
0
}
}
app/src/main/java/com/topjohnwu/magisk/view/Notifications.kt
View file @
6dbd8baa
...
...
@@ -8,19 +8,22 @@ import android.os.Build.VERSION.SDK_INT
import
androidx.core.content.getSystemService
import
androidx.core.graphics.drawable.toIcon
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.core.Const
import
com.topjohnwu.magisk.core.Const.ID.PROGRESS_NOTIFICATION_CHANNEL
import
com.topjohnwu.magisk.core.Const.ID.UPDATE_NOTIFICATION_CHANNEL
import
com.topjohnwu.magisk.core.download.DownloadService
import
com.topjohnwu.magisk.core.download.Subject
import
com.topjohnwu.magisk.di.AppContext
import
com.topjohnwu.magisk.ktx.getBitmap
import
java.util.concurrent.atomic.AtomicInteger
@Suppress
(
"DEPRECATION"
)
object
Notifications
{
val
mgr
by
lazy
{
AppContext
.
getSystemService
<
NotificationManager
>()
!!
}
private
const
val
APK_UPDATE_NOTIFICATION_ID
=
5
private
val
nextId
=
AtomicInteger
(
APK_UPDATE_NOTIFICATION_ID
)
fun
setup
(
context
:
Context
)
{
if
(
SDK_INT
>=
26
)
{
var
channel
=
NotificationChannel
(
UPDATE_NOTIFICATION_CHANNEL
,
...
...
@@ -46,7 +49,7 @@ object Notifications {
}
fun
managerUpdate
(
context
:
Context
)
{
val
intent
=
DownloadService
.
p
endingIntent
(
context
,
Subject
.
Manager
())
val
intent
=
DownloadService
.
getP
endingIntent
(
context
,
Subject
.
Manager
())
val
builder
=
updateBuilder
(
context
)
.
setContentTitle
(
context
.
getString
(
R
.
string
.
magisk_update_title
))
...
...
@@ -54,7 +57,7 @@ object Notifications {
.
setAutoCancel
(
true
)
.
setContentIntent
(
intent
)
mgr
.
notify
(
Const
.
ID
.
APK_UPDATE_NOTIFICATION_ID
,
builder
.
build
())
mgr
.
notify
(
APK_UPDATE_NOTIFICATION_ID
,
builder
.
build
())
}
fun
progress
(
context
:
Context
,
title
:
CharSequence
):
Notification
.
Builder
{
...
...
@@ -69,4 +72,6 @@ object Notifications {
.
setOngoing
(
true
)
return
builder
}
fun
nextId
()
=
nextId
.
incrementAndGet
()
}
app/src/main/res/navigation/main.xml
View file @
6dbd8baa
...
...
@@ -51,11 +51,6 @@
app:argType=
"android.net.Uri"
app:nullable=
"true"
/>
<argument
android:name=
"dismiss_id"
android:defaultValue=
"-1"
app:argType=
"integer"
/>
</fragment>
<fragment
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment