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
8ca188f4
Commit
8ca188f4
authored
Jul 21, 2019
by
topjohnwu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Stream and process module zips
parent
746a1d8d
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
99 additions
and
270 deletions
+99
-270
AndroidManifest.xml
app/src/main/AndroidManifest.xml
+1
-3
j.java
app/src/main/java/a/j.java
+2
-2
k.kt
app/src/main/java/a/k.kt
+0
-5
ClassMap.kt
app/src/main/java/com/topjohnwu/magisk/ClassMap.kt
+1
-3
ApplicationModule.kt
...rc/main/java/com/topjohnwu/magisk/di/ApplicationModule.kt
+0
-4
DownloadModuleService.java
...opjohnwu/magisk/model/download/DownloadModuleService.java
+0
-156
ModuleProcessor.kt
...va/com/topjohnwu/magisk/model/download/ModuleProcessor.kt
+44
-0
ModuleTransformer.kt
.../com/topjohnwu/magisk/model/download/ModuleTransformer.kt
+0
-68
RemoteFileService.kt
.../com/topjohnwu/magisk/model/download/RemoteFileService.kt
+12
-16
HomeFragment.kt
...rc/main/java/com/topjohnwu/magisk/ui/home/HomeFragment.kt
+2
-2
XAndroid.kt
app/src/main/java/com/topjohnwu/magisk/utils/XAndroid.kt
+4
-2
XJava.kt
app/src/main/java/com/topjohnwu/magisk/utils/XJava.kt
+3
-7
XNetwork.kt
app/src/main/java/com/topjohnwu/magisk/utils/XNetwork.kt
+30
-2
No files found.
app/src/main/AndroidManifest.xml
View file @
8ca188f4
...
...
@@ -65,9 +65,7 @@
<!-- Service -->
<service
android:name=
"a.j"
/>
<service
android:name=
"a.k"
<service
android:name=
"a.j"
android:exported=
"false"
/>
<!-- Hardcode GMS version -->
...
...
app/src/main/java/a/j.java
View file @
8ca188f4
package
a
;
import
com.topjohnwu.magisk.model.download.Download
Module
Service
;
import
com.topjohnwu.magisk.model.download.DownloadService
;
public
class
j
extends
Download
Module
Service
{
public
class
j
extends
DownloadService
{
/* stub */
}
app/src/main/java/a/k.kt
deleted
100644 → 0
View file @
746a1d8d
package
a
import
com.topjohnwu.magisk.model.download.DownloadService
class
k
:
DownloadService
()
\ No newline at end of file
app/src/main/java/com/topjohnwu/magisk/ClassMap.kt
View file @
8ca188f4
package
com.topjohnwu.magisk
import
com.topjohnwu.magisk.model.download.DownloadModuleService
import
com.topjohnwu.magisk.model.download.DownloadService
import
com.topjohnwu.magisk.model.receiver.GeneralReceiver
import
com.topjohnwu.magisk.model.update.UpdateCheckService
...
...
@@ -17,8 +16,7 @@ object ClassMap {
FlashActivity
::
class
.
java
to
a
.
f
::
class
.
java
,
UpdateCheckService
::
class
.
java
to
a
.
g
::
class
.
java
,
GeneralReceiver
::
class
.
java
to
a
.
h
::
class
.
java
,
DownloadModuleService
::
class
.
java
to
a
.
j
::
class
.
java
,
DownloadService
::
class
.
java
to
a
.
k
::
class
.
java
,
DownloadService
::
class
.
java
to
a
.
j
::
class
.
java
,
SuRequestActivity
::
class
.
java
to
a
.
m
::
class
.
java
)
...
...
app/src/main/java/com/topjohnwu/magisk/di/ApplicationModule.kt
View file @
8ca188f4
...
...
@@ -4,8 +4,6 @@ import android.content.Context
import
androidx.preference.PreferenceManager
import
com.skoumal.teanity.rxbus.RxBus
import
com.topjohnwu.magisk.App
import
com.topjohnwu.magisk.model.download.ModuleTransformer
import
com.topjohnwu.magisk.model.entity.internal.DownloadSubject
import
org.koin.dsl.module
...
...
@@ -17,6 +15,4 @@ val applicationModule = module {
factory
(
Protected
)
{
get
<
App
>().
protectedContext
}
single
(
SUTimeout
)
{
get
<
Context
>(
Protected
).
getSharedPreferences
(
"su_timeout"
,
0
)
}
single
{
PreferenceManager
.
getDefaultSharedPreferences
(
get
<
Context
>(
Protected
))
}
factory
{
(
subject
:
DownloadSubject
)
->
ModuleTransformer
(
get
(),
subject
)
}
}
\ No newline at end of file
app/src/main/java/com/topjohnwu/magisk/model/download/DownloadModuleService.java
deleted
100644 → 0
View file @
746a1d8d
package
com
.
topjohnwu
.
magisk
.
model
.
download
;
import
android.app.PendingIntent
;
import
android.app.Service
;
import
android.content.Intent
;
import
android.net.Uri
;
import
android.os.IBinder
;
import
androidx.annotation.Nullable
;
import
com.topjohnwu.magisk.App
;
import
com.topjohnwu.magisk.ClassMap
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.magisk.model.entity.Repo
;
import
com.topjohnwu.magisk.ui.flash.FlashActivity
;
import
com.topjohnwu.magisk.view.Notifications
;
import
com.topjohnwu.magisk.view.ProgressNotification
;
import
com.topjohnwu.net.Networking
;
import
com.topjohnwu.superuser.Shell
;
import
com.topjohnwu.superuser.ShellUtils
;
import
java.io.BufferedOutputStream
;
import
java.io.File
;
import
java.io.FileOutputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.OutputStream
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.zip.ZipEntry
;
import
java.util.zip.ZipInputStream
;
import
java.util.zip.ZipOutputStream
;
public
class
DownloadModuleService
extends
Service
{
private
List
<
ProgressNotification
>
notifications
;
@Nullable
@Override
public
IBinder
onBind
(
Intent
intent
)
{
return
null
;
}
@Override
public
void
onCreate
()
{
notifications
=
new
ArrayList
<>();
}
@Override
public
int
onStartCommand
(
Intent
intent
,
int
flags
,
int
startId
)
{
Shell
.
EXECUTOR
.
execute
(()
->
{
Repo
repo
=
intent
.
getParcelableExtra
(
"repo"
);
boolean
install
=
intent
.
getBooleanExtra
(
"install"
,
false
);
dlProcessInstall
(
repo
,
install
);
});
return
START_REDELIVER_INTENT
;
}
@Override
public
synchronized
void
onTaskRemoved
(
Intent
rootIntent
)
{
for
(
ProgressNotification
n
:
notifications
)
{
Notifications
.
mgr
.
cancel
(
n
.
hashCode
());
}
notifications
.
clear
();
}
private
synchronized
void
addNotification
(
ProgressNotification
n
)
{
if
(
notifications
.
isEmpty
())
{
// Start foreground
startForeground
(
n
.
hashCode
(),
n
.
getNotification
());
}
notifications
.
add
(
n
);
}
private
synchronized
void
removeNotification
(
ProgressNotification
n
)
{
notifications
.
remove
(
n
);
if
(
notifications
.
isEmpty
())
{
// No more tasks, stop service
stopForeground
(
true
);
stopSelf
();
}
else
{
// Pick another notification as our foreground notification
n
=
notifications
.
get
(
0
);
startForeground
(
n
.
hashCode
(),
n
.
getNotification
());
}
}
private
void
dlProcessInstall
(
Repo
repo
,
boolean
install
)
{
File
output
=
new
File
(
Const
.
EXTERNAL_PATH
,
repo
.
getDownloadFilename
());
ProgressNotification
progress
=
new
ProgressNotification
(
output
.
getName
());
addNotification
(
progress
);
try
{
InputStream
in
=
Networking
.
get
(
repo
.
getZipUrl
())
.
setDownloadProgressListener
(
progress
)
.
execForInputStream
().
getResult
();
OutputStream
out
=
new
BufferedOutputStream
(
new
FileOutputStream
(
output
));
processZip
(
in
,
out
);
Intent
intent
=
new
Intent
(
this
,
ClassMap
.
get
(
FlashActivity
.
class
));
intent
.
setData
(
Uri
.
fromFile
(
output
))
.
addFlags
(
Intent
.
FLAG_ACTIVITY_NEW_TASK
)
.
putExtra
(
Const
.
Key
.
FLASH_ACTION
,
Const
.
Value
.
FLASH_ZIP
);
synchronized
(
getApplication
())
{
if
(
install
&&
App
.
foreground
()
!=
null
&&
!(
App
.
foreground
()
instanceof
FlashActivity
))
{
/* Only start flashing if there is a foreground activity and the
* user is not also flashing another module at the same time */
App
.
foreground
().
startActivity
(
intent
);
}
else
{
/* Or else we preset a notification notifying that we are done */
PendingIntent
pi
=
PendingIntent
.
getActivity
(
this
,
progress
.
hashCode
(),
intent
,
PendingIntent
.
FLAG_UPDATE_CURRENT
);
progress
.
dlDone
(
pi
);
}
}
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
progress
.
dlFail
();
}
removeNotification
(
progress
);
}
private
void
processZip
(
InputStream
in
,
OutputStream
out
)
throws
IOException
{
try
(
ZipInputStream
zin
=
new
ZipInputStream
(
in
);
ZipOutputStream
zout
=
new
ZipOutputStream
(
out
))
{
// Inject latest module-installer.sh as update-binary
zout
.
putNextEntry
(
new
ZipEntry
(
"META-INF/"
));
zout
.
putNextEntry
(
new
ZipEntry
(
"META-INF/com/"
));
zout
.
putNextEntry
(
new
ZipEntry
(
"META-INF/com/google/"
));
zout
.
putNextEntry
(
new
ZipEntry
(
"META-INF/com/google/android/"
));
zout
.
putNextEntry
(
new
ZipEntry
(
"META-INF/com/google/android/update-binary"
));
try
(
InputStream
update_bin
=
Networking
.
get
(
Const
.
Url
.
MODULE_INSTALLER
)
.
execForInputStream
().
getResult
())
{
ShellUtils
.
pump
(
update_bin
,
zout
);
}
zout
.
putNextEntry
(
new
ZipEntry
(
"META-INF/com/google/android/updater-script"
));
zout
.
write
(
"#MAGISK\n"
.
getBytes
(
"UTF-8"
));
int
off
=
-
1
;
ZipEntry
entry
;
while
((
entry
=
zin
.
getNextEntry
())
!=
null
)
{
if
(
off
<
0
)
off
=
entry
.
getName
().
indexOf
(
'/'
)
+
1
;
String
path
=
entry
.
getName
().
substring
(
off
);
if
(
path
.
isEmpty
())
continue
;
if
(
path
.
startsWith
(
"META-INF"
))
continue
;
zout
.
putNextEntry
(
new
ZipEntry
(
path
));
if
(!
entry
.
isDirectory
())
ShellUtils
.
pump
(
zin
,
zout
);
}
}
}
}
app/src/main/java/com/topjohnwu/magisk/model/download/ModuleProcessor.kt
0 → 100644
View file @
8ca188f4
package
com.topjohnwu.magisk.model.download
import
com.topjohnwu.magisk.utils.withStreams
import
java.io.File
import
java.io.InputStream
import
java.util.zip.ZipEntry
import
java.util.zip.ZipInputStream
import
java.util.zip.ZipOutputStream
fun
InputStream
.
toModule
(
file
:
File
,
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
var
entry
:
ZipEntry
?
=
zin
.
nextEntry
while
(
entry
!=
null
)
{
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
)
}
}
entry
=
zin
.
nextEntry
}
}
}
\ No newline at end of file
app/src/main/java/com/topjohnwu/magisk/model/download/ModuleTransformer.kt
deleted
100644 → 0
View file @
746a1d8d
package
com.topjohnwu.magisk.model.download
import
android.content.Context
import
com.topjohnwu.magisk.model.entity.internal.DownloadSubject
import
com.topjohnwu.magisk.utils.cachedFile
import
com.topjohnwu.magisk.utils.withStreams
import
java.io.File
import
java.util.zip.ZipEntry
import
java.util.zip.ZipInputStream
import
java.util.zip.ZipOutputStream
class
ModuleTransformer
(
private
val
context
:
Context
,
subject
:
DownloadSubject
)
{
private
val
destination
=
context
.
cachedFile
(
subject
.
fileName
)
fun
inject
(
file
:
File
,
installer
:
File
):
File
{
return
injectInternal
(
move
(
file
),
installer
)
}
// ---
private
fun
injectInternal
(
file
:
File
,
installer
:
File
):
File
{
val
input
=
ZipInputStream
(
file
.
inputStream
())
val
output
=
ZipOutputStream
(
destination
.
outputStream
())
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
.
inputStream
().
copyTo
(
zout
).
also
{
zout
.
flush
()
}
zout
.
putNextEntry
(
ZipEntry
(
"META-INF/com/google/android/updater-script"
))
zout
.
write
(
"#MAGISK\n"
.
toByteArray
(
charset
(
"UTF-8"
)))
var
off
=
-
1
var
entry
:
ZipEntry
?
=
zin
.
nextEntry
while
(
entry
!=
null
)
{
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
).
also
{
zout
.
flush
()
}
}
}
entry
=
zin
.
nextEntry
}
}
file
.
delete
()
return
destination
}
private
fun
move
(
file
:
File
)
=
context
.
cachedFile
(
"temp"
).
apply
{
file
.
renameTo
(
this
)
}
}
\ No newline at end of file
app/src/main/java/com/topjohnwu/magisk/model/download/RemoteFileService.kt
View file @
8ca188f4
...
...
@@ -9,18 +9,19 @@ import com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.data.repository.FileRepository
import
com.topjohnwu.magisk.model.entity.internal.DownloadSubject
import
com.topjohnwu.magisk.model.entity.internal.DownloadSubject.*
import
com.topjohnwu.magisk.utils.ProgInputStream
import
com.topjohnwu.magisk.utils.cachedFile
import
com.topjohnwu.magisk.utils.firstMap
import
com.topjohnwu.magisk.utils.writeTo
CachedFile
import
com.topjohnwu.magisk.utils.writeTo
import
com.topjohnwu.magisk.view.Notifications
import
com.topjohnwu.superuser.ShellUtils
import
io.reactivex.Single
import
io.reactivex.android.schedulers.AndroidSchedulers
import
okhttp3.ResponseBody
import
org.koin.android.ext.android.get
import
org.koin.android.ext.android.inject
import
org.koin.core.parameter.parametersOf
import
timber.log.Timber
import
java.io.File
import
java.io.InputStream
abstract
class
RemoteFileService
:
NotificationService
()
{
...
...
@@ -73,19 +74,14 @@ abstract class RemoteFileService : NotificationService() {
}
private
fun
download
(
subject
:
DownloadSubject
)
=
repo
.
downloadFile
(
subject
.
url
)
.
map
{
it
.
to
File
(
subject
.
hashCode
(),
subject
.
fileName
)
}
.
map
{
it
.
to
Stream
(
subject
.
hashCode
()
)
}
.
map
{
when
(
subject
)
{
is
Module
->
{
update
(
subject
.
hashCode
())
{
it
.
setContentText
(
getString
(
R
.
string
.
download_module
))
.
setProgress
(
0
,
0
,
true
)
}
get
<
ModuleTransformer
>
{
parametersOf
(
subject
)
}
.
inject
(
it
,
startInternal
(
Installer
).
blockingGet
())
cachedFile
(
subject
.
fileName
).
apply
{
when
(
subject
)
{
is
Module
->
it
.
toModule
(
this
,
repo
.
downloadFile
(
Const
.
Url
.
MODULE_INSTALLER
).
blockingGet
().
byteStream
())
else
->
it
.
writeTo
(
this
)
}
else
->
it
}
}
...
...
@@ -95,11 +91,11 @@ abstract class RemoteFileService : NotificationService() {
.
firstOrNull
{
it
==
name
}
?.
let
{
File
(
this
,
it
)
}
private
fun
ResponseBody
.
to
File
(
id
:
Int
,
name
:
String
):
File
{
private
fun
ResponseBody
.
to
Stream
(
id
:
Int
):
InputStream
{
val
maxRaw
=
contentLength
()
val
max
=
maxRaw
/
1
_000_000f
return
writeToCachedFile
(
this
@RemoteFileService
,
name
)
{
return
ProgInputStream
(
byteStream
()
)
{
val
progress
=
it
/
1
_000_000f
update
(
id
)
{
notification
->
...
...
app/src/main/java/com/topjohnwu/magisk/ui/home/HomeFragment.kt
View file @
8ca188f4
...
...
@@ -11,7 +11,7 @@ import com.topjohnwu.magisk.model.events.*
import
com.topjohnwu.magisk.ui.base.MagiskActivity
import
com.topjohnwu.magisk.ui.base.MagiskFragment
import
com.topjohnwu.magisk.utils.ISafetyNetHelper
import
com.topjohnwu.magisk.utils.
copy
To
import
com.topjohnwu.magisk.utils.
write
To
import
com.topjohnwu.magisk.utils.inject
import
com.topjohnwu.magisk.view.MarkDownWindow
import
com.topjohnwu.magisk.view.dialogs.*
...
...
@@ -73,7 +73,7 @@ class HomeFragment : MagiskFragment<HomeViewModel, FragmentMagiskBinding>(),
private
fun
downloadSafetyNet
(
requiresUserInput
:
Boolean
=
true
)
{
fun
download
()
=
magiskRepo
.
fetchSafetynet
()
.
map
{
it
.
byteStream
().
copy
To
(
EXT_FILE
)
}
.
map
{
it
.
byteStream
().
write
To
(
EXT_FILE
)
}
.
subscribeK
{
updateSafetyNet
(
true
)
}
if
(!
requiresUserInput
)
{
...
...
app/src/main/java/com/topjohnwu/magisk/utils/XAndroid.kt
View file @
8ca188f4
...
...
@@ -95,10 +95,12 @@ fun File.provide(context: Context = get()): Uri {
}
fun
File
.
mv
(
destination
:
File
)
{
inputStream
().
copy
To
(
destination
)
inputStream
().
write
To
(
destination
)
deleteRecursively
()
}
fun
String
.
toFile
()
=
File
(
this
)
fun
Intent
.
chooser
(
title
:
String
=
"Pick an app"
)
=
Intent
.
createChooser
(
this
,
title
)
\ No newline at end of file
fun
Intent
.
chooser
(
title
:
String
=
"Pick an app"
)
=
Intent
.
createChooser
(
this
,
title
)
fun
Context
.
cachedFile
(
name
:
String
)
=
File
(
cacheDir
,
name
)
app/src/main/java/com/topjohnwu/magisk/utils/XJava.kt
View file @
8ca188f4
...
...
@@ -2,8 +2,6 @@ package com.topjohnwu.magisk.utils
import
android.net.Uri
import
androidx.core.net.toFile
import
org.kamranzafar.jtar.TarInputStream
import
org.kamranzafar.jtar.TarOutputStream
import
java.io.File
import
java.io.InputStream
import
java.io.OutputStream
...
...
@@ -18,12 +16,10 @@ fun ZipInputStream.forEach(callback: (ZipEntry) -> Unit) {
}
}
fun
Uri
.
copyTo
(
file
:
File
)
=
toFile
().
copyTo
(
file
)
fun
InputStream
.
copyTo
(
file
:
File
)
=
withStreams
(
this
,
file
.
outputStream
())
{
reader
,
writer
->
reader
.
copyTo
(
writer
)
}
fun
Uri
.
writeTo
(
file
:
File
)
=
toFile
().
copyTo
(
file
)
fun
File
.
tarInputStream
()
=
TarInputStream
(
inputStream
())
fun
File
.
tarOutputStream
()
=
TarOutputStream
(
this
)
fun
InputStream
.
writeTo
(
file
:
File
)
=
withStreams
(
this
,
file
.
outputStream
())
{
reader
,
writer
->
reader
.
copyTo
(
writer
)
}
inline
fun
<
In
:
InputStream
,
Out
:
OutputStream
>
withStreams
(
inStream
:
In
,
...
...
app/src/main/java/com/topjohnwu/magisk/utils/XNetwork.kt
View file @
8ca188f4
package
com.topjohnwu.magisk.utils
import
android.content.Context
import
com.topjohnwu.superuser.internal.UiThreadHandler
import
okhttp3.ResponseBody
import
java.io.File
import
java.io.FilterInputStream
import
java.io.InputStream
import
java.io.OutputStream
...
...
@@ -32,8 +34,6 @@ inline fun InputStream.writeTo(output: OutputStream, progress: (Long) -> Unit =
fun
ResponseBody
.
writeToString
()
=
string
()
fun
Context
.
cachedFile
(
name
:
String
)
=
File
(
cacheDir
,
name
)
inline
fun
InputStream
.
copyToWithProgress
(
out
:
OutputStream
,
progressEmitter
:
(
Long
)
->
Unit
,
...
...
@@ -49,4 +49,32 @@ inline fun InputStream.copyToWithProgress(
progressEmitter
(
bytesCopied
)
}
return
bytesCopied
}
class
ProgInputStream
(
base
:
InputStream
,
val
progressEmitter
:
(
Long
)
->
Unit
=
{})
:
FilterInputStream
(
base
)
{
private
var
bytesRead
:
Long
=
0
override
fun
read
():
Int
{
val
b
=
read
()
if
(
b
>=
0
)
{
bytesRead
++
UiThreadHandler
.
run
{
progressEmitter
(
bytesRead
)
}
}
return
b
}
override
fun
read
(
b
:
ByteArray
):
Int
{
return
read
(
b
,
0
,
b
.
size
)
}
override
fun
read
(
b
:
ByteArray
,
off
:
Int
,
len
:
Int
):
Int
{
val
sz
=
super
.
read
(
b
,
off
,
len
)
if
(
sz
>
0
)
{
bytesRead
+=
sz
UiThreadHandler
.
run
{
progressEmitter
(
bytesRead
)
}
}
return
sz
}
}
\ No newline at end of file
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