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
3af66b72
Commit
3af66b72
authored
Dec 03, 2018
by
topjohnwu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Use notifications when downloading modules
parent
422c24bd
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
154 additions
and
208 deletions
+154
-208
ReposAdapter.java
...full/java/com/topjohnwu/magisk/adapters/ReposAdapter.java
+10
-11
DownloadModule.java
...full/java/com/topjohnwu/magisk/asyncs/DownloadModule.java
+136
-0
ProcessRepoZip.java
...full/java/com/topjohnwu/magisk/asyncs/ProcessRepoZip.java
+0
-196
NotificationProgress.java
...com/topjohnwu/magisk/components/NotificationProgress.java
+7
-0
strings.xml
app/src/full/res/values/strings.xml
+1
-1
No files found.
app/src/full/java/com/topjohnwu/magisk/adapters/ReposAdapter.java
View file @
3af66b72
...
...
@@ -12,8 +12,8 @@ import android.widget.LinearLayout;
import
android.widget.TextView
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.asyncs.DownloadModule
;
import
com.topjohnwu.magisk.asyncs.MarkDownWindow
;
import
com.topjohnwu.magisk.asyncs.ProcessRepoZip
;
import
com.topjohnwu.magisk.components.BaseActivity
;
import
com.topjohnwu.magisk.components.CustomAlertDialog
;
import
com.topjohnwu.magisk.container.Module
;
...
...
@@ -105,16 +105,15 @@ public class ReposAdapter extends SectionedAdapter<ReposAdapter.SectionHolder, R
holder
.
downloadImage
.
setOnClickListener
(
v
->
{
new
CustomAlertDialog
((
BaseActivity
)
context
)
.
setTitle
(
context
.
getString
(
R
.
string
.
repo_install_title
,
repo
.
getName
()))
.
setMessage
(
context
.
getString
(
R
.
string
.
repo_install_msg
,
repo
.
getDownloadFilename
()))
.
setCancelable
(
true
)
.
setPositiveButton
(
R
.
string
.
install
,
(
d
,
i
)
->
new
ProcessRepoZip
((
BaseActivity
)
context
,
repo
,
true
).
exec
()
)
.
setNeutralButton
(
R
.
string
.
download
,
(
d
,
i
)
->
new
ProcessRepoZip
((
BaseActivity
)
context
,
repo
,
false
).
exec
())
.
setNegativeButton
(
R
.
string
.
no_thanks
,
null
)
.
show
();
.
setTitle
(
context
.
getString
(
R
.
string
.
repo_install_title
,
repo
.
getName
()))
.
setMessage
(
context
.
getString
(
R
.
string
.
repo_install_msg
,
repo
.
getDownloadFilename
()))
.
setCancelable
(
true
)
.
setPositiveButton
(
R
.
string
.
install
,
(
d
,
i
)
->
DownloadModule
.
exec
((
BaseActivity
)
context
,
repo
,
true
))
.
setNeutralButton
(
R
.
string
.
download
,
(
d
,
i
)
->
DownloadModule
.
exec
((
BaseActivity
)
context
,
repo
,
false
))
.
setNegativeButton
(
R
.
string
.
no_thanks
,
null
)
.
show
();
});
}
...
...
app/src/full/java/com/topjohnwu/magisk/asyncs/DownloadModule.java
0 → 100644
View file @
3af66b72
package
com
.
topjohnwu
.
magisk
.
asyncs
;
import
android.Manifest
;
import
android.content.Intent
;
import
android.net.Uri
;
import
android.os.AsyncTask
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.magisk.Data
;
import
com.topjohnwu.magisk.FlashActivity
;
import
com.topjohnwu.magisk.MagiskManager
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.components.BaseActivity
;
import
com.topjohnwu.magisk.components.NotificationProgress
;
import
com.topjohnwu.magisk.container.Repo
;
import
com.topjohnwu.magisk.utils.WebService
;
import
com.topjohnwu.magisk.utils.ZipUtils
;
import
com.topjohnwu.superuser.ShellUtils
;
import
java.io.BufferedInputStream
;
import
java.io.BufferedOutputStream
;
import
java.io.File
;
import
java.io.FileOutputStream
;
import
java.io.FilterInputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.OutputStream
;
import
java.net.HttpURLConnection
;
import
java.util.zip.ZipEntry
;
import
java.util.zip.ZipInputStream
;
import
java.util.zip.ZipOutputStream
;
public
class
DownloadModule
{
public
static
void
exec
(
BaseActivity
activity
,
Repo
repo
,
boolean
install
)
{
activity
.
runWithPermission
(
new
String
[]
{
Manifest
.
permission
.
WRITE_EXTERNAL_STORAGE
},
()
->
AsyncTask
.
THREAD_POOL_EXECUTOR
.
execute
(()
->
dlProcessInstall
(
repo
,
install
)));
}
private
static
void
dlProcessInstall
(
Repo
repo
,
boolean
install
)
{
File
output
=
new
File
(
Const
.
EXTERNAL_PATH
,
repo
.
getDownloadFilename
());
NotificationProgress
progress
=
new
NotificationProgress
(
output
.
getName
());
try
{
MagiskManager
mm
=
Data
.
MM
();
File
temp1
=
new
File
(
mm
.
getCacheDir
(),
"temp.zip"
);
HttpURLConnection
conn
=
WebService
.
mustRequest
(
repo
.
getZipUrl
());
ProgressInputStream
pis
=
new
ProgressInputStream
(
conn
.
getInputStream
(),
conn
.
getContentLength
(),
progress
);
removeTopFolder
(
new
BufferedInputStream
(
pis
),
new
BufferedOutputStream
(
new
FileOutputStream
(
temp1
)));
conn
.
disconnect
();
progress
.
getNotification
()
.
setProgress
(
0
,
0
,
true
)
.
setContentTitle
(
mm
.
getString
(
R
.
string
.
zip_process_msg
))
.
setContentText
(
""
);
progress
.
update
();
ZipUtils
.
signZip
(
temp1
,
output
);
temp1
.
delete
();
if
(
install
)
{
progress
.
dismiss
();
Intent
intent
=
new
Intent
(
mm
,
Data
.
classMap
.
get
(
FlashActivity
.
class
));
intent
.
setData
(
Uri
.
fromFile
(
output
))
.
addFlags
(
Intent
.
FLAG_ACTIVITY_NEW_TASK
)
.
putExtra
(
Const
.
Key
.
FLASH_ACTION
,
Const
.
Value
.
FLASH_ZIP
);
mm
.
startActivity
(
intent
);
}
else
{
progress
.
getNotification
().
setContentTitle
(
output
.
getName
());
progress
.
dlDone
();
}
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
progress
.
dlFail
();
}
}
private
static
void
removeTopFolder
(
InputStream
in
,
OutputStream
out
)
throws
IOException
{
try
(
ZipInputStream
zin
=
new
ZipInputStream
(
in
);
ZipOutputStream
zout
=
new
ZipOutputStream
(
out
))
{
ZipEntry
entry
;
int
off
=
-
1
;
while
((
entry
=
zin
.
getNextEntry
())
!=
null
)
{
if
(
off
<
0
)
off
=
entry
.
getName
().
indexOf
(
'/'
)
+
1
;
String
path
=
entry
.
getName
().
substring
(
off
);
if
(
path
.
isEmpty
())
continue
;
zout
.
putNextEntry
(
new
ZipEntry
(
path
));
if
(!
entry
.
isDirectory
())
ShellUtils
.
pump
(
zin
,
zout
);
}
}
}
private
static
class
ProgressInputStream
extends
FilterInputStream
{
private
long
totalBytes
;
private
long
bytesDownloaded
;
private
NotificationProgress
progress
;
protected
ProgressInputStream
(
InputStream
in
,
long
size
,
NotificationProgress
p
)
{
super
(
in
);
totalBytes
=
size
;
progress
=
p
;
}
private
void
updateProgress
()
{
progress
.
onProgress
(
bytesDownloaded
,
totalBytes
);
}
@Override
public
int
read
()
throws
IOException
{
int
b
=
super
.
read
();
if
(
b
>=
0
)
{
bytesDownloaded
++;
updateProgress
();
}
return
b
;
}
@Override
public
int
read
(
byte
[]
b
)
throws
IOException
{
return
read
(
b
,
0
,
b
.
length
);
}
@Override
public
int
read
(
byte
[]
b
,
int
off
,
int
len
)
throws
IOException
{
int
sz
=
super
.
read
(
b
,
off
,
len
);
if
(
sz
>
0
)
{
bytesDownloaded
+=
sz
;
updateProgress
();
}
return
sz
;
}
}
}
app/src/full/java/com/topjohnwu/magisk/asyncs/ProcessRepoZip.java
deleted
100644 → 0
View file @
422c24bd
package
com
.
topjohnwu
.
magisk
.
asyncs
;
import
android.Manifest
;
import
android.app.ProgressDialog
;
import
android.content.Intent
;
import
android.net.Uri
;
import
android.widget.Toast
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.magisk.Data
;
import
com.topjohnwu.magisk.FlashActivity
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.components.BaseActivity
;
import
com.topjohnwu.magisk.components.SnackbarMaker
;
import
com.topjohnwu.magisk.container.Repo
;
import
com.topjohnwu.magisk.utils.Utils
;
import
com.topjohnwu.magisk.utils.WebService
;
import
com.topjohnwu.magisk.utils.ZipUtils
;
import
com.topjohnwu.superuser.Shell
;
import
com.topjohnwu.superuser.ShellUtils
;
import
java.io.BufferedInputStream
;
import
java.io.BufferedOutputStream
;
import
java.io.File
;
import
java.io.FileInputStream
;
import
java.io.FileOutputStream
;
import
java.io.FilterInputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.OutputStream
;
import
java.net.HttpURLConnection
;
import
java.util.jar.JarEntry
;
import
java.util.jar.JarInputStream
;
import
java.util.jar.JarOutputStream
;
import
androidx.annotation.NonNull
;
public
class
ProcessRepoZip
extends
ParallelTask
<
Void
,
Object
,
Boolean
>
{
private
ProgressDialog
progressDialog
;
private
boolean
mInstall
;
private
File
mFile
;
private
Repo
mRepo
;
private
int
progress
=
0
,
total
=
-
1
;
public
ProcessRepoZip
(
BaseActivity
context
,
Repo
repo
,
boolean
install
)
{
super
(
context
);
mRepo
=
repo
;
mInstall
=
install
&&
Shell
.
rootAccess
();
mFile
=
new
File
(
Const
.
EXTERNAL_PATH
,
repo
.
getDownloadFilename
());
}
private
void
removeTopFolder
(
File
input
,
File
output
)
throws
IOException
{
JarEntry
entry
;
try
(
JarInputStream
in
=
new
JarInputStream
(
new
BufferedInputStream
(
new
FileInputStream
(
input
)));
JarOutputStream
out
=
new
JarOutputStream
(
new
BufferedOutputStream
(
new
FileOutputStream
(
output
)))
)
{
String
path
;
while
((
entry
=
in
.
getNextJarEntry
())
!=
null
)
{
// Remove the top directory from the path
path
=
entry
.
getName
().
substring
(
entry
.
getName
().
indexOf
(
"/"
)
+
1
);
// If it's the top folder, ignore it
if
(
path
.
isEmpty
())
{
continue
;
}
// Don't include placeholder
if
(
path
.
equals
(
"system/placeholder"
))
{
continue
;
}
out
.
putNextEntry
(
new
JarEntry
(
path
));
ShellUtils
.
pump
(
in
,
out
);
}
}
}
@Override
protected
BaseActivity
getActivity
()
{
return
(
BaseActivity
)
super
.
getActivity
();
}
@Override
protected
void
onPreExecute
()
{
BaseActivity
activity
=
getActivity
();
mFile
.
getParentFile
().
mkdirs
();
progressDialog
=
ProgressDialog
.
show
(
activity
,
activity
.
getString
(
R
.
string
.
zip_download_title
),
activity
.
getString
(
R
.
string
.
zip_download_msg
,
0
));
}
@Override
protected
Boolean
doInBackground
(
Void
...
params
)
{
BaseActivity
activity
=
getActivity
();
if
(
activity
==
null
)
return
null
;
try
{
// Request zip from Internet
HttpURLConnection
conn
=
WebService
.
mustRequest
(
mRepo
.
getZipUrl
());
total
=
conn
.
getContentLength
();
// Temp files
File
temp1
=
new
File
(
activity
.
getCacheDir
(),
"1.zip"
);
File
temp2
=
new
File
(
temp1
.
getParentFile
(),
"2.zip"
);
temp1
.
getParentFile
().
mkdir
();
// First upgrade the zip, Web -> temp1
try
(
InputStream
in
=
new
BufferedInputStream
(
new
ProgressInputStream
(
conn
.
getInputStream
()));
OutputStream
out
=
new
BufferedOutputStream
(
new
FileOutputStream
(
temp1
))
)
{
ShellUtils
.
pump
(
in
,
out
);
in
.
close
();
}
conn
.
disconnect
();
Data
.
mainHandler
.
post
(()
->
{
progressDialog
.
setTitle
(
R
.
string
.
zip_process_title
);
progressDialog
.
setMessage
(
getActivity
().
getString
(
R
.
string
.
zip_process_msg
));
});
// First remove top folder in Github source zip, temp1 -> temp2
removeTopFolder
(
temp1
,
temp2
);
// Then sign the zip
ZipUtils
.
signZip
(
temp2
,
mFile
);
// Delete temp files
temp1
.
delete
();
temp2
.
delete
();
return
true
;
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
return
false
;
}
}
@Override
protected
void
onPostExecute
(
Boolean
result
)
{
BaseActivity
activity
=
getActivity
();
if
(
activity
==
null
)
return
;
progressDialog
.
dismiss
();
if
(
result
)
{
Uri
uri
=
Uri
.
fromFile
(
mFile
);
if
(
mInstall
)
{
Intent
intent
=
new
Intent
(
activity
,
Data
.
classMap
.
get
(
FlashActivity
.
class
));
intent
.
setData
(
uri
).
putExtra
(
Const
.
Key
.
FLASH_ACTION
,
Const
.
Value
.
FLASH_ZIP
);
activity
.
startActivity
(
intent
);
}
else
{
SnackbarMaker
.
showUri
(
activity
,
uri
);
}
}
else
{
Utils
.
toast
(
R
.
string
.
process_error
,
Toast
.
LENGTH_LONG
);
}
super
.
onPostExecute
(
result
);
}
@Override
public
void
exec
(
Void
...
voids
)
{
getActivity
().
runWithPermission
(
new
String
[]
{
Manifest
.
permission
.
WRITE_EXTERNAL_STORAGE
},
super
::
exec
);
}
private
class
ProgressInputStream
extends
FilterInputStream
{
ProgressInputStream
(
InputStream
in
)
{
super
(
in
);
}
private
void
updateDlProgress
(
int
step
)
{
progress
+=
step
;
progressDialog
.
setMessage
(
getActivity
().
getString
(
R
.
string
.
zip_download_msg
,
(
int
)
(
100
*
(
double
)
progress
/
total
+
0.5
)));
}
@Override
public
synchronized
int
read
()
throws
IOException
{
int
b
=
super
.
read
();
if
(
b
>
0
)
{
Data
.
mainHandler
.
post
(()
->
updateDlProgress
(
1
));
}
return
b
;
}
@Override
public
int
read
(
@NonNull
byte
[]
b
)
throws
IOException
{
return
read
(
b
,
0
,
b
.
length
);
}
@Override
public
synchronized
int
read
(
@NonNull
byte
[]
b
,
int
off
,
int
len
)
throws
IOException
{
int
read
=
super
.
read
(
b
,
off
,
len
);
if
(
read
>
0
)
{
Data
.
mainHandler
.
post
(()
->
updateDlProgress
(
read
));
}
return
read
;
}
}
}
app/src/full/java/com/topjohnwu/magisk/components/NotificationProgress.java
View file @
3af66b72
...
...
@@ -55,6 +55,13 @@ public class NotificationProgress implements DownloadProgressListener {
update
();
}
public
void
dlFail
()
{
builder
.
setProgress
(
0
,
0
,
false
)
.
setContentText
(
Data
.
MM
().
getString
(
R
.
string
.
download_file_error
))
.
setSmallIcon
(
R
.
drawable
.
ic_cancel
);
update
();
}
public
void
dismiss
()
{
mgr
.
cancel
(
Const
.
ID
.
DOWNLOAD_PROGRESS_ID
);
}
...
...
app/src/full/res/values/strings.xml
View file @
3af66b72
...
...
@@ -74,6 +74,7 @@
<string
name=
"update_channel"
>
Magisk Updates
</string>
<string
name=
"progress_channel"
>
Progress Notifications
</string>
<string
name=
"download_complete"
>
Download complete
</string>
<string
name=
"download_file_error"
>
Error downloading file
</string>
<string
name=
"magisk_update_title"
>
New Magisk Update Available!
</string>
<string
name=
"manager_update_title"
>
New Magisk Manager Update Available!
</string>
...
...
@@ -123,7 +124,6 @@
<string
name=
"env_fix_msg"
>
Your device needs additional setup for Magisk to work properly. It will download the Magisk setup zip, do you want to proceed now?
</string>
<string
name=
"setup_title"
>
Additional Setup
</string>
<string
name=
"setup_msg"
>
Running environment setup…
</string>
<string
name=
"download_file_error"
>
Error downloading file
</string>
<string
name=
"downloading_toast"
>
Downloading %1$s
</string>
<string
name=
"no_rw_storage"
>
This feature will not work without permission to write external storage.
</string>
...
...
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