Compare commits

...

114 commits
0.3.3 ... main

Author SHA1 Message Date
3dcc9912d3 new release 2024-08-20 10:05:53 -07:00
2434b38117 update readme 2024-08-10 11:43:35 -07:00
ed11ab882b test release 2024-08-10 11:06:55 -07:00
5742255b5b test release 2024-08-10 11:03:44 -07:00
e668cd4b46 update images 2024-08-10 07:29:36 -07:00
732f230ee6 deprecation 2024-01-29 08:41:50 -07:00
dbfcb1e9f1 new release 2023-12-07 05:43:46 -07:00
abaa65516e update readme 2023-10-18 16:49:03 -07:00
ac1184b164 update readme 2023-10-18 16:44:13 -07:00
0e1391e89d new release 2023-07-28 04:48:26 -07:00
f84b96cfc6 new release 2023-07-27 15:32:26 -07:00
532b05dde2 new release 2023-06-25 19:11:06 -07:00
5eb44e6bc1 new release 2023-04-21 07:16:32 -07:00
319019cd46 new release 2023-03-08 11:38:01 -07:00
fc3c1c98b0 new release 2023-03-03 13:34:54 -07:00
7f627b5e4c new release 2023-03-03 13:33:24 -07:00
98cd78a1ec m3u playlists 2023-03-03 13:17:47 -07:00
684c1e36cc upgrade exoplayer 2023-03-03 13:09:09 -07:00
13004d2bd3 new release 2023-02-28 12:02:50 -07:00
448dfc3ab7 bug fix 2023-02-22 12:36:04 -07:00
175462a344 upgrade dependencies 2023-02-22 09:55:45 -07:00
0083f34a82 new release 2023-02-06 09:16:13 -07:00
791c747832 new release 2023-02-06 09:15:46 -07:00
7df9789241 add compatibility with api 21 2023-02-03 18:59:08 -07:00
b3e65a8fcf new release 2023-02-03 16:49:23 -07:00
55b5113fd3 load public media from cache 2023-02-03 16:24:18 -07:00
7aa05c783a check policy per object 2023-02-03 15:52:10 -07:00
ce28a53de7 move cache location 2023-02-03 14:03:39 -07:00
6c83a96491 new release 2023-01-24 07:03:53 -07:00
4196c2f6e8 new release 2023-01-24 07:02:15 -07:00
7be7d93b50 new release 2023-01-24 06:23:21 -07:00
303f0469d7 new release 2023-01-22 19:39:12 -07:00
31537846da set object policy 2023-01-22 19:16:09 -07:00
1b1dc39482 get object policy 2023-01-22 18:40:46 -07:00
ec78f304ee object policy 2023-01-22 14:05:14 -07:00
8a3a2d62db first step 2023-01-22 12:31:25 -07:00
b76890e320 new release 2023-01-22 09:03:57 -07:00
4841fbcf5d new release 2023-01-22 07:18:58 -07:00
81693d37db new release 2023-01-22 07:16:09 -07:00
0fe7f7a79b set policy 2023-01-22 06:11:28 -07:00
16fca27422 check permissions 2023-01-22 05:36:20 -07:00
960707d4e0 get bucket policy 2023-01-21 20:26:37 -07:00
9ee818e47a first step 2023-01-21 18:54:15 -07:00
95bba1f473 new release 2023-01-21 14:48:23 -07:00
b3c1953a3b ui fix 2023-01-21 13:00:06 -07:00
77f4a25a32 update readme 2023-01-11 07:25:14 -07:00
920c66f71d new release 2023-01-10 13:26:18 -07:00
24c5d229d2 new release 2023-01-10 13:21:34 -07:00
b167ea24d8 new release 2023-01-10 13:10:12 -07:00
d033dfbb3b new release 2023-01-09 18:44:13 -07:00
8f2a33514b new release 2023-01-09 16:03:51 -07:00
46acbb13fb new release 2023-01-09 11:47:09 -07:00
aa95967473 new release 2023-01-08 08:36:34 -07:00
7566c924fd playback fix 2023-01-07 19:24:38 -07:00
bfdf1b1527 update description 2023-01-07 16:28:40 -07:00
1f52b6048b new release 2023-01-07 11:24:23 -07:00
eddc353a82 code cleanup 2023-01-07 10:16:01 -07:00
19cc86b45e region fix 2023-01-07 09:47:35 -07:00
c30eb36854 fix cache 2023-01-06 11:48:30 -07:00
cd4d17d497 new release 2023-01-04 12:33:05 -07:00
13e6664569 new release 2023-01-03 10:52:13 -07:00
6f6f9207cc new release 2023-01-03 10:51:07 -07:00
6240ad14db new release 2023-01-02 17:40:31 -07:00
f093972779 new release 2023-01-02 17:36:15 -07:00
7223d9333f copy links 2023-01-02 17:03:58 -07:00
51b2f1f783 new release 2023-01-02 14:02:11 -07:00
cd0b72a887 preferences 2023-01-02 13:49:20 -07:00
48fa899a97 play queue 2023-01-02 12:07:30 -07:00
c3cf489510 get links 2023-01-02 11:52:55 -07:00
3c8d41e05e first step 2023-01-02 10:01:59 -07:00
3e67badeb2 new release 2023-01-01 14:43:38 -07:00
803297b2d6 add library 2023-01-01 09:16:33 -07:00
52d5106ee3 update description 2022-12-31 19:23:57 -07:00
79806b9bb2 new release 2022-12-31 11:40:12 -07:00
0177c5d7b4 new release 2022-12-31 11:36:38 -07:00
5dd93a01c5 new release 2022-12-31 10:16:44 -07:00
697d2b8b07 new release 2022-12-30 21:50:14 -07:00
7dff026db1 new release 2022-12-30 20:55:02 -07:00
6e1f171f7b calculating folder size 2022-12-30 20:13:34 -07:00
4b0651c9c6 file list working 2022-12-30 19:51:53 -07:00
99049977c1 file list implemented 2022-12-30 18:44:42 -07:00
69dacae861 get subpath 2022-12-30 17:37:47 -07:00
9c45c4aaf0 first step 2022-12-30 10:24:42 -07:00
881eadc957 new release 2022-12-29 19:47:01 -07:00
a3d90da346 new release 2022-12-29 19:28:14 -07:00
7f61ec6ea5 fix strings 2022-12-29 17:21:33 -07:00
8a0642e0fd new release 2022-12-29 11:26:27 -07:00
d49fb984e0 new release 2022-12-29 10:54:21 -07:00
44c28dc748 folder download 2022-12-29 09:16:15 -07:00
c1342adcee batch download 2022-12-29 07:44:41 -07:00
a8b6a2d019 folder write 2022-12-28 20:45:40 -07:00
b73ec1e44b minor changes 2022-12-28 19:22:17 -07:00
eb3d82ac05 add folder prompt 2022-12-28 18:00:23 -07:00
e06bba66de new release 2022-12-27 18:22:54 -07:00
0e62408f1d new release 2022-12-27 18:16:39 -07:00
1ac83482f4 new release 2022-12-26 17:55:34 -07:00
5b3be1b8a9 new release 2022-12-26 16:17:42 -07:00
d7811c8914 new release 2022-12-26 16:15:57 -07:00
7521067d3f fix PiP 2022-12-26 15:51:16 -07:00
53afbd0acc new release 2022-12-26 11:40:39 -07:00
d0aa5190f9 fix freeform 2022-12-26 11:28:01 -07:00
458b622139 set cors 2022-12-26 11:04:33 -07:00
b2de50b544 buttons 2022-12-26 08:13:13 -07:00
8343a54595 hostname 2022-12-26 07:42:51 -07:00
76f6a39915 get cors policy 2022-12-25 21:37:41 -07:00
c2289a3f83 first step 2022-12-25 18:54:52 -07:00
7da7a1b5ec new release 2022-12-23 13:53:03 -07:00
5e7297ebb1 new release 2022-12-23 13:27:18 -07:00
cb50a01854 style access working 2022-12-23 11:53:23 -07:00
ddffa7ccfe style access selection 2022-12-23 11:02:50 -07:00
424caf8b87 new release 2022-12-22 07:29:10 -07:00
0e069bef1e ui fix 2022-12-22 06:41:24 -07:00
6526002a9b new release 2022-12-21 11:06:03 -07:00
4f272ae199 new release 2022-12-20 19:47:23 -07:00
100 changed files with 3700 additions and 1069 deletions

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="11" />
<bytecodeTargetLevel target="17" />
</component>
</project>

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="deploymentTargetSelector">
<selectionStates>
<SelectionState runConfigName="app">
<option name="selectionMode" value="DROPDOWN" />
</SelectionState>
</selectionStates>
</component>
</project>

View file

@ -4,15 +4,26 @@
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="testRunner" value="GRADLE" />
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalProjectPath" value="/data/2/asgardius/StudioProjects/s3manager" />
<option name="gradleJvm" value="#GRADLE_LOCAL_JAVA_HOME" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
<option value="/data/2/asgardius/StudioProjects/s3manager" />
<option value="/data/2/asgardius/StudioProjects/s3manager/app" />
</set>
</option>
<option name="resolveExternalAnnotations" value="false" />
</GradleProjectSettings>
<GradleProjectSettings>
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="#GRADLE_LOCAL_JAVA_HOME" />
<option name="modules">
<set>
<option value="/data/2/asgardius/StudioProjects/s3manager" />
<option value="/data/2/asgardius/StudioProjects/s3manager/app" />
</set>
</option>
<option name="resolveExternalAnnotations" value="false" />
</GradleProjectSettings>
</option>
</component>

11
.idea/migrations.xml Normal file
View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectMigrations">
<option name="MigrateToGradleLocalJavaHome">
<set>
<option value="/data/2/asgardius/StudioProjects/s3manager" />
<option value="$PROJECT_DIR$" />
</set>
</option>
</component>
</project>

View file

@ -1,4 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DesignSurface">
<option name="filePathToZoomLevelMap">
@ -28,7 +27,8 @@
</map>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="Android Studio default JDK" project-jdk-type="JavaSDK">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">

252
.idea/other.xml Normal file
View file

@ -0,0 +1,252 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="direct_access_persist.xml">
<option name="deviceSelectionList">
<list>
<PersistentDeviceSelectionData>
<option name="api" value="27" />
<option name="brand" value="DOCOMO" />
<option name="codename" value="F01L" />
<option name="id" value="F01L" />
<option name="manufacturer" value="FUJITSU" />
<option name="name" value="F-01L" />
<option name="screenDensity" value="360" />
<option name="screenX" value="720" />
<option name="screenY" value="1280" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="28" />
<option name="brand" value="DOCOMO" />
<option name="codename" value="SH-01L" />
<option name="id" value="SH-01L" />
<option name="manufacturer" value="SHARP" />
<option name="name" value="AQUOS sense2 SH-01L" />
<option name="screenDensity" value="480" />
<option name="screenX" value="1080" />
<option name="screenY" value="2160" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="31" />
<option name="brand" value="samsung" />
<option name="codename" value="a51" />
<option name="id" value="a51" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy A51" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="akita" />
<option name="id" value="akita" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 8a" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="samsung" />
<option name="codename" value="b0q" />
<option name="id" value="b0q" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy S22 Ultra" />
<option name="screenDensity" value="600" />
<option name="screenX" value="1440" />
<option name="screenY" value="3088" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="32" />
<option name="brand" value="google" />
<option name="codename" value="bluejay" />
<option name="id" value="bluejay" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 6a" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="29" />
<option name="brand" value="samsung" />
<option name="codename" value="crownqlteue" />
<option name="id" value="crownqlteue" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy Note9" />
<option name="screenDensity" value="420" />
<option name="screenX" value="2220" />
<option name="screenY" value="1080" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="dm3q" />
<option name="id" value="dm3q" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy S23 Ultra" />
<option name="screenDensity" value="600" />
<option name="screenX" value="1440" />
<option name="screenY" value="3088" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="google" />
<option name="codename" value="felix" />
<option name="id" value="felix" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel Fold" />
<option name="screenDensity" value="420" />
<option name="screenX" value="2208" />
<option name="screenY" value="1840" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="google" />
<option name="codename" value="felix_camera" />
<option name="id" value="felix_camera" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel Fold (Camera-enabled)" />
<option name="screenDensity" value="420" />
<option name="screenX" value="2208" />
<option name="screenY" value="1840" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="samsung" />
<option name="codename" value="gts8uwifi" />
<option name="id" value="gts8uwifi" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy Tab S8 Ultra" />
<option name="screenDensity" value="320" />
<option name="screenX" value="1848" />
<option name="screenY" value="2960" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="husky" />
<option name="id" value="husky" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 8 Pro" />
<option name="screenDensity" value="390" />
<option name="screenX" value="1008" />
<option name="screenY" value="2244" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="30" />
<option name="brand" value="motorola" />
<option name="codename" value="java" />
<option name="id" value="java" />
<option name="manufacturer" value="Motorola" />
<option name="name" value="G20" />
<option name="screenDensity" value="280" />
<option name="screenX" value="720" />
<option name="screenY" value="1600" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="google" />
<option name="codename" value="lynx" />
<option name="id" value="lynx" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 7a" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="31" />
<option name="brand" value="google" />
<option name="codename" value="oriole" />
<option name="id" value="oriole" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 6" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="google" />
<option name="codename" value="panther" />
<option name="id" value="panther" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 7" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="q5q" />
<option name="id" value="q5q" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy Z Fold5" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1812" />
<option name="screenY" value="2176" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="30" />
<option name="brand" value="google" />
<option name="codename" value="r11" />
<option name="id" value="r11" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel Watch" />
<option name="screenDensity" value="320" />
<option name="screenX" value="384" />
<option name="screenY" value="384" />
<option name="type" value="WEAR_OS" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="30" />
<option name="brand" value="google" />
<option name="codename" value="redfin" />
<option name="id" value="redfin" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 5" />
<option name="screenDensity" value="440" />
<option name="screenX" value="1080" />
<option name="screenY" value="2340" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="shiba" />
<option name="id" value="shiba" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 8" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="google" />
<option name="codename" value="tangorpro" />
<option name="id" value="tangorpro" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel Tablet" />
<option name="screenDensity" value="320" />
<option name="screenX" value="1600" />
<option name="screenY" value="2560" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="29" />
<option name="brand" value="samsung" />
<option name="codename" value="x1q" />
<option name="id" value="x1q" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy S20" />
<option name="screenDensity" value="480" />
<option name="screenX" value="1440" />
<option name="screenY" value="3200" />
</PersistentDeviceSelectionData>
</list>
</option>
</component>
</project>

7
.idea/vcs.xml Normal file
View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
<mapping directory="/data/2/asgardius/StudioProjects/s3manager" vcs="Git" />
</component>
</project>

View file

@ -1,13 +1,11 @@
# s3manager
# Asgardius S3 Manager
File Explorer to manage servers compatible with S3 Object Storage Protocol
Current feature list
* Audio and Video playback (opus, ogg, oga, mp3, m4a, flac, mka, mkv, mp4, m4v, webm)
* Picture preview (jpg, jpeg, png, gif)
* Picture preview (jpg, jpeg, png, gif, webp)
* Plain text file preview (txt, md)
* Webpage viewer (htm, html)
* Multiple account support
@ -18,10 +16,15 @@ Current feature list
* Delete folders
* File upload
* File download
* Download folder content
* Upload folder content
* pdf file reader using user provided pdf.js server
* file sharing links
* get object info
* get bucket info
* Set CORS policy
* Set bucket as public or private
* Set object as public or private
Planned feature list
@ -31,13 +34,9 @@ This app is a work in progress, so it have some bugs that need to be fixed
You need to setup a pdf.js server to use pdf viewer. Just download latest version from official website and upload to any web server with ssl on same root domain than S3 server (can be same subdomain or a different one). Then set url to pdfjs root folder like https://example.com/pdfjs-dist
[<img src="app-store-badges/fdroid.png"
alt="Get it on F-Droid"
height="80">](https://f-droid.org/packages/asgardius.page.s3manager/)
[<img src="app-store-badges/play-store.png"
alt="Get it on Google Play"
height="80">](https://play.google.com/store/apps/details?id=asgardius.page.s3manager)
height="80">](https://play.google.com/store/apps/details?id=asgardius.page.s3managermk2)
F-droid release may take a few days to get updated [More info here](https://www.f-droid.org/en/docs/FAQ_-_App_Developers/#ive-published-a-new-release-why-is-it-not-in-the-repository)
@ -45,6 +44,8 @@ F-droid release may take a few days to get updated [More info here](https://www.
You can get help at https://forum.asgardius.company/t/s3-manager
You can find app documentation at https://wiki-en.asgardius.company/index.php?title=Asgardius_S3_Manager_Documentation (english) or https://wiki-es.asgardius.company/index.php?title=Documentacion_Asgardius_S3_Manager (spanish)
Supported languages
* English
@ -59,11 +60,16 @@ Knnown issues
Known supported providers
* Amazon Web Services
* Scaleway Elements (partial)
* Oracle Cloud (partial)
* Wasabi Cloud
* MinIO
* Scaleway Elements
* Wasabi Cloud (Provider broke access control intentionally since March 13 2023)
* Backblaze B2
* Cloudflare R2 (partial)
* MinIO **
* Garage **
Known not supported providers
* Google Cloud
* Google Cloud (Not compatible with S3v4)
* Oracle Cloud (compatibility issues with S3v4)
** Extra steps required (read documentation)

View file

@ -6,11 +6,11 @@ android {
compileSdk 33
defaultConfig {
applicationId "asgardius.page.s3manager"
minSdk 23
targetSdk 33
versionCode 42
versionName "0.3.3"
applicationId "asgardius.page.s3managermk2"
minSdk 21
targetSdk 34
versionCode 2
versionName "0.11.1"
setProperty("archivesBaseName", "s3-manager-$versionName")
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@ -29,23 +29,25 @@ android {
buildFeatures {
viewBinding true
}
namespace 'asgardius.page.s3managermk2'
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
def exoplayer_version = "2.18.1"
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.8.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
def exoplayer_version = "2.19.1"
implementation "com.google.android.exoplayer:exoplayer:$exoplayer_version"
implementation "com.google.android.exoplayer:extension-mediasession:$exoplayer_version"
implementation 'androidx.recyclerview:recyclerview:1.2.1'
implementation"com.otaliastudios:zoomlayout:1.9.0"
// BEGIN AWS DEPENDENCIES
def aws_version = "2.58.0"
def aws_version = "2.76.1"
implementation "com.amazonaws:aws-android-sdk-s3:$aws_version"
implementation ("com.amazonaws:aws-android-sdk-mobile-client:$aws_version") { transitive = true }
// END AWS DEPENDENCIES
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
}

View file

@ -1,4 +1,4 @@
package asgardius.page.s3manager;
package asgardius.page.s3managermk2;
import android.content.Context;

View file

@ -1,14 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="asgardius.page.s3manager">
android:installLocation="auto"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission
android:name="android.permission.READ_PHONE_STATE"
tools:node="remove" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application
android:allowBackup="true"
@ -19,12 +18,27 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.AsgardiusS3Manager"
tools:targetApi="31">
tools:targetApi="31"
android:usesCleartextTraffic="true" >
<activity
android:name=".ObjectPolicy"
android:exported="false" />
<activity
android:name=".BucketPolicy"
android:exported="false" />
<activity
android:name=".CorsConfig"
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize|screenLayout|uiMode|keyboardHidden"
android:exported="false" >
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>
<activity
android:name=".Settings"
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize|screenLayout|uiMode|keyboardHidden"
android:exported="false"
android:label="@string/settings">
android:label="@string/settings" >
<meta-data
android:name="android.app.lib_name"
android:value="" />
@ -32,7 +46,7 @@
<activity
android:name=".ObjectInfo"
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize|screenLayout|uiMode|keyboardHidden"
android:exported="false">
android:exported="false" >
<meta-data
android:name="android.app.lib_name"
android:value="" />
@ -44,8 +58,8 @@
<activity
android:name=".Downloader"
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize|screenLayout|uiMode|keyboardHidden"
android:exported="false"
android:label="@string/download_file" />
android:documentLaunchMode="always"
android:exported="false" />
<activity
android:name=".CreateBucket"
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize|screenLayout|uiMode|keyboardHidden"
@ -54,19 +68,23 @@
<activity
android:name=".Uploader"
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize|screenLayout|uiMode|keyboardHidden"
android:exported="false"
android:label="@string/upload_button" />
android:documentLaunchMode="always"
android:exported="false" />
<activity
android:name=".ImageViewer"
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize|screenLayout|uiMode|keyboardHidden"
android:exported="false" />
android:exported="false"
android:documentLaunchMode="always"
android:hardwareAccelerated="false" />
<activity
android:name=".TextViewer"
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize|screenLayout|uiMode|keyboardHidden"
android:documentLaunchMode="always"
android:exported="false" />
<activity
android:name=".WebBrowser"
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize|screenLayout|uiMode|keyboardHidden"
android:documentLaunchMode="always"
android:exported="false" />
<activity
android:name=".AccountAdd"
@ -87,16 +105,16 @@
android:label="@string/bucket_list" />
<activity
android:name=".VideoPlayer"
android:resizeableActivity="true"
android:supportsPictureInPicture="true"
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize|screenLayout|uiMode|keyboardHidden"
android:exported="false"
android:launchMode="singleTask"
android:theme="@style/Theme.AsgardiusS3Manager.NoActionBar" />
android:resizeableActivity="true"
android:documentLaunchMode="always"
android:supportsPictureInPicture="true" />
<activity
android:name=".MainActivity"
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize|screenLayout|uiMode|keyboardHidden"
android:exported="true">
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />

View file

@ -9,15 +9,16 @@
<H3>Created by Page Asgardius</H3>
<H3>Libraries used in this app</H3>
<ul>
<li>Amazon Web Services SDK 2.58.0</li>
<li>ExoPlayer 2.18.1</li>
<li>Amazon Web Services SDK 2.76.1</li>
<li>ExoPlayer 2.19.1</li>
<li>ZoomLayout 1.9.0</li>
<li>Adwaita Icon Theme for GNOME 43</li>
<li>pdf.js</li>
</ul>
<H3>This software released under GNU General Public License 3</H3>
<p>You can find source code at https://patrice.asgardius.company/gitea/asgardius/s3manager
<p>You can find source code at https://git.asgardius.company/asgardius/s3manager
<br>
You need to setup a pdf.js server to use pdf viewer. Just download latest version from official website and upload to any web server with ssl on same root domain than S3 server (can be same subdomain or a different one in some cases). Then set url to pdfjs root folder like https://example.com/pdfjs-dist
You need to setup a pdf.js server to use pdf viewer. You can use https://office.asgardius.company/pdfjs or setup your own.
<br>
You can find technical support on official forum https://forum.asgardius.company/t/s3-manager</p>
</Body>

View file

@ -1,80 +0,0 @@
package asgardius.page.s3manager;
import androidx.appcompat.app.AppCompatActivity;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.Toast;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.stream.Collectors;
public class ImageViewer extends AppCompatActivity {
String videoURL;
ImageView iv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_image_viewer);
final ProgressBar simpleProgressBar = (ProgressBar) findViewById(R.id.simpleProgressBar);
iv = (ImageView) findViewById(R.id.imageViewer);
//System.out.println(videoURL);
Thread imgread = new Thread(new Runnable() {
@Override
public void run() {
try {
//Your code goes here
videoURL = getIntent().getStringExtra("video_url");
URL thumb_u = new URL(videoURL);
Drawable thumb_d = Drawable.createFromStream(thumb_u.openStream(), "src");
runOnUiThread(new Runnable() {
@Override
public void run() {
simpleProgressBar.setVisibility(View.INVISIBLE);
iv.setImageDrawable(thumb_d);
}
});
} catch (Exception e) {
e.printStackTrace();
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.media_list_fail), Toast.LENGTH_SHORT).show();
finish();
}
});
finish();
}
}
});
imgread.start();
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
View decorView = getWindow().getDecorView();
decorView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}
}

View file

@ -1,169 +0,0 @@
package asgardius.page.s3manager;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.regions.Region;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.S3ClientOptions;
import com.amazonaws.services.s3.model.GeneratePresignedUrlRequest;
import java.net.URL;
import java.util.Calendar;
import java.util.Date;
public class Share extends AppCompatActivity {
String username, password, endpoint, bucket, object, location;
boolean mediafile;
Region region;
S3ClientOptions s3ClientOptions;
AWSCredentials myCredentials;
AmazonS3 s3client;
Calendar mycal;
EditText datepick, monthpick, yearpick, hourpick, minutepick;
int date, month, year, hour, minute;
Button share, external;
GeneratePresignedUrlRequest request;
Date expiration;
URL objectURL;
int videotime;
public static String URLify(String str) {
str = str.trim();
int length = str.length();
int trueL = length;
if(str.contains(" ")) {
for(int i = 0; i < length; i++) {
if(str.charAt(i) == ' ') {
trueL = trueL + 2;
}
}
char[] oldArr = str.toCharArray();
char[] newArr = new char[trueL];
int x = 0;
for(int i = 0; i < length; i++) {
if(oldArr[i] == ' ') {
newArr[x] = '%';
newArr[x+1] = '2';
newArr[x+2] = '0';
x += 3;
} else {
newArr[x] = oldArr[i];
x++;
}
}
str = new String(newArr, 0, trueL);
}
return str;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_share);
mycal = Calendar.getInstance();
datepick = (EditText)findViewById(R.id.Date);
monthpick = (EditText)findViewById(R.id.Month);
yearpick = (EditText)findViewById(R.id.Year);
hourpick = (EditText)findViewById(R.id.Hour);
minutepick = (EditText)findViewById(R.id.Minute);
share = (Button)findViewById(R.id.share);
external = (Button)findViewById(R.id.open_in);
endpoint = getIntent().getStringExtra("endpoint");
username = getIntent().getStringExtra("username");
password = getIntent().getStringExtra("password");
bucket = getIntent().getStringExtra("bucket");
location = getIntent().getStringExtra("region");
object = getIntent().getStringExtra("object");
mediafile = getIntent().getBooleanExtra("mediafile", false);
videotime = getIntent().getIntExtra("videotime", 1);
region = Region.getRegion(location);
s3ClientOptions = S3ClientOptions.builder().build();
myCredentials = new BasicAWSCredentials(username, password);
try {
s3client = new AmazonS3Client(myCredentials, region);
} catch (Exception e) {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.media_list_fail), Toast.LENGTH_SHORT).show();
}
s3client.setEndpoint(endpoint);
if (!endpoint.contains(getResources().getString(R.string.aws_endpoint))) {
s3ClientOptions.setPathStyleAccess(true);
}
s3client.setS3ClientOptions(s3ClientOptions);
share.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
//buttonaction
try {
if (datepick.getText().toString().equals("") || monthpick.getText().toString().equals("") ||
yearpick.getText().toString().equals("") || hourpick.getText().toString().equals("") ||
minutepick.getText().toString().equals("")) {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.null_expiration_date), Toast.LENGTH_SHORT).show();
} else {
date = Integer.parseInt(datepick.getText().toString());
month = Integer.parseInt(monthpick.getText().toString());
year = Integer.parseInt(yearpick.getText().toString());
hour = Integer.parseInt(hourpick.getText().toString());
minute = Integer.parseInt(minutepick.getText().toString());
mycal.set(Calendar.YEAR, year);
mycal.set(Calendar.MONTH, month-1);
mycal.set(Calendar.DATE, date);
mycal.set(Calendar.HOUR, hour);
mycal.set(Calendar.MINUTE, minute);
mycal.set(Calendar.SECOND, 0);
expiration = mycal.getTime();
//System.out.println(expiration);
request = new GeneratePresignedUrlRequest(bucket, object).withExpiration(expiration);
objectURL = s3client.generatePresignedUrl(request);
//System.out.println(URLify(objectURL.toString()));
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
shareIntent.putExtra(Intent.EXTRA_TEXT, URLify(objectURL.toString()));
startActivity(Intent.createChooser(shareIntent, "choose one"));
}
} catch (Exception e) {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.invalid_expiration_date), Toast.LENGTH_SHORT).show();
}
}
});
external.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
//buttonaction
try {
if (mediafile) {
expiration = new Date();
mycal.setTime(expiration);
//System.out.println("today is " + mycal.getTime());
mycal.add(Calendar.HOUR, videotime);
//System.out.println("Expiration date: " + mycal.getTime());
expiration = mycal.getTime();
request = new GeneratePresignedUrlRequest(bucket, object).withExpiration(expiration);
} else {
request = new GeneratePresignedUrlRequest(bucket, object);
}
objectURL = s3client.generatePresignedUrl(request);
//System.out.println(URLify(objectURL.toString()));
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
shareIntent.putExtra(Intent.EXTRA_TEXT, URLify(objectURL.toString()));
startActivity(Intent.createChooser(shareIntent, "choose one"));
} catch (Exception e) {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.invalid_expiration_date), Toast.LENGTH_SHORT).show();
}
}
});
}
}

View file

@ -1,8 +1,4 @@
package asgardius.page.s3manager;
import static com.amazonaws.regions.Regions.US_EAST_1;
import androidx.appcompat.app.AppCompatActivity;
package asgardius.page.s3managermk2;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
@ -12,6 +8,8 @@ import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.regions.Region;
@ -19,13 +17,14 @@ import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.S3ClientOptions;
import com.amazonaws.services.s3.model.Bucket;
import com.google.android.material.switchmaterial.SwitchMaterial;
import java.util.ArrayList;
import java.util.List;
public class AccountAdd extends AppCompatActivity {
EditText aapick, aupick, appick, aepick, arpick, pdfpick;
String alias, username, password, endpoint, id, location, pdfendpoint;
SwitchMaterial pathstyle;
String alias, username, password, endpoint, id, location, pdfendpoint, style;
AWSCredentials myCredentials;
AmazonS3 s3client;
Region region;
@ -41,6 +40,7 @@ public class AccountAdd extends AppCompatActivity {
arpick = (EditText)findViewById(R.id.region);
aupick = (EditText)findViewById(R.id.username);
appick = (EditText)findViewById(R.id.password);
pathstyle = (SwitchMaterial) findViewById(R.id.pathstyle);
Button register = (Button)findViewById(R.id.addaccount);
Button accounttest = (Button)findViewById(R.id.testaccount);
edit = getIntent().getBooleanExtra("edit", false);
@ -53,6 +53,11 @@ public class AccountAdd extends AppCompatActivity {
password = getIntent().getStringExtra("password");
location = getIntent().getStringExtra("region");
pdfendpoint = getIntent().getStringExtra("pdfendpoint");
if (getIntent().getBooleanExtra("style", false)) {
pathstyle.setChecked(true);
} else {
pathstyle.setChecked(false);
}
aapick.setText(id);
aepick.setText(endpoint);
//aapick.setEnabled(false);
@ -76,12 +81,12 @@ public class AccountAdd extends AppCompatActivity {
location = arpick.getText().toString();
username = aupick.getText().toString();
password = appick.getText().toString();
MyDbHelper dbHelper = new MyDbHelper(AccountAdd.this);
if (alias.equals("") && endpoint.equals("") && username.equals(getResources().getString(R.string.access_key))) {
endpoint = getResources().getString(R.string.endpoint_url);
alias = "Google Test";
pdfendpoint = getResources().getString(R.string.pdf_reader);
if (pathstyle.isChecked()) {
style = "1";
} else {
style = "0";
}
MyDbHelper dbHelper = new MyDbHelper(AccountAdd.this);
SQLiteDatabase db = dbHelper.getWritableDatabase();
if (alias.equals("") || endpoint.equals("") || username.equals("") || password.equals("")) {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.accountadd_null), Toast.LENGTH_SHORT).show();
@ -95,11 +100,14 @@ public class AccountAdd extends AppCompatActivity {
if (location.equals("")) {
location = "us-east-1";
}
if(endpoint.endsWith("/")) {
endpoint = endpoint.substring(0, endpoint.length()-1);
}
if (edit) {
db.execSQL("UPDATE account SET id=\""+alias+"\", endpoint=\""+endpoint+"\", username=\""+username+"\", password=\""+password+"\", region=\""+location+"\", pdfendpoint=\""+pdfendpoint+"\" WHERE id=\""+id+"\"");
db.execSQL("UPDATE account SET id=\""+alias+"\", endpoint=\""+endpoint+"\", username=\""+username+"\", password=\""+password+"\", region=\""+location+"\", pdfendpoint=\""+pdfendpoint+"\", style=\""+style+"\" WHERE id=\""+id+"\"");
Toast.makeText(getApplicationContext(),getResources().getString(R.string.accountsave_success), Toast.LENGTH_SHORT).show();
} else {
db.execSQL("INSERT INTO account VALUES (\""+alias+"\", \""+endpoint+"\", \""+username+"\", \""+password+"\", \""+location+"\", \""+pdfendpoint+"\")");
db.execSQL("INSERT INTO account VALUES (\""+alias+"\", \""+endpoint+"\", \""+username+"\", \""+password+"\", \""+location+"\", \""+pdfendpoint+"\", \""+style+"\")");
Toast.makeText(getApplicationContext(),getResources().getString(R.string.accountadd_success), Toast.LENGTH_SHORT).show();
}
mainmenu();
@ -120,10 +128,6 @@ public class AccountAdd extends AppCompatActivity {
username = aupick.getText().toString();
password = appick.getText().toString();
location = arpick.getText().toString();
if (alias.equals("") && endpoint.equals("") && username.equals(getResources().getString(R.string.access_key))) {
endpoint = getResources().getString(R.string.endpoint_url);
alias = "Google Test";
}
if (alias.equals("") || endpoint.equals("") || username.equals("") || password.equals("")) {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.accountadd_null), Toast.LENGTH_SHORT).show();
} else if (endpoint.startsWith("http://")) {
@ -137,14 +141,16 @@ public class AccountAdd extends AppCompatActivity {
public void run() {
try {
//Your code goes here
if (location.equals("")) {
location = "us-east-1";
if (endpoint.contains(getResources().getString(R.string.aws_endpoint)) || location.equals("")) {
region = Region.getRegion("us-east-1");
} else {
region = Region.getRegion(location);
}
if(endpoint.endsWith("/")) {
endpoint = endpoint.substring(0, endpoint.length()-1);
}
region = Region.getRegion("us-east-1");
S3ClientOptions s3ClientOptions = S3ClientOptions.builder().build();
if (!endpoint.contains(getResources().getString(R.string.aws_endpoint))) {
s3ClientOptions.setPathStyleAccess(true);
}
s3ClientOptions.setPathStyleAccess(pathstyle.isChecked());
myCredentials = new BasicAWSCredentials(username, password);
s3client = new AmazonS3Client(myCredentials, region);
s3client.setEndpoint(endpoint);
@ -167,7 +173,7 @@ public class AccountAdd extends AppCompatActivity {
@Override
public void run() {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.media_list_fail), Toast.LENGTH_SHORT).show();
Toast.makeText(getApplicationContext(),e.toString(), Toast.LENGTH_SHORT).show();
}
});
}

View file

@ -1,4 +1,4 @@
package asgardius.page.s3manager;
package asgardius.page.s3managermk2;
import android.annotation.SuppressLint;
import android.content.Context;
@ -7,10 +7,11 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import asgardius.page.s3manager.BucketSelect;
public class Adapter extends RecyclerView.Adapter<Adapter.ViewHolder>{
ArrayList Img, Name;

View file

@ -0,0 +1,192 @@
package asgardius.page.s3managermk2;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.regions.Region;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.S3ClientOptions;
public class BucketPolicy extends AppCompatActivity {
String username, password, endpoint, bucket, location;
Region region;
S3ClientOptions s3ClientOptions;
AWSCredentials myCredentials;
AmazonS3 s3client;
boolean style, publicbucket;
ProgressBar simpleProgressBar;
TextView permission;
Button setpublic, setprivate;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bucket_policy);
simpleProgressBar = (ProgressBar) findViewById(R.id.simpleProgressBar);
permission = (TextView) findViewById(R.id.permission);
endpoint = getIntent().getStringExtra("endpoint");
username = getIntent().getStringExtra("username");
password = getIntent().getStringExtra("password");
bucket = getIntent().getStringExtra("bucket");
style = getIntent().getBooleanExtra("style", false);
location = getIntent().getStringExtra("region");
getSupportActionBar().setTitle(bucket+"/");
region = Region.getRegion(location);
s3ClientOptions = S3ClientOptions.builder().build();
myCredentials = new BasicAWSCredentials(username, password);
try {
s3client = new AmazonS3Client(myCredentials, region);
} catch (Exception e) {
Toast.makeText(getApplicationContext(), e.toString(), Toast.LENGTH_SHORT).show();
}
s3client.setEndpoint(endpoint);
s3ClientOptions.setPathStyleAccess(style);
s3client.setS3ClientOptions(s3ClientOptions);
setprivate = (Button)findViewById(R.id.set_private);
setpublic = (Button)findViewById(R.id.set_public);
Thread getPolicy = new Thread(new Runnable() {
@Override
public void run() {
try {
//Your code goes here
String policy = s3client.getBucketPolicy(bucket).getPolicyText();
publicbucket = policy.contains("arn:aws:s3:::"+bucket+"/*") && policy.contains("s3:GetObject");
//System.out.println(policy);
runOnUiThread(new Runnable() {
@Override
public void run() {
//Your code goes here
if(publicbucket){
permission.setText(getResources().getString(R.string.public_bucket));
} else {
permission.setText(getResources().getString(R.string.custom_policy));
setpublic.setVisibility(View.VISIBLE);
}
setprivate.setVisibility(View.VISIBLE);
simpleProgressBar.setVisibility(View.INVISIBLE);
}
});
} catch (Exception e) {
e.printStackTrace();
runOnUiThread(new Runnable() {
@Override
public void run() {
if(e.toString().contains("NoSuchBucketPolicy")) {
permission.setText(getResources().getString(R.string.private_bucket));
setpublic.setVisibility(View.VISIBLE);
simpleProgressBar.setVisibility(View.INVISIBLE);
}
else {
Toast.makeText(getApplicationContext(),e.toString(), Toast.LENGTH_SHORT).show();
finish();
}
}
});
//Toast.makeText(getApplicationContext(),getResources().getString(R.string.media_list_fail), Toast.LENGTH_SHORT).show();
}
}
});
getPolicy.start();
setpublic.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
//buttonaction
simpleProgressBar.setVisibility(View.VISIBLE);
setPublic();
}
});
setprivate.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
//buttonaction
simpleProgressBar.setVisibility(View.VISIBLE);
setPrivate();
}
});
}
private void setPublic() {
Thread setPublic = new Thread(new Runnable() {
@Override
public void run() {
try {
//Your code goes here
String policy = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:GetBucketLocation\",\"s3:ListBucket\"],\"Resource\":[\"arn:aws:s3:::"
+bucket+"\"]},{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:GetObject\"],\"Resource\":[\"arn:aws:s3:::"+bucket+"/*\"]}]}";
s3client.setBucketPolicy(bucket, policy);
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.policy_ok), Toast.LENGTH_SHORT).show();
finish();
}
});
} catch (Exception e) {
e.printStackTrace();
runOnUiThread(new Runnable() {
@Override
public void run() {
simpleProgressBar.setVisibility(View.INVISIBLE);
Toast.makeText(getApplicationContext(),getResources().getString(R.string.policy_error), Toast.LENGTH_SHORT).show();
}
});
//Toast.makeText(getApplicationContext(),getResources().getString(R.string.media_list_fail), Toast.LENGTH_SHORT).show();
}
}
});
setPublic.start();
}
private void setPrivate() {
Thread setPrivate = new Thread(new Runnable() {
@Override
public void run() {
try {
//Your code goes here
s3client.deleteBucketPolicy(bucket);
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.policy_ok), Toast.LENGTH_SHORT).show();
finish();
}
});
} catch (Exception e) {
e.printStackTrace();
runOnUiThread(new Runnable() {
@Override
public void run() {
simpleProgressBar.setVisibility(View.INVISIBLE);
Toast.makeText(getApplicationContext(),getResources().getString(R.string.policy_error), Toast.LENGTH_SHORT).show();
}
});
//Toast.makeText(getApplicationContext(),getResources().getString(R.string.media_list_fail), Toast.LENGTH_SHORT).show();
}
}
});
setPrivate.start();
}
}

View file

@ -1,16 +1,16 @@
package asgardius.page.s3manager;
import static android.media.MediaExtractor.MetricsConstants.MIME_TYPE;
import static com.amazonaws.regions.Regions.US_EAST_1;
package asgardius.page.s3managermk2;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.app.Activity;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.view.MenuItem;
@ -26,7 +26,6 @@ import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.S3ClientOptions;
import com.amazonaws.services.s3.model.Bucket;
import com.amazonaws.services.s3.model.DeleteObjectRequest;
import com.amazonaws.services.s3.model.DeleteObjectsRequest;
import com.amazonaws.services.s3.model.ListObjectsRequest;
import com.amazonaws.services.s3.model.ObjectListing;
@ -40,14 +39,14 @@ public class BucketSelect extends AppCompatActivity {
ArrayList Name;
ArrayList Img;
RecyclerView recyclerView;
String username, password, endpoint, prefix, location, file, pdfendpoint;
int treelevel;
String username, password, endpoint, prefix, location, pdfendpoint;
boolean style, isplaylist;
Region region;
S3ClientOptions s3ClientOptions;
AWSCredentials myCredentials;
AmazonS3 s3client;
ProgressBar simpleProgressBar;
int videocache, videotime, buffersize;
int videocache, videotime, buffersize, treelevel, playlisttime;
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -57,16 +56,21 @@ public class BucketSelect extends AppCompatActivity {
password = getIntent().getStringExtra("password");
location = getIntent().getStringExtra("region");
pdfendpoint = getIntent().getStringExtra("pdfendpoint");
style = getIntent().getBooleanExtra("style", false);
videocache = getIntent().getIntExtra("videocache", 40);
videotime = getIntent().getIntExtra("videotime", 1);
playlisttime = getIntent().getIntExtra("playlisttime", 1);
buffersize = getIntent().getIntExtra("buffersize", 2000);
isplaylist = getIntent().getBooleanExtra("isplaylist", false);
prefix = "";
setContentView(R.layout.activity_bucket_select);
region = Region.getRegion("us-east-1");
s3ClientOptions = S3ClientOptions.builder().build();
if (!endpoint.contains(getResources().getString(R.string.aws_endpoint))) {
s3ClientOptions.setPathStyleAccess(true);
if (endpoint.contains(getResources().getString(R.string.aws_endpoint))) {
region = Region.getRegion("us-east-1");
} else {
region = Region.getRegion(location);
}
s3ClientOptions = S3ClientOptions.builder().build();
s3ClientOptions.setPathStyleAccess(style);
myCredentials = new BasicAWSCredentials(username, password);
s3client = new AmazonS3Client(myCredentials, region);
s3client.setEndpoint(endpoint);
@ -123,7 +127,7 @@ public class BucketSelect extends AppCompatActivity {
@Override
public void run() {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.media_list_fail), Toast.LENGTH_SHORT).show();
Toast.makeText(getApplicationContext(),e.toString(), Toast.LENGTH_SHORT).show();
}
});
//Toast.makeText(getApplicationContext(),getResources().getString(R.string.media_list_fail), Toast.LENGTH_SHORT).show();
@ -161,7 +165,17 @@ public class BucketSelect extends AppCompatActivity {
//Toast.makeText(MainActivity.this, "You Clicked " + menuItem.getTitle(), Toast.LENGTH_SHORT).show();
if (menuItem.getTitle() == getResources().getString(R.string.upload_file_tobucket)) {
//Toast.makeText(BucketSelect.this, getResources().getString(R.string.pending_feature), Toast.LENGTH_SHORT).show();
upload(Name.get(position).toString());
upload(Name.get(position).toString(), false);
} else if (menuItem.getTitle() == getResources().getString(R.string.upload_folder_tobucket)) {
//Toast.makeText(BucketSelect.this, getResources().getString(R.string.pending_feature), Toast.LENGTH_SHORT).show();
upload(Name.get(position).toString(), true);
} else if (menuItem.getTitle() == getResources().getString(R.string.create_link)) {
share(Name.get(position).toString());
} else if (menuItem.getTitle() == getResources().getString(R.string.download_bucket)) {
//Toast.makeText(BucketSelect.this, getResources().getString(R.string.pending_feature), Toast.LENGTH_SHORT).show();
download(Name.get(position).toString());
} else if (menuItem.getTitle() == getResources().getString(R.string.create_bucket)) {
//upload();
@ -171,6 +185,12 @@ public class BucketSelect extends AppCompatActivity {
} else if (menuItem.getTitle() == getResources().getString(R.string.object_info)) {
objectInfo(Name.get(position).toString());
} else if (menuItem.getTitle() == getResources().getString(R.string.copy_name)) {
copyName(Name.get(position).toString());
} else if (menuItem.getTitle() == getResources().getString(R.string.cors_config)) {
corsConfig(Name.get(position).toString());
} else if (menuItem.getTitle() == getResources().getString(R.string.bucket_policy)) {
policyConfig(Name.get(position).toString());
} else if (menuItem.getTitle() == getResources().getString(R.string.file_del)) {
//Toast.makeText(BucketSelect.this, getResources().getString(R.string.pending_feature), Toast.LENGTH_SHORT).show();
delete(prefix + Name.get(position).toString());
@ -197,9 +217,29 @@ public class BucketSelect extends AppCompatActivity {
intent.putExtra("treelevel", treelevel);
intent.putExtra("region", location);
intent.putExtra("pdfendpoint", pdfendpoint);
intent.putExtra("style", style);
intent.putExtra("videocache", videocache);
intent.putExtra("videotime", videotime);
intent.putExtra("buffersize", buffersize);
intent.putExtra("playlisttime", playlisttime);
intent.putExtra("isplaylist", isplaylist);
startActivity(intent);
}
private void share(String bucket) {
Intent intent = new Intent(this, Share.class);
//treelevel ++;
intent.putExtra("endpoint", endpoint);
intent.putExtra("username", username);
intent.putExtra("password", password);
intent.putExtra("bucket", bucket);
intent.putExtra("title", bucket);
intent.putExtra("region", location);
intent.putExtra("videotime", videotime);
intent.putExtra("playlisttime", playlisttime);
intent.putExtra("style", style);
startActivity(intent);
}
@ -265,7 +305,7 @@ public class BucketSelect extends AppCompatActivity {
@Override
public void run() {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.media_list_fail), Toast.LENGTH_SHORT).show();
Toast.makeText(getApplicationContext(),e.toString(), Toast.LENGTH_SHORT).show();
}
});
//Toast.makeText(getApplicationContext(),getResources().getString(R.string.media_list_fail), Toast.LENGTH_SHORT).show();
@ -286,7 +326,7 @@ public class BucketSelect extends AppCompatActivity {
dialog.show();
}
private void upload(String bucket) {
private void upload(String bucket, boolean isfolder) {
Intent intent = new Intent(this, Uploader.class);
intent.putExtra("endpoint", endpoint);
intent.putExtra("username", username);
@ -294,6 +334,8 @@ public class BucketSelect extends AppCompatActivity {
intent.putExtra("bucket", bucket);
intent.putExtra("prefix", prefix);
intent.putExtra("region", location);
intent.putExtra("style", style);
intent.putExtra("isfolder", isfolder);
startActivity(intent);
}
@ -306,6 +348,7 @@ public class BucketSelect extends AppCompatActivity {
intent.putExtra("password", password);
intent.putExtra("bucket", bucket);
intent.putExtra("region", location);
intent.putExtra("style", style);
startActivity(intent);
}
@ -316,7 +359,66 @@ public class BucketSelect extends AppCompatActivity {
intent.putExtra("username", username);
intent.putExtra("password", password);
intent.putExtra("region", location);
intent.putExtra("style", style);
//startActivity(intent);
((Activity) this).startActivityForResult(intent, 25);
}
private void download(String bucket) {
Intent intent = new Intent(this, Downloader.class);
intent.putExtra("endpoint", endpoint);
intent.putExtra("username", username);
intent.putExtra("password", password);
intent.putExtra("prefix", prefix);
intent.putExtra("region", location);
intent.putExtra("style", style);
intent.putExtra("bucket", bucket);
intent.putExtra("isfolder", true);
startActivity(intent);
}
private void corsConfig(String bucket) {
Intent intent = new Intent(this, CorsConfig.class);
intent.putExtra("endpoint", endpoint);
intent.putExtra("username", username);
intent.putExtra("password", password);
intent.putExtra("bucket", bucket);
intent.putExtra("region", location);
intent.putExtra("style", style);
intent.putExtra("pdfendpoint", pdfendpoint);
startActivity(intent);
}
private void policyConfig(String bucket) {
Intent intent = new Intent(this, BucketPolicy.class);
intent.putExtra("endpoint", endpoint);
intent.putExtra("username", username);
intent.putExtra("password", password);
intent.putExtra("bucket", bucket);
intent.putExtra("region", location);
intent.putExtra("style", style);
intent.putExtra("pdfendpoint", pdfendpoint);
startActivity(intent);
}
public void copyName (String name) {
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("name", name);
clipboard.setPrimaryClip(clip);
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.S_V2) {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.copy_ok), Toast.LENGTH_SHORT).show();
}
}
public void onActivityResult(int requestCode, int resultCode, final Intent resultData) {
// The ACTION_OPEN_DOCUMENT intent was sent with the request code OPEN_DIRECTORY_REQUEST_CODE.
// If the request code seen here doesn't match, it's the response to some other intent,
// and the below code shouldn't run at all.
super.onActivityResult(requestCode, resultCode, resultData);
if(requestCode == 25 && resultCode == 25) {
recreate();
}
}
}

View file

@ -0,0 +1,278 @@
package asgardius.page.s3managermk2;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.regions.Region;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.S3ClientOptions;
import com.amazonaws.services.s3.model.BucketCrossOriginConfiguration;
import com.amazonaws.services.s3.model.CORSRule;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
public class CorsConfig extends AppCompatActivity {
String username, password, endpoint, bucket, location;
URI pdfendpoint;
Region region;
S3ClientOptions s3ClientOptions;
AWSCredentials myCredentials;
AmazonS3 s3client;
ProgressBar simpleProgressBar;
BucketCrossOriginConfiguration bucketcors;
boolean style;
boolean allorigins, pdfcompatible, found = false;
TextView origins;
Button allowall, allowpdf, deletecors;
BucketCrossOriginConfiguration corsconfig;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_cors_config);
simpleProgressBar = (ProgressBar) findViewById(R.id.simpleProgressBar);
endpoint = getIntent().getStringExtra("endpoint");
username = getIntent().getStringExtra("username");
password = getIntent().getStringExtra("password");
bucket = getIntent().getStringExtra("bucket");
style = getIntent().getBooleanExtra("style", false);
location = getIntent().getStringExtra("region");
allowall = (Button)findViewById(R.id.allow_all);
allowpdf = (Button)findViewById(R.id.allow_pdf);
deletecors = (Button)findViewById(R.id.delete_cors);
try {
pdfendpoint = new URI(getIntent().getStringExtra("pdfendpoint"));
} catch (URISyntaxException e) {
e.printStackTrace();
}
getSupportActionBar().setTitle(bucket+"/");
region = Region.getRegion(location);
s3ClientOptions = S3ClientOptions.builder().build();
myCredentials = new BasicAWSCredentials(username, password);
origins = (TextView) findViewById(R.id.origins);
try {
s3client = new AmazonS3Client(myCredentials, region);
} catch (Exception e) {
Toast.makeText(getApplicationContext(),e.toString(), Toast.LENGTH_SHORT).show();
}
s3client.setEndpoint(endpoint);
s3ClientOptions.setPathStyleAccess(style);
s3client.setS3ClientOptions(s3ClientOptions);
Thread getCors = new Thread(new Runnable() {
@Override
public void run() {
try {
//Your code goes here
bucketcors = s3client.getBucketCrossOriginConfiguration(bucket);
if (bucketcors != null) {
List<CORSRule> corsRules = bucketcors.getRules();
if (!corsRules.isEmpty()) {
found = true;
for (CORSRule rule: corsRules) {
//System.out.println("allowOrigins: "+rule.getAllowedOrigins());
//System.out.println("AllowedMethod: "+rule.getAllowedMethods());
if (rule.getAllowedOrigins().toString().equals("[*]")) {
allorigins = true;
} else if (rule.getAllowedOrigins().toString().contains("https://"+pdfendpoint.getHost())) {
pdfcompatible = true;
}
}
}
}
runOnUiThread(new Runnable() {
@Override
public void run() {
simpleProgressBar.setVisibility(View.INVISIBLE);
if (allorigins) {
origins.setText(getResources().getString(R.string.cors_all));
deletecors.setVisibility(View.VISIBLE);
} else if (pdfcompatible) {
origins.setText(getResources().getString(R.string.cors_pdf));
deletecors.setVisibility(View.VISIBLE);
allowall.setVisibility(View.VISIBLE);
} else if (found) {
origins.setText(getResources().getString(R.string.cors_npdf));
deletecors.setVisibility(View.VISIBLE);
allowpdf.setVisibility(View.VISIBLE);
allowall.setVisibility(View.VISIBLE);
} else {
origins.setText(getResources().getString(R.string.cors_none));
allowall.setVisibility(View.VISIBLE);
allowpdf.setVisibility(View.VISIBLE);
}
}
});
} catch (Exception e) {
e.printStackTrace();
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(),e.toString(), Toast.LENGTH_SHORT).show();
}
});
//Toast.makeText(getApplicationContext(),getResources().getString(R.string.media_list_fail), Toast.LENGTH_SHORT).show();
finish();
}
}
});
getCors.start();
allowall.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
//buttonaction
simpleProgressBar.setVisibility(View.VISIBLE);
setAllowall();
}
});
allowpdf.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
//buttonaction
simpleProgressBar.setVisibility(View.VISIBLE);
setAllowpdf();
}
});
deletecors.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
//buttonaction
simpleProgressBar.setVisibility(View.VISIBLE);
setDeletecors();
}
});
}
private void setAllowall() {
Thread addAll = new Thread(new Runnable() {
@Override
public void run() {
try {
//Your code goes here
List<CORSRule.AllowedMethods> allowMethods = new ArrayList<>();
allowMethods.add(CORSRule.AllowedMethods.GET);
List<String> allowOrigins = new ArrayList<>();
allowOrigins.add("*");
CORSRule corsRules = new CORSRule().withAllowedMethods(allowMethods).withAllowedOrigins(allowOrigins);
corsconfig = new BucketCrossOriginConfiguration().withRules(corsRules);
s3client.setBucketCrossOriginConfiguration(bucket, corsconfig);
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.policy_ok), Toast.LENGTH_SHORT).show();
finish();
}
});
} catch (Exception e) {
e.printStackTrace();
runOnUiThread(new Runnable() {
@Override
public void run() {
simpleProgressBar.setVisibility(View.INVISIBLE);
Toast.makeText(getApplicationContext(),getResources().getString(R.string.policy_error), Toast.LENGTH_SHORT).show();
}
});
//Toast.makeText(getApplicationContext(),getResources().getString(R.string.media_list_fail), Toast.LENGTH_SHORT).show();
}
}
});
addAll.start();
}
private void setAllowpdf() {
Thread addPdf = new Thread(new Runnable() {
@Override
public void run() {
try {
//Your code goes here
List<CORSRule.AllowedMethods> allowMethods = new ArrayList<>();
allowMethods.add(CORSRule.AllowedMethods.GET);
List<String> allowOrigins = new ArrayList<>();
allowOrigins.add("https://"+pdfendpoint.getHost());
CORSRule corsRules = new CORSRule().withAllowedMethods(allowMethods).withAllowedOrigins(allowOrigins);
corsconfig = new BucketCrossOriginConfiguration().withRules(corsRules);
s3client.setBucketCrossOriginConfiguration(bucket, corsconfig);
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.policy_ok), Toast.LENGTH_SHORT).show();
finish();
}
});
} catch (Exception e) {
e.printStackTrace();
runOnUiThread(new Runnable() {
@Override
public void run() {
simpleProgressBar.setVisibility(View.INVISIBLE);
Toast.makeText(getApplicationContext(),getResources().getString(R.string.policy_error), Toast.LENGTH_SHORT).show();
}
});
//Toast.makeText(getApplicationContext(),getResources().getString(R.string.media_list_fail), Toast.LENGTH_SHORT).show();
}
}
});
addPdf.start();
}
private void setDeletecors() {
Thread delCors = new Thread(new Runnable() {
@Override
public void run() {
try {
//Your code goes here
s3client.deleteBucketCrossOriginConfiguration(bucket);
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.policy_ok), Toast.LENGTH_SHORT).show();
finish();
}
});
} catch (Exception e) {
e.printStackTrace();
runOnUiThread(new Runnable() {
@Override
public void run() {
simpleProgressBar.setVisibility(View.INVISIBLE);
Toast.makeText(getApplicationContext(),getResources().getString(R.string.policy_error), Toast.LENGTH_SHORT).show();
}
});
//Toast.makeText(getApplicationContext(),getResources().getString(R.string.media_list_fail), Toast.LENGTH_SHORT).show();
}
}
});
delCors.start();
}
}

View file

@ -1,9 +1,5 @@
package asgardius.page.s3manager;
package asgardius.page.s3managermk2;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
@ -11,22 +7,18 @@ import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.regions.Region;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.S3ClientOptions;
import com.amazonaws.services.s3.model.DeleteObjectsRequest;
import com.amazonaws.services.s3.model.ListObjectsRequest;
import com.amazonaws.services.s3.model.ObjectListing;
import com.amazonaws.services.s3.model.S3ObjectSummary;
import java.util.ArrayList;
import java.util.List;
public class CreateBucket extends AppCompatActivity {
String username, password, endpoint, bucket, location;
boolean style;
EditText bname;
Region region;
S3ClientOptions s3ClientOptions;
@ -42,11 +34,10 @@ public class CreateBucket extends AppCompatActivity {
username = getIntent().getStringExtra("username");
password = getIntent().getStringExtra("password");
location = getIntent().getStringExtra("region");
style = getIntent().getBooleanExtra("style", false);
region = Region.getRegion("us-east-1");
s3ClientOptions = S3ClientOptions.builder().build();
if (!endpoint.contains(getResources().getString(R.string.aws_endpoint))) {
s3ClientOptions.setPathStyleAccess(true);
}
s3ClientOptions.setPathStyleAccess(style);
myCredentials = new BasicAWSCredentials(username, password);
s3client = new AmazonS3Client(myCredentials, region);
s3client.setEndpoint(endpoint);
@ -75,8 +66,10 @@ public class CreateBucket extends AppCompatActivity {
@Override
public void run() {
// Sending reference and data to Adapter
setResult(25);
Toast.makeText(getApplicationContext(),getResources().getString(R.string.create_bucket_success), Toast.LENGTH_SHORT).show();
mainmenu();
finish();
//mainmenu();
}
});
@ -89,7 +82,7 @@ public class CreateBucket extends AppCompatActivity {
@Override
public void run() {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.media_list_fail), Toast.LENGTH_SHORT).show();
Toast.makeText(getApplicationContext(),e.toString(), Toast.LENGTH_SHORT).show();
}
});
//Toast.makeText(getApplicationContext(),getResources().getString(R.string.media_list_fail), Toast.LENGTH_SHORT).show();
@ -106,12 +99,12 @@ public class CreateBucket extends AppCompatActivity {
}
private void mainmenu() {
/*private void mainmenu() {
Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("EXIT", true);
startActivity(intent);
}
}*/
}

View file

@ -1,8 +1,9 @@
package asgardius.page.s3manager;
package asgardius.page.s3managermk2;
import static android.content.ContentValues.TAG;
import androidx.appcompat.app.AppCompatActivity;
import androidx.documentfile.provider.DocumentFile;
import android.app.Activity;
import android.content.Context;
@ -25,27 +26,37 @@ import com.amazonaws.regions.Region;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.S3ClientOptions;
import com.amazonaws.services.s3.model.ListObjectsRequest;
import com.amazonaws.services.s3.model.ObjectListing;
import com.amazonaws.services.s3.model.S3Object;
import com.amazonaws.services.s3.model.S3ObjectSummary;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
public class Downloader extends AppCompatActivity {
String username, password, endpoint, bucket, filename, prefix, location;
Uri fileuri;
Uri fileuri, filepath;
Region region;
String[] folder;
S3ClientOptions s3ClientOptions;
AWSCredentials myCredentials;
AmazonS3 s3client;
ProgressBar simpleProgressBar;
ListObjectsRequest orequest;
Intent intent;
Button fileDownload;
Thread downloadFile, downloadProgress;
S3Object object;
DocumentFile document;
boolean started = false;
boolean cancel = false;
boolean style, isfolder;
long filesize = 0;
long objectsize;
long transfered = 0;
private WifiManager.WifiLock mWifiLock;
private PowerManager.WakeLock mWakeLock;
@ -65,14 +76,19 @@ public class Downloader extends AppCompatActivity {
password = getIntent().getStringExtra("password");
bucket = getIntent().getStringExtra("bucket");
location = getIntent().getStringExtra("region");
style = getIntent().getBooleanExtra("style", false);
isfolder = getIntent().getBooleanExtra("isfolder", false);
prefix = getIntent().getStringExtra("prefix");
if(isfolder) {
getSupportActionBar().setTitle(getResources().getString(R.string.download_files));
} else {
getSupportActionBar().setTitle(getResources().getString(R.string.download_file));
}
simpleProgressBar = (ProgressBar) findViewById(R.id.simpleProgressBar);
fileDownload = (Button)findViewById(R.id.filedownload);
region = Region.getRegion(location);
s3ClientOptions = S3ClientOptions.builder().build();
if (!endpoint.contains(getResources().getString(R.string.aws_endpoint))) {
s3ClientOptions.setPathStyleAccess(true);
}
s3ClientOptions.setPathStyleAccess(style);
myCredentials = new BasicAWSCredentials(username, password);
s3client = new AmazonS3Client(myCredentials, region);
s3client.setEndpoint(endpoint);
@ -117,9 +133,62 @@ public class Downloader extends AppCompatActivity {
//Your code goes here
//s3client.createBucket(bucket, location);
//System.out.println(fkey);
object = s3client.getObject(bucket, prefix+filename);
filesize = (object.getObjectMetadata().getContentLength())/1024;
writeContentToFile(fileuri);
if (isfolder) {
if (prefix == null) {
orequest = new ListObjectsRequest().withBucketName(bucket).withMaxKeys(1000);
} else {
orequest = new ListObjectsRequest().withBucketName(bucket).withPrefix(prefix).withMaxKeys(1000);
}
ArrayList<String> objectlist = new ArrayList<String>();
ObjectListing result = s3client.listObjects(orequest);
List<S3ObjectSummary> objects = result.getObjectSummaries();
for (S3ObjectSummary os : objects) {
objectlist.add(os.getKey());
objectsize = os.getSize();
if (objectsize%1024 == 0) {
filesize = filesize+(objectsize/1024);
} else {
filesize = filesize+(objectsize/1024)+1;
}
}
while (result.isTruncated()) {
result = s3client.listNextBatchOfObjects (result);
objects = result.getObjectSummaries();
for (S3ObjectSummary os : objects) {
objectlist.add(os.getKey());
objectsize = os.getSize();
if (objectsize%1024 == 0) {
filesize = filesize+(objectsize/1024);
} else {
filesize = filesize+(objectsize/1024)+1;
}
}
}
for (String os : objectlist) {
document = DocumentFile.fromTreeUri(getApplicationContext(), fileuri);
object = s3client.getObject(bucket, os);
if (os.replace(prefix, "").contains("/")) {
folder = os.replace(prefix, "").split("/");
for (int i = 0; i < folder.length-1; i++) {
DocumentFile subfolder = document.findFile(folder[i].replace("/", ""));
if (subfolder != null) {
document = subfolder;
} else {
document = document.createDirectory(folder[i].replace("/", ""));
}
}
filepath = document.createFile(null, folder[folder.length-1]).getUri();
} else {
filepath = document.createFile(null, os.replace(prefix, "")).getUri();
}
writeContentToFile(filepath, object);
}
} else {
object = s3client.getObject(bucket, prefix+filename);
filesize = (object.getObjectMetadata().getContentLength())/1024;
writeContentToFile(fileuri, object);
}
runOnUiThread(new Runnable() {
@Override
public void run() {
@ -134,7 +203,11 @@ public class Downloader extends AppCompatActivity {
//System.out.println("WakeLock released");
}
simpleProgressBar.setProgress(100);
fileDownload.setText(getResources().getString(R.string.download_success));
if (isfolder) {
fileDownload.setText(getResources().getString(R.string.batch_download_success));
} else {
fileDownload.setText(getResources().getString(R.string.download_success));
}
fileDownload.setEnabled(false);
//simpleProgressBar.setVisibility(View.INVISIBLE);
}
@ -201,16 +274,33 @@ public class Downloader extends AppCompatActivity {
private void performFileSearch(String messageTitle) {
//uri = Uri.parse("content://com.android.externalstorage.documents/document/home");
intent = new Intent();
intent.setAction(Intent.ACTION_CREATE_DOCUMENT);
//intent.addCategory(Intent.CATEGORY_OPENABLE);
//intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
//intent.putExtra("android.provider.extra.INITIAL_URI", uri);
intent.putExtra(Intent.EXTRA_TITLE, filename);
intent.setType("*/*");
if (isfolder) {
intent.setAction(Intent.ACTION_OPEN_DOCUMENT_TREE);
} else {
intent.setAction(Intent.ACTION_CREATE_DOCUMENT);
//intent.addCategory(Intent.CATEGORY_OPENABLE);
//intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
//intent.putExtra("android.provider.extra.INITIAL_URI", uri);
intent.putExtra(Intent.EXTRA_TITLE, filename);
intent.setType("*/*");
}
((Activity) this).startActivityForResult(intent, 50);
}
@Override
public void onDestroy() {
if (!mWifiLock.isHeld()) {
mWifiLock.acquire();
//System.out.println("WifiLock acquired");
}
if (!mWakeLock.isHeld()) {
mWakeLock.acquire();
//System.out.println("WakeLock acquired");
}
super.onDestroy();
}
public void onActivityResult(int requestCode, int resultCode, final Intent resultData) {
// The ACTION_OPEN_DOCUMENT intent was sent with the request code OPEN_DIRECTORY_REQUEST_CODE.
// If the request code seen here doesn't match, it's the response to some other intent,
@ -238,7 +328,7 @@ public class Downloader extends AppCompatActivity {
}
}
private void writeContentToFile(Uri uri) throws IOException {
private void writeContentToFile(Uri uri, S3Object object) throws IOException {
try (
final InputStream in = object.getObjectContent();
final OutputStream out = getContentResolver().openOutputStream(uri);

View file

@ -0,0 +1,136 @@
package asgardius.page.s3managermk2;
import android.annotation.SuppressLint;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.ProgressBar;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.otaliastudios.zoom.ZoomImageView;
import java.net.URL;
public class ImageViewer extends AppCompatActivity {
String videoURL, title;
ZoomImageView iv;
boolean controls = false;
float cursorx, cursory;
@SuppressLint("ClickableViewAccessibility")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_image_viewer);
videoURL = getIntent().getStringExtra("video_url");
title = getIntent().getStringExtra("title");
getSupportActionBar().setTitle(title);
final ProgressBar simpleProgressBar = (ProgressBar) findViewById(R.id.simpleProgressBar);
iv = (ZoomImageView) findViewById(R.id.imageViewer);
//System.out.println(videoURL);
Thread imgread = new Thread(new Runnable() {
@Override
public void run() {
try {
//Your code goes here
URL thumb_u = new URL(videoURL);
Drawable thumb_d = Drawable.createFromStream(thumb_u.openStream(), "src");
runOnUiThread(new Runnable() {
@Override
public void run() {
simpleProgressBar.setVisibility(View.INVISIBLE);
iv.setImageDrawable(thumb_d);
}
});
} catch (OutOfMemoryError e) {
e.printStackTrace();
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.picture_too_big), Toast.LENGTH_SHORT).show();
finish();
}
});
finish();
} catch (Exception e) {
e.printStackTrace();
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(),e.toString(), Toast.LENGTH_SHORT).show();
finish();
}
});
finish();
}
}
});
imgread.start();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
getWindow().getAttributes().layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
}
iv.setOnTouchListener((v, event) -> {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
cursorx = event.getX();
cursory = event.getY();
iv.performClick();
return true;
} else if (event.getAction() == MotionEvent.ACTION_UP) {
if(Math.abs(event.getX() - cursorx) < 5 || Math.abs(event.getY() - cursory) < 5) {
if(controls) {
controls = false;
hideSystemBars();
}
else {
controls = true;
showSystemBars();
}
}
return true;
}
return false;
});
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
controls = false;
hideSystemBars();
}
private void hideSystemBars() {
// Set the IMMERSIVE flag.
// Set the content to appear under the system bars so that the content
// doesn't resize when the system bars hide and show.
View decorView = getWindow().getDecorView();
decorView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
| View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
| View.SYSTEM_UI_FLAG_IMMERSIVE);
}
private void showSystemBars() {
View decorView = getWindow().getDecorView();
decorView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
}
}

View file

@ -1,4 +1,4 @@
package asgardius.page.s3manager;
package asgardius.page.s3managermk2;
import android.content.DialogInterface;
import android.content.Intent;
@ -20,14 +20,14 @@ import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
static boolean DEFAULT_PATH_STYLE_ACCESS = true;
boolean style, isplaylist;
String alias, username, password, endpoint, location, pdfendpoint;
RecyclerView recyclerView;
SQLiteDatabase db;
ArrayList Name;
ArrayList Img;
MyDbHelper dbHelper;
int videocache, videotime, buffersize;
int videocache, videotime, buffersize, playlisttime;
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -68,6 +68,8 @@ public class MainActivity extends AppCompatActivity {
db.execSQL("INSERT INTO preferences VALUES ('videocache', '300')");
db.execSQL("INSERT INTO preferences VALUES ('videotime', '3')");
db.execSQL("INSERT INTO preferences VALUES ('buffersize', '12000')");
db.execSQL("INSERT INTO preferences VALUES ('playlisttime', '5')");
db.execSQL("INSERT INTO preferences VALUES ('isplaylist', '0')");
videocache = 300;
//videotime = 3;
db.close();
@ -117,6 +119,74 @@ public class MainActivity extends AppCompatActivity {
//Toast.makeText(getApplicationContext(),getResources().getString(R.string.media_list_fail), Toast.LENGTH_SHORT).show();
finish();
}
try {
db = dbHelper.getWritableDatabase();
String query = "SELECT value FROM preferences where setting='playlisttime'";
Cursor cursor = db.rawQuery(query,null);
while (cursor.moveToNext()){
playlisttime = (Integer.parseInt(cursor.getString(0)));
}
db.close();
if (playlisttime == 0) {
try {
db = dbHelper.getWritableDatabase();
db.execSQL("INSERT INTO preferences VALUES ('playlisttime', '5')");
playlisttime = 5;
db.close();
} catch (Exception e) {
db = dbHelper.getWritableDatabase();
db.execSQL("CREATE TABLE IF NOT EXISTS preferences(setting text UNIQUE, value text)");
db.close();
}
}
} catch (Exception e) {
e.printStackTrace();
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.broken_database), Toast.LENGTH_SHORT).show();
}
});
//Toast.makeText(getApplicationContext(),getResources().getString(R.string.media_list_fail), Toast.LENGTH_SHORT).show();
finish();
}
try {
db = dbHelper.getWritableDatabase();
String query = "SELECT value FROM preferences where setting='isplaylist'";
Cursor cursor = db.rawQuery(query,null);
String update = null;
while (cursor.moveToNext()){
isplaylist = cursor.getString(0).equals("1");
if(!isplaylist) {
update = cursor.getString(0);
}
}
db.close();
if (!isplaylist && update == null) {
try {
db = dbHelper.getWritableDatabase();
db.execSQL("INSERT INTO preferences VALUES ('isplaylist', '0')");
isplaylist = false;
db.close();
} catch (Exception e) {
db = dbHelper.getWritableDatabase();
db.execSQL("CREATE TABLE IF NOT EXISTS preferences(setting text UNIQUE, value text)");
db.close();
}
}
} catch (Exception e) {
e.printStackTrace();
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.broken_database), Toast.LENGTH_SHORT).show();
}
});
//Toast.makeText(getApplicationContext(),getResources().getString(R.string.media_list_fail), Toast.LENGTH_SHORT).show();
finish();
}
try {
db = dbHelper.getWritableDatabase();
String query = "SELECT value FROM preferences where setting='buffersize'";
@ -219,7 +289,7 @@ public class MainActivity extends AppCompatActivity {
// Database Queries
try {
//This retrieves credentials from selected account
String query = "SELECT endpoint, username, password, region, pdfendpoint FROM account where id=\""+ Name.get(position).toString()+ "\"";
String query = "SELECT endpoint, username, password, region, pdfendpoint, style FROM account where id=\""+ Name.get(position).toString()+ "\"";
Cursor cursor = db.rawQuery(query,null);
if (cursor.moveToNext()){
endpoint = cursor.getString(0);
@ -227,12 +297,27 @@ public class MainActivity extends AppCompatActivity {
password = cursor.getString(2);
location = cursor.getString(3);
pdfendpoint = cursor.getString(4);
try {
style = cursor.getString(5).equals("1");
} catch (Exception e) {
e.printStackTrace();
style = false;
}
db.close();
//This launch file explorer using selected account
explorer();
}
} catch (Exception e) {
e.printStackTrace();
try {
db = dbHelper.getWritableDatabase();
db.execSQL("alter table account add column style text");
db.close();
} catch (Exception f) {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.broken_database), Toast.LENGTH_SHORT).show();
finish();
}
}
}
@ -255,7 +340,7 @@ public class MainActivity extends AppCompatActivity {
try {
db = dbHelper.getWritableDatabase();
//This retrieves credentials from selected account
String query = "SELECT id, endpoint, username, password, region, pdfendpoint FROM account where id=\""+ Name.get(position).toString()+ "\"";
String query = "SELECT id, endpoint, username, password, region, pdfendpoint, style FROM account where id=\""+ Name.get(position).toString()+ "\"";
System.out.println(query);
Cursor cursor = db.rawQuery(query,null);
if (cursor.moveToNext()){
@ -265,6 +350,12 @@ public class MainActivity extends AppCompatActivity {
password = cursor.getString(3);
location = cursor.getString(4);
pdfendpoint = cursor.getString(5);
try {
style = cursor.getString(6).equals("1");
} catch (Exception e) {
e.printStackTrace();
style = false;
}
}
db.close();
//This launch account editor
@ -272,6 +363,14 @@ public class MainActivity extends AppCompatActivity {
//Toast.makeText(MainActivity.this, "This feature is not yet implemented", Toast.LENGTH_SHORT).show();
} catch (Exception e) {
e.printStackTrace();
try {
db = dbHelper.getWritableDatabase();
db.execSQL("alter table account add column style text");
db.close();
} catch (Exception f) {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.broken_database), Toast.LENGTH_SHORT).show();
finish();
}
}
}
else if (menuItem.getTitle() == getResources().getString(R.string.accountdel_button)) {
@ -346,9 +445,12 @@ public class MainActivity extends AppCompatActivity {
intent.putExtra("password", password);
intent.putExtra("region", location);
intent.putExtra("pdfendpoint", pdfendpoint);
intent.putExtra("style", style);
intent.putExtra("videocache", videocache);
intent.putExtra("videotime", videotime);
intent.putExtra("buffersize", buffersize);
intent.putExtra("playlisttime", playlisttime);
intent.putExtra("isplaylist", isplaylist);
startActivity(intent);
}
@ -363,6 +465,7 @@ public class MainActivity extends AppCompatActivity {
intent.putExtra("password", password);
intent.putExtra("region", location);
intent.putExtra("pdfendpoint", pdfendpoint);
intent.putExtra("style", style);
}
intent.putExtra("edit", edit);
startActivity(intent);

View file

@ -1,15 +1,17 @@
package asgardius.page.s3manager;
package asgardius.page.s3managermk2;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class MyDbHelper extends SQLiteOpenHelper {
private static final String usertable = "CREATE TABLE IF NOT EXISTS account(id text UNIQUE, endpoint text, username text, password text, region text, pdfendpoint text)";
private static final String usertable = "CREATE TABLE IF NOT EXISTS account(id text UNIQUE, endpoint text, username text, password text, region text, pdfendpoint text, style text)";
private static final String preftable = "CREATE TABLE IF NOT EXISTS preferences(setting text UNIQUE, value text)";
private static final String setvideocache = "INSERT INTO preferences VALUES ('videocache', '300')";
private static final String setvideotime = "INSERT INTO preferences VALUES ('videotime', '3')";
private static final String setbuffersize = "INSERT INTO preferences VALUES ('buffersize', '12000')";
private static final String setplaylisttime = "INSERT INTO preferences VALUES ('playlisttime', '5')";
private static final String setisplaylist = "INSERT INTO preferences VALUES ('isplaylist', '0')";
//private static final String upgrade = "ALTER TABLE account add column pdfendpoint text";
private static final int DATABASE_VERSION = 1;
private static final String dbname = "accounts.sqlite3";
@ -24,6 +26,8 @@ public class MyDbHelper extends SQLiteOpenHelper {
db.execSQL(setvideocache);
db.execSQL(setvideotime);
db.execSQL(setbuffersize);
db.execSQL(setplaylisttime);
db.execSQL(setisplaylist);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

View file

@ -1,37 +1,34 @@
package asgardius.page.s3manager;
import androidx.appcompat.app.AppCompatActivity;
package asgardius.page.s3managermk2;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.regions.Region;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.S3ClientOptions;
import com.amazonaws.services.s3.model.Bucket;
import com.amazonaws.services.s3.model.ListObjectsRequest;
import com.amazonaws.services.s3.model.ObjectListing;
import com.amazonaws.services.s3.model.S3ObjectSummary;
import java.util.ArrayList;
import java.util.List;
public class ObjectInfo extends AppCompatActivity {
String username, password, endpoint, bucket, object, location;
String username, password, endpoint, bucket, object, location, title;
Region region;
S3ClientOptions s3ClientOptions;
AWSCredentials myCredentials;
AmazonS3 s3client;
ProgressBar simpleProgressBar;
TextView filesize, filesizeinfo, objectcount;
boolean isobject, isfolder;
boolean isobject, isfolder, style;
long totalSize = 0;
int totalItems = 0;
ListObjectsRequest orequest;
@ -49,15 +46,17 @@ public class ObjectInfo extends AppCompatActivity {
filesizeinfo = (TextView) findViewById(R.id.size_info);
objectcount = (TextView) findViewById(R.id.object_count);
endpoint = getIntent().getStringExtra("endpoint");
title = getIntent().getStringExtra("title");
username = getIntent().getStringExtra("username");
password = getIntent().getStringExtra("password");
bucket = getIntent().getStringExtra("bucket");
style = getIntent().getBooleanExtra("style", false);
location = getIntent().getStringExtra("region");
object = getIntent().getStringExtra("object");
if (object == null) {
getSupportActionBar().setTitle(bucket+"/");
} else {
getSupportActionBar().setTitle(bucket+"/"+object);
getSupportActionBar().setTitle(title);
}
region = Region.getRegion(location);
s3ClientOptions = S3ClientOptions.builder().build();
@ -65,12 +64,10 @@ public class ObjectInfo extends AppCompatActivity {
try {
s3client = new AmazonS3Client(myCredentials, region);
} catch (Exception e) {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.media_list_fail), Toast.LENGTH_SHORT).show();
Toast.makeText(getApplicationContext(),e.toString(), Toast.LENGTH_SHORT).show();
}
s3client.setEndpoint(endpoint);
if (!endpoint.contains(getResources().getString(R.string.aws_endpoint))) {
s3ClientOptions.setPathStyleAccess(true);
}
s3ClientOptions.setPathStyleAccess(style);
s3client.setS3ClientOptions(s3ClientOptions);
Thread getInfo = new Thread(new Runnable() {
@ -80,7 +77,7 @@ public class ObjectInfo extends AppCompatActivity {
//Your code goes here
if (object == null) {
isobject = false;
orequest = new ListObjectsRequest().withBucketName(bucket).withMaxKeys(8000);
orequest = new ListObjectsRequest().withBucketName(bucket).withMaxKeys(1000);
} else {
isobject = true;
if (object.endsWith("/")) {
@ -88,7 +85,7 @@ public class ObjectInfo extends AppCompatActivity {
} else {
isfolder = false;
}
orequest = new ListObjectsRequest().withBucketName(bucket).withPrefix(object).withMaxKeys(8000);
orequest = new ListObjectsRequest().withBucketName(bucket).withPrefix(object).withMaxKeys(1000);
}
ObjectListing result = s3client.listObjects(orequest);
List<S3ObjectSummary> objects = result.getObjectSummaries();
@ -140,7 +137,7 @@ public class ObjectInfo extends AppCompatActivity {
@Override
public void run() {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.media_list_fail), Toast.LENGTH_SHORT).show();
Toast.makeText(getApplicationContext(),e.toString(), Toast.LENGTH_SHORT).show();
}
});
//Toast.makeText(getApplicationContext(),getResources().getString(R.string.media_list_fail), Toast.LENGTH_SHORT).show();

View file

@ -0,0 +1,260 @@
package asgardius.page.s3managermk2;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.regions.Region;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.S3ClientOptions;
public class ObjectPolicy extends AppCompatActivity {
String username, password, endpoint, bucket, location, filename, title, policy;
Region region;
S3ClientOptions s3ClientOptions;
AWSCredentials myCredentials;
AmazonS3 s3client;
boolean style, publicbucket, publicobject, parent;
ProgressBar simpleProgressBar;
TextView permission;
Button setpublic, setprivate;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_object_policy);
simpleProgressBar = (ProgressBar) findViewById(R.id.simpleProgressBar);
permission = (TextView) findViewById(R.id.permission);
endpoint = getIntent().getStringExtra("endpoint");
filename = getIntent().getStringExtra("filename");
username = getIntent().getStringExtra("username");
password = getIntent().getStringExtra("password");
bucket = getIntent().getStringExtra("bucket");
title = getIntent().getStringExtra("title");
style = getIntent().getBooleanExtra("style", false);
location = getIntent().getStringExtra("region");
getSupportActionBar().setTitle(title);
region = Region.getRegion(location);
s3ClientOptions = S3ClientOptions.builder().build();
myCredentials = new BasicAWSCredentials(username, password);
try {
s3client = new AmazonS3Client(myCredentials, region);
} catch (Exception e) {
Toast.makeText(getApplicationContext(), e.toString(), Toast.LENGTH_SHORT).show();
}
s3client.setEndpoint(endpoint);
s3ClientOptions.setPathStyleAccess(style);
s3client.setS3ClientOptions(s3ClientOptions);
setprivate = (Button)findViewById(R.id.set_private);
setpublic = (Button)findViewById(R.id.set_public);
Thread getPolicy = new Thread(new Runnable() {
@Override
public void run() {
try {
//Your code goes here
policy = s3client.getBucketPolicy(bucket).getPolicyText();
publicbucket = policy.contains("arn:aws:s3:::"+bucket+"/*") && policy.contains("s3:GetObject");
publicobject = false;
parent = true;
if(!publicbucket && policy.contains("s3:GetObject")) {
if((policy.contains("\"arn:aws:s3:::"+bucket+"/"+filename+"\"") || policy.contains("\"arn:aws:s3:::"+bucket+"/"+filename+"*\"") || policy.contains("\"arn:aws:s3:::"+bucket+"/"+filename+"**\"")) && policy.contains("s3:GetObject")) {
publicobject = true;
parent = false;
} else {
String[] path = filename.split("/");
String filepath = "";
for (int i = 0; i < path.length-1; i++) {
filepath = filepath+path[i]+"/";
//System.out.println(filepath);
if(policy.contains("\"arn:aws:s3:::"+bucket+"/"+filepath+"*\"") || policy.contains("\"arn:aws:s3:::"+bucket+"/"+filepath+"**\"")) {
publicobject = true;
i = path.length;
}
}
}
}
//System.out.println(policy);
runOnUiThread(new Runnable() {
@Override
public void run() {
//Your code goes here
if(publicbucket){
permission.setText(getResources().getString(R.string.public_object));
setprivate.setEnabled(false);
setprivate.setText(getResources().getString(R.string.parent_policy));
setprivate.setVisibility(View.VISIBLE);
}else if(publicobject) {
permission.setText(getResources().getString(R.string.public_object));
if(parent) {
setprivate.setEnabled(false);
setprivate.setText(getResources().getString(R.string.parent_policy));
}
setprivate.setVisibility(View.VISIBLE);
}else {
permission.setText(getResources().getString(R.string.private_object));
setpublic.setVisibility(View.VISIBLE);
}
simpleProgressBar.setVisibility(View.INVISIBLE);
}
});
} catch (Exception e) {
e.printStackTrace();
runOnUiThread(new Runnable() {
@Override
public void run() {
if(e.toString().contains("NoSuchBucketPolicy")) {
permission.setText(getResources().getString(R.string.private_object));
setpublic.setVisibility(View.VISIBLE);
simpleProgressBar.setVisibility(View.INVISIBLE);
}
else {
Toast.makeText(getApplicationContext(),e.toString(), Toast.LENGTH_SHORT).show();
finish();
}
}
});
//Toast.makeText(getApplicationContext(),getResources().getString(R.string.media_list_fail), Toast.LENGTH_SHORT).show();
}
}
});
getPolicy.start();
setpublic.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
//buttonaction
simpleProgressBar.setVisibility(View.VISIBLE);
setPublic();
}
});
setprivate.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
//buttonaction
simpleProgressBar.setVisibility(View.VISIBLE);
setPrivate();
}
});
}
private void setPublic() {
Thread setPublic = new Thread(new Runnable() {
@Override
public void run() {
try {
//Your code goes here
if(policy == null) {
if(filename.endsWith("/")) {
policy = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:GetObject\"],\"Resource\":[\"arn:aws:s3:::"+bucket+"/"+filename+"*\"]}]}";
} else {
policy = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:GetObject\"],\"Resource\":[\"arn:aws:s3:::"+bucket+"/"+filename+"\"]}]}";
}
} else if(policy.endsWith("]}]}")) {
if(filename.endsWith("/")) {
policy = policy.substring(0, policy.length()-4)+",\"arn:aws:s3:::"+bucket+"/"+filename+"*\"]}]}";
} else {
policy = policy.substring(0, policy.length()-4)+",\"arn:aws:s3:::"+bucket+"/"+filename+"\"]}]}";
}
} else {
if(filename.endsWith("/")) {
policy = policy.substring(0, policy.length()-3)+",\"arn:aws:s3:::"+bucket+"/"+filename+"*\"}]}";
} else {
policy = policy.substring(0, policy.length()-3)+",\"arn:aws:s3:::"+bucket+"/"+filename+"\"}]}";
}
}
s3client.setBucketPolicy(bucket, policy);
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.policy_ok), Toast.LENGTH_SHORT).show();
finish();
}
});
} catch (Exception e) {
e.printStackTrace();
runOnUiThread(new Runnable() {
@Override
public void run() {
simpleProgressBar.setVisibility(View.INVISIBLE);
Toast.makeText(getApplicationContext(),getResources().getString(R.string.policy_error), Toast.LENGTH_SHORT).show();
}
});
//Toast.makeText(getApplicationContext(),getResources().getString(R.string.media_list_fail), Toast.LENGTH_SHORT).show();
}
}
});
setPublic.start();
}
private void setPrivate() {
Thread setPrivate = new Thread(new Runnable() {
@Override
public void run() {
try {
//Your code goes here
String newpolicy = null;
if(policy.contains(",\"arn:aws:s3:::"+bucket+"/"+filename+"*\"")) {
newpolicy = policy.replace(",\"arn:aws:s3:::"+bucket+"/"+filename+"*\"", "");
s3client.setBucketPolicy(bucket, newpolicy);
} else if(policy.contains(",\"arn:aws:s3:::"+bucket+"/"+filename+"**\"")) {
newpolicy = policy.replace(",\"arn:aws:s3:::"+bucket+"/"+filename+"**\"", "");
s3client.setBucketPolicy(bucket, newpolicy);
} else if(policy.contains(",\"arn:aws:s3:::"+bucket+"/"+filename+"\"")) {
newpolicy = policy.replace(",\"arn:aws:s3:::"+bucket+"/"+filename+"\"", "");
s3client.setBucketPolicy(bucket, newpolicy);
} else if(policy.contains("\"arn:aws:s3:::"+bucket+"/"+filename+"*\",")) {
newpolicy = policy.replace("\"arn:aws:s3:::"+bucket+"/"+filename+"*\",", "");
s3client.setBucketPolicy(bucket, newpolicy);
} else if(policy.contains("\"arn:aws:s3:::"+bucket+"/"+filename+"**\",")) {
newpolicy = policy.replace("\"arn:aws:s3:::"+bucket+"/"+filename+"**\",", "");
s3client.setBucketPolicy(bucket, newpolicy);
} else if(policy.contains("\"arn:aws:s3:::"+bucket+"/"+filename+"\",")) {
newpolicy = policy.replace("\"arn:aws:s3:::"+bucket+"/"+filename+"\",", "");
s3client.setBucketPolicy(bucket, newpolicy);
} else {
s3client.deleteBucketPolicy(bucket);
}
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.policy_ok), Toast.LENGTH_SHORT).show();
finish();
}
});
} catch (Exception e) {
e.printStackTrace();
runOnUiThread(new Runnable() {
@Override
public void run() {
simpleProgressBar.setVisibility(View.INVISIBLE);
Toast.makeText(getApplicationContext(),getResources().getString(R.string.policy_error), Toast.LENGTH_SHORT).show();
}
});
//Toast.makeText(getApplicationContext(),getResources().getString(R.string.media_list_fail), Toast.LENGTH_SHORT).show();
}
}
});
setPrivate.start();
}
}

View file

@ -1,16 +1,14 @@
package asgardius.page.s3manager;
package asgardius.page.s3managermk2;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.app.AppOpsManager;
import android.app.PictureInPictureParams;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.view.MenuItem;
@ -32,12 +30,13 @@ import com.amazonaws.services.s3.model.ListObjectsRequest;
import com.amazonaws.services.s3.model.ObjectListing;
import com.amazonaws.services.s3.model.S3ObjectSummary;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
@ -47,16 +46,15 @@ public class ObjectSelect extends AppCompatActivity {
ArrayList Img;
//ArrayList object;
RecyclerView recyclerView;
String username, password, endpoint, bucket, prefix, location, pdfendpoint, query;
int treelevel;
String username, password, endpoint, bucket, prefix, location, pdfendpoint, query, policy;
boolean style, isplaylist;
String[] filename;
Region region;
S3ClientOptions s3ClientOptions;
AWSCredentials myCredentials;
AmazonS3 s3client;
ProgressBar simpleProgressBar;
int videocache, videotime, buffersize;
AppOpsManager appOpsManager;
int videocache, videotime, buffersize, treelevel, playlisttime;
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -67,12 +65,14 @@ public class ObjectSelect extends AppCompatActivity {
bucket = getIntent().getStringExtra("bucket");
location = getIntent().getStringExtra("region");
pdfendpoint = getIntent().getStringExtra("pdfendpoint");
style = getIntent().getBooleanExtra("style", false);
prefix = getIntent().getStringExtra("prefix");
treelevel = getIntent().getIntExtra("treelevel", 0);
videocache = getIntent().getIntExtra("videocache", 40);
videotime = getIntent().getIntExtra("videotime", 1);
playlisttime = getIntent().getIntExtra("playlisttime", 1);
buffersize = getIntent().getIntExtra("buffersize", 2000);
appOpsManager = (AppOpsManager)getSystemService(Context.APP_OPS_SERVICE);
isplaylist = getIntent().getBooleanExtra("isplaylist", false);
setContentView(R.layout.activity_object_select);
getSupportActionBar().setTitle(bucket+"/"+prefix);
region = Region.getRegion(location);
@ -81,12 +81,10 @@ public class ObjectSelect extends AppCompatActivity {
try {
s3client = new AmazonS3Client(myCredentials, region);
} catch (Exception e) {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.media_list_fail), Toast.LENGTH_SHORT).show();
Toast.makeText(getApplicationContext(),e.toString(), Toast.LENGTH_SHORT).show();
}
s3client.setEndpoint(endpoint);
if (!endpoint.contains(getResources().getString(R.string.aws_endpoint))) {
s3ClientOptions.setPathStyleAccess(true);
}
s3ClientOptions.setPathStyleAccess(style);
s3client.setS3ClientOptions(s3ClientOptions);
@ -126,28 +124,9 @@ public class ObjectSelect extends AppCompatActivity {
if (filename.length == treelevel+1) {
object.add(filename[treelevel]+"/");
}
else {
}
//i++;
}
while (result.isTruncated()) {
result = s3client.listNextBatchOfObjects (result);
od = result.getCommonPrefixes();
for (String os : od) {
filename = os.split("/");
if (filename.length == treelevel+1) {
object.add(filename[treelevel]+"/");
}
else {
}
//i++;
}
}
//This get file list
List<S3ObjectSummary> ob = result.getObjectSummaries();
for (S3ObjectSummary os : ob) {
@ -161,8 +140,23 @@ public class ObjectSelect extends AppCompatActivity {
//i++;
}
//Get next batch
while (result.isTruncated()) {
result = s3client.listNextBatchOfObjects (result);
//This get folder list
od = result.getCommonPrefixes();
for (String os : od) {
filename = os.split("/");
if (filename.length == treelevel+1) {
object.add(filename[treelevel]+"/");
}
//i++;
}
//This get file list
ob = result.getObjectSummaries();
for (S3ObjectSummary os : ob) {
filename = os.getKey().split("/");
@ -194,13 +188,15 @@ public class ObjectSelect extends AppCompatActivity {
else if (Name.get(i).toString().toLowerCase(Locale.ROOT).endsWith(".pdf")) {
Img.add(R.drawable.pdffile);
}
else if (Name.get(i).toString().toLowerCase(Locale.ROOT).endsWith(".jpg") || Name.get(i).toString().toLowerCase(Locale.ROOT).endsWith(".jpeg") || Name.get(i).toString().toLowerCase(Locale.ROOT).endsWith(".png") || Name.get(i).toString().toLowerCase(Locale.ROOT).endsWith(".gif")) {
else if (Name.get(i).toString().toLowerCase(Locale.ROOT).endsWith(".jpg") || Name.get(i).toString().toLowerCase(Locale.ROOT).endsWith(".jpeg")
|| Name.get(i).toString().toLowerCase(Locale.ROOT).endsWith(".png") || Name.get(i).toString().toLowerCase(Locale.ROOT).endsWith(".gif")
|| Name.get(i).toString().toLowerCase(Locale.ROOT).endsWith(".webp")) {
Img.add(R.drawable.imagefile);
}
else if (Name.get(i).toString().toLowerCase(Locale.ROOT).endsWith(".opus") || Name.get(i).toString().toLowerCase(Locale.ROOT).endsWith(".ogg")
|| Name.get(i).toString().toLowerCase(Locale.ROOT).endsWith(".oga") || Name.get(i).toString().toLowerCase(Locale.ROOT).endsWith(".mp3")
|| Name.get(i).toString().toLowerCase(Locale.ROOT).endsWith(".m4a") || Name.get(i).toString().toLowerCase(Locale.ROOT).endsWith(".flac")
|| Name.get(i).toString().toLowerCase(Locale.ROOT).endsWith(".mka")) {
|| Name.get(i).toString().toLowerCase(Locale.ROOT).endsWith(".mka") || Name.get(i).toString().toLowerCase(Locale.ROOT).endsWith(".m3u")) {
Img.add(R.drawable.audiofile);
}
else if(Name.get(i).toString().toLowerCase(Locale.ROOT).endsWith(".mp4") || Name.get(i).toString().toLowerCase(Locale.ROOT).endsWith(".mkv")
@ -237,10 +233,10 @@ public class ObjectSelect extends AppCompatActivity {
@Override
public void run() {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.media_list_fail), Toast.LENGTH_SHORT).show();
Toast.makeText(getApplicationContext(),e.toString(), Toast.LENGTH_SHORT).show();
}
});
//Toast.makeText(getApplicationContext(),getResources().getString(R.string.media_list_fail), Toast.LENGTH_SHORT).show();
//Toast.makeText(getApplicationContext(),e.toString(), Toast.LENGTH_SHORT).show();
finish();
}
}
@ -259,9 +255,9 @@ public class ObjectSelect extends AppCompatActivity {
try {
GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucket, prefix + Name.get(position).toString());
URL objectURL = s3client.generatePresignedUrl(request);
imageViewer(objectURL.toString());
imageViewer(objectURL.toString(), Name.get(position).toString());
} catch (Exception e) {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.media_list_fail), Toast.LENGTH_SHORT).show();
Toast.makeText(getApplicationContext(),e.toString(), Toast.LENGTH_SHORT).show();
}
} /*else if (Img.get(position).equals(R.drawable.textfile)) {
//load media file
@ -270,7 +266,7 @@ public class ObjectSelect extends AppCompatActivity {
URL objectURL = s3client.generatePresignedUrl(request);
textViewer(objectURL.toString());
} catch (Exception e) {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.media_list_fail), Toast.LENGTH_SHORT).show();
Toast.makeText(getApplicationContext(),e.toString(), Toast.LENGTH_SHORT).show();
}
}*/ else if (Img.get(position).equals(R.drawable.webpage) || Img.get(position).equals(R.drawable.ptextfile)) {
//load media file
@ -279,7 +275,7 @@ public class ObjectSelect extends AppCompatActivity {
URL objectURL = s3client.generatePresignedUrl(request);
webBrowser(objectURL.toString(), Name.get(position).toString());
} catch (Exception e) {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.media_list_fail), Toast.LENGTH_SHORT).show();
Toast.makeText(getApplicationContext(),e.toString(), Toast.LENGTH_SHORT).show();
}
} else if (Img.get(position).equals(R.drawable.pdffile)) {
//load media file
@ -315,62 +311,73 @@ public class ObjectSelect extends AppCompatActivity {
@Override
public void run() {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.media_list_fail), Toast.LENGTH_SHORT).show();
Toast.makeText(getApplicationContext(),e.toString(), Toast.LENGTH_SHORT).show();
}
});
//Toast.makeText(getApplicationContext(),getResources().getString(R.string.media_list_fail), Toast.LENGTH_SHORT).show();
//Toast.makeText(getApplicationContext(),e.toString(), Toast.LENGTH_SHORT).show();
finish();
}
}
});
if (pdfendpoint == null) {
if (pdfendpoint == null || pdfendpoint.equals("")) {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.pdf_reader_notready), Toast.LENGTH_SHORT).show();
} else {
pdfread.start();
}
} else if (Img.get(position).equals(R.drawable.audiofile) || Img.get(position).equals(R.drawable.videofile)) {
Thread mediaread = new Thread(new Runnable() {
simpleProgressBar.setVisibility(View.VISIBLE);
if (isplaylist && !Name.get(position).toString().toLowerCase(Locale.ROOT).endsWith(".m3u")) {
videoPlayer(null, Name.get(position).toString());
} else {
Thread mediaread = new Thread(new Runnable() {
@Override
public void run() {
try {
//load media file
Date expiration = new Date();
Calendar mycal = Calendar.getInstance();
mycal.setTime(expiration);
//System.out.println("today is " + mycal.getTime());
mycal.add(Calendar.HOUR, videotime);
//System.out.println("Expiration date: " + mycal.getTime());
expiration = mycal.getTime();
GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucket, prefix + Name.get(position).toString()).withExpiration(expiration);;
URL objectURL = s3client.generatePresignedUrl(request);
runOnUiThread(new Runnable() {
@Override
public void run() {
// Sending reference and data to Adapter
videoPlayer(objectURL.toString(), Name.get(position).toString().endsWith(".m3u8"));
@Override
public void run() {
try {
//load media file
Date expiration = new Date();
Calendar mycal = Calendar.getInstance();
mycal.setTime(expiration);
//System.out.println("today is " + mycal.getTime());
mycal.add(Calendar.HOUR, videotime);
//System.out.println("Expiration date: " + mycal.getTime());
expiration = mycal.getTime();
try {
policy = s3client.getBucketPolicy(bucket).getPolicyText();
} catch (Exception e) {
policy = null;
}
});
//System.out.println("tree "+treelevel);
//System.out.println("prefix "+prefix);
String objectURL = PolicyCheck.getFileKey(s3client, bucket, prefix + Name.get(position).toString(), expiration, policy);
/*GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucket, prefix + Name.get(position).toString()).withExpiration(expiration);;
URL objectURL = s3client.generatePresignedUrl(request);*/
} catch (Exception e) {
e.printStackTrace();
runOnUiThread(new Runnable() {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.media_list_fail), Toast.LENGTH_SHORT).show();
}
});
//Toast.makeText(getApplicationContext(),getResources().getString(R.string.media_list_fail), Toast.LENGTH_SHORT).show();
finish();
@Override
public void run() {
// Sending reference and data to Adapter
videoPlayer(objectURL, Name.get(position).toString());
}
});
//System.out.println("tree "+treelevel);
//System.out.println("prefix "+prefix);
} catch (Exception e) {
e.printStackTrace();
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(),e.toString(), Toast.LENGTH_SHORT).show();
}
});
//Toast.makeText(getApplicationContext(),e.toString(), Toast.LENGTH_SHORT).show();
finish();
}
}
}
});
mediaread.start();
});
mediaread.start();
}
} else {
Toast.makeText(ObjectSelect.this, getResources().getString(R.string.unsupported_file), Toast.LENGTH_SHORT).show();
}
@ -393,9 +400,21 @@ public class ObjectSelect extends AppCompatActivity {
//Toast.makeText(MainActivity.this, "You Clicked " + menuItem.getTitle(), Toast.LENGTH_SHORT).show();
if (menuItem.getTitle() == getResources().getString(R.string.upload_file_here)) {
//Toast.makeText(ObjectSelect.this, getResources().getString(R.string.pending_feature), Toast.LENGTH_SHORT).show();
upload();
upload(false);
} else if (menuItem.getTitle() == getResources().getString(R.string.upload_folder_here)) {
//Toast.makeText(ObjectSelect.this, getResources().getString(R.string.pending_feature), Toast.LENGTH_SHORT).show();
upload(true);
} else if (menuItem.getTitle() == getResources().getString(R.string.download_folder)) {
//Toast.makeText(ObjectSelect.this, getResources().getString(R.string.pending_feature), Toast.LENGTH_SHORT).show();
download(Name.get(position).toString(), true);
} else if (menuItem.getTitle() == getResources().getString(R.string.bucket_policy)) {
policyConfig(prefix + Name.get(position).toString(), Name.get(position).toString());
} else if (menuItem.getTitle() == getResources().getString(R.string.create_link)) {
share( Name.get(position).toString(), Img.get(position).equals(R.drawable.audiofile) || Img.get(position).equals(R.drawable.videofile));
} else if (menuItem.getTitle() == getResources().getString(R.string.object_info)) {
objectInfo(prefix + Name.get(position).toString());
objectInfo(prefix + Name.get(position).toString(), Name.get(position).toString());
} else if (menuItem.getTitle() == getResources().getString(R.string.copy_name)) {
copyName(Name.get(position).toString());
} else if (menuItem.getTitle() == getResources().getString(R.string.file_del)) {
if (Name.size() == 1 && treelevel >= 1) {
Toast.makeText(ObjectSelect.this, getResources().getString(R.string.only_item_onlist), Toast.LENGTH_SHORT).show();
@ -421,18 +440,21 @@ public class ObjectSelect extends AppCompatActivity {
//Toast.makeText(MainActivity.this, "You Clicked " + menuItem.getTitle(), Toast.LENGTH_SHORT).show();
if (menuItem.getTitle() == getResources().getString(R.string.download_file)) {
//Toast.makeText(ObjectSelect.this, getResources().getString(R.string.pending_feature), Toast.LENGTH_SHORT).show();
download(Name.get(position).toString());
download(Name.get(position).toString(), false);
} else if (menuItem.getTitle() == getResources().getString(R.string.bucket_policy)) {
policyConfig(prefix + Name.get(position).toString(), Name.get(position).toString());
} else if (menuItem.getTitle() == getResources().getString(R.string.upload_file_here)) {
//Toast.makeText(ObjectSelect.this, getResources().getString(R.string.pending_feature), Toast.LENGTH_SHORT).show();
upload();
upload(false);
} else if (menuItem.getTitle() == getResources().getString(R.string.upload_folder_here)) {
//Toast.makeText(ObjectSelect.this, getResources().getString(R.string.pending_feature), Toast.LENGTH_SHORT).show();
upload(true);
} else if (menuItem.getTitle() == getResources().getString(R.string.create_link)) {
if (Img.get(position).equals(R.drawable.audiofile) || Img.get(position).equals(R.drawable.videofile)) {
share(prefix + Name.get(position).toString(), true);
} else {
share(prefix + Name.get(position).toString(), false);
}
share(Name.get(position).toString(), Img.get(position).equals(R.drawable.audiofile) || Img.get(position).equals(R.drawable.videofile));
} else if (menuItem.getTitle() == getResources().getString(R.string.object_info)) {
objectInfo(prefix + Name.get(position).toString());
objectInfo(prefix + Name.get(position).toString(), Name.get(position).toString());
} else if (menuItem.getTitle() == getResources().getString(R.string.copy_name)) {
copyName(Name.get(position).toString());
} else if (menuItem.getTitle() == getResources().getString(R.string.file_del)) {
if (menuItem.getTitle() == getResources().getString(R.string.file_del)) {
if (Name.size() == 1 && treelevel >= 1) {
@ -452,16 +474,119 @@ public class ObjectSelect extends AppCompatActivity {
}));
}
private void videoPlayer(String url, boolean hls) {
private void videoPlayer(String url, String title) {
if (title.toLowerCase(Locale.ROOT).endsWith(".m3u")) {
Thread mediaread = new Thread(new Runnable() {
Intent intent = new Intent(this, VideoPlayer.class);
intent.putExtra("video_url", url);
intent.putExtra("videocache", videocache);
intent.putExtra("buffersize", buffersize);
intent.putExtra("hls", hls);
startActivity(intent);
@Override
public void run() {
try {
//load media file
ArrayList<String> links = getPlaylist(url);
ArrayList<String> medialist = new ArrayList<String>();
for (int i = 0; i < links.size(); i++) {
medialist.add(links.get(i).toString());
}
runOnUiThread(new Runnable() {
@Override
public void run() {
// Sending reference and data to Adapter
//videoPlayer(objectURL.toString(), Name.get(position).toString());
Intent intent = new Intent(getApplicationContext(), VideoPlayer.class);
intent.putExtra("video_url", url);
intent.putExtra("title", title);
intent.putExtra("videocache", videocache);
intent.putExtra("buffersize", buffersize);
intent.putExtra("isplaylist", true);
intent.putExtra("queue", links);
intent.putExtra("names", medialist);
simpleProgressBar.setVisibility(View.INVISIBLE);
startActivity(intent);
}
});
//System.out.println("tree "+treelevel);
//System.out.println("prefix "+prefix);
} catch (Exception e) {
e.printStackTrace();
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(),e.toString(), Toast.LENGTH_SHORT).show();
}
});
}
}
});
mediaread.start();
}
else if (isplaylist) {
Thread mediaread = new Thread(new Runnable() {
@Override
public void run() {
try {
//load media file
ArrayList<String> medialist = new ArrayList<String>();
for (int i = 0; i < Name.size(); i++) {
if (Img.get(i).equals(R.drawable.audiofile) || Img.get(i).equals(R.drawable.videofile)) {
medialist.add(Name.get(i).toString());
}
}
ArrayList<String> links = getLinks(medialist);
runOnUiThread(new Runnable() {
@Override
public void run() {
if(links != null) {
// Sending reference and data to Adapter
//videoPlayer(objectURL.toString(), Name.get(position).toString());
Intent intent = new Intent(getApplicationContext(), VideoPlayer.class);
intent.putExtra("video_url", url);
intent.putExtra("title", title);
intent.putExtra("videocache", videocache);
intent.putExtra("buffersize", buffersize);
intent.putExtra("isplaylist", isplaylist);
intent.putExtra("queue", links);
intent.putExtra("names", medialist);
simpleProgressBar.setVisibility(View.INVISIBLE);
startActivity(intent);
}
}
});
//System.out.println("tree "+treelevel);
//System.out.println("prefix "+prefix);
} catch (Exception e) {
e.printStackTrace();
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(),e.toString(), Toast.LENGTH_SHORT).show();
}
});
}
}
});
mediaread.start();
} else {
Intent intent = new Intent(this, VideoPlayer.class);
intent.putExtra("video_url", url);
intent.putExtra("title", title);
intent.putExtra("videocache", videocache);
intent.putExtra("buffersize", buffersize);
intent.putExtra("isplaylist", isplaylist);
simpleProgressBar.setVisibility(View.INVISIBLE);
startActivity(intent);
}
}
private void textViewer(String url) {
Intent intent = new Intent(this, TextViewer.class);
@ -470,10 +595,11 @@ public class ObjectSelect extends AppCompatActivity {
}
private void imageViewer(String url) {
private void imageViewer(String url, String title) {
Intent intent = new Intent(this, ImageViewer.class);
intent.putExtra("video_url", url);
intent.putExtra("title", title);
startActivity(intent);
}
@ -499,9 +625,12 @@ public class ObjectSelect extends AppCompatActivity {
intent.putExtra("treelevel", treelevel+1);
intent.putExtra("region", location);
intent.putExtra("pdfendpoint", pdfendpoint);
intent.putExtra("style", style);
intent.putExtra("videocache", videocache);
intent.putExtra("videotime", videotime);
intent.putExtra("buffersize", buffersize);
intent.putExtra("playlisttime", playlisttime);
intent.putExtra("isplaylist", isplaylist);
startActivity(intent);
}
@ -514,15 +643,18 @@ public class ObjectSelect extends AppCompatActivity {
intent.putExtra("username", username);
intent.putExtra("password", password);
intent.putExtra("bucket", bucket);
intent.putExtra("object", object);
intent.putExtra("object", prefix+object);
intent.putExtra("title", object);
intent.putExtra("region", location);
intent.putExtra("mediafile", mediafile);
intent.putExtra("videotime", videotime);
intent.putExtra("playlisttime", playlisttime);
intent.putExtra("style", style);
startActivity(intent);
}
private void objectInfo(String object) {
private void objectInfo(String object, String title) {
Intent intent = new Intent(this, ObjectInfo.class);
//treelevel ++;
@ -531,7 +663,9 @@ public class ObjectSelect extends AppCompatActivity {
intent.putExtra("password", password);
intent.putExtra("bucket", bucket);
intent.putExtra("object", object);
intent.putExtra("title", title);
intent.putExtra("region", location);
intent.putExtra("style", style);
startActivity(intent);
}
@ -613,10 +747,10 @@ public class ObjectSelect extends AppCompatActivity {
@Override
public void run() {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.media_list_fail), Toast.LENGTH_SHORT).show();
Toast.makeText(getApplicationContext(),e.toString(), Toast.LENGTH_SHORT).show();
}
});
//Toast.makeText(getApplicationContext(),getResources().getString(R.string.media_list_fail), Toast.LENGTH_SHORT).show();
//Toast.makeText(getApplicationContext(),e.toString(), Toast.LENGTH_SHORT).show();
finish();
}
}
@ -634,7 +768,7 @@ public class ObjectSelect extends AppCompatActivity {
dialog.show();
}
private void upload() {
private void upload(boolean isfolder) {
Intent intent = new Intent(this, Uploader.class);
intent.putExtra("endpoint", endpoint);
intent.putExtra("username", username);
@ -642,19 +776,94 @@ public class ObjectSelect extends AppCompatActivity {
intent.putExtra("bucket", bucket);
intent.putExtra("prefix", prefix);
intent.putExtra("region", location);
intent.putExtra("style", style);
intent.putExtra("isfolder", isfolder);
startActivity(intent);
}
private void download(String filename) {
private void download(String filename, boolean isfolder) {
Intent intent = new Intent(this, Downloader.class);
intent.putExtra("filename", filename);
if(isfolder) {
intent.putExtra("prefix", prefix+filename);
} else {
intent.putExtra("prefix", prefix);
intent.putExtra("filename", filename);
}
intent.putExtra("endpoint", endpoint);
intent.putExtra("username", username);
intent.putExtra("password", password);
intent.putExtra("prefix", prefix);
intent.putExtra("region", location);
intent.putExtra("style", style);
intent.putExtra("bucket", bucket);
intent.putExtra("isfolder", isfolder);
startActivity(intent);
}
private void policyConfig(String filename, String title) {
Intent intent = new Intent(this, ObjectPolicy.class);
intent.putExtra("endpoint", endpoint);
intent.putExtra("username", username);
intent.putExtra("password", password);
intent.putExtra("bucket", bucket);
intent.putExtra("filename", filename);
intent.putExtra("region", location);
intent.putExtra("style", style);
intent.putExtra("title", title);
intent.putExtra("pdfendpoint", pdfendpoint);
startActivity(intent);
}
public void copyName (String name) {
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip;
if(name.endsWith("/")) {
clip = ClipData.newPlainText("name", name.replace("/", ""));
} else {
clip = ClipData.newPlainText("name", name);
}
clipboard.setPrimaryClip(clip);
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.S_V2) {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.copy_ok), Toast.LENGTH_SHORT).show();
}
}
public ArrayList<String> getLinks (ArrayList<String> medialist) throws InterruptedException {
ArrayList<String> links = new ArrayList<String>();
Date expiration = new Date();
Calendar mycal = Calendar.getInstance();
mycal.setTime(expiration);
//System.out.println("today is " + mycal.getTime());
mycal.add(Calendar.HOUR, playlisttime);
//System.out.println("Expiration date: " + mycal.getTime());
expiration = mycal.getTime();
for (int i = 0; i < medialist.size(); i++) {
//GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucket, prefix+medialist.get(i)).withExpiration(expiration);;
//links.add(s3client.generatePresignedUrl(request).toString());
links.add(PolicyCheck.getFileKey(s3client, bucket, prefix+medialist.get(i), expiration, policy));
}
return links;
}
public ArrayList<String> getPlaylist(String playlist) {
ArrayList<String> links = new ArrayList<String>();
try {
BufferedReader br = new BufferedReader(new InputStreamReader((new URL(playlist).openStream())));
String strLine;
//Read File Line By Line
while ((strLine = br.readLine()) != null) {
// Print the content on the console - do what you want to do
if(!strLine.startsWith("#")) {
links.add(strLine);
}
}
//Close the input stream
return links;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}

View file

@ -0,0 +1,46 @@
package asgardius.page.s3managermk2;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.GeneratePresignedUrlRequest;
import java.util.Date;
public class PolicyCheck {
public static String getFileKey(AmazonS3 s3client, String bucket, String object, Date expiration, String policy) {
try {
Boolean publicobject;
String fileKey = null;
publicobject = false;
if(policy.contains("arn:aws:s3:::"+bucket+"/*") && policy.contains("s3:GetObject")) {
publicobject = true;
} else if(policy.contains("s3:GetObject")) {
if((policy.contains("\"arn:aws:s3:::"+bucket+"/"+object+"\"") || policy.contains("\"arn:aws:s3:::"+bucket+"/"+object+"*\"") || policy.contains("\"arn:aws:s3:::"+bucket+"/"+object+"**\"")) && policy.contains("s3:GetObject")) {
publicobject = true;
} else {
String[] path = object.split("/");
String filepath = "";
for (int i = 0; i < path.length-1; i++) {
filepath = filepath+path[i]+"/";
//System.out.println(filepath);
if(policy.contains("\"arn:aws:s3:::"+bucket+"/"+filepath+"*\"") || policy.contains("\"arn:aws:s3:::"+bucket+"/"+filepath+"**\"")) {
publicobject = true;
i = path.length;
}
}
}
}
if(publicobject) {
fileKey = s3client.getUrl(bucket, object).toString();
} else {
GeneratePresignedUrlRequest request;
request = new GeneratePresignedUrlRequest(bucket, object).withExpiration(expiration);
fileKey = s3client.generatePresignedUrl(request).toString();
}
return fileKey;
} catch (Exception e) {
GeneratePresignedUrlRequest request;
request = new GeneratePresignedUrlRequest(bucket, object).withExpiration(expiration);
return s3client.generatePresignedUrl(request).toString();
}
}
}

View file

@ -1,4 +1,4 @@
package asgardius.page.s3manager;
package asgardius.page.s3managermk2;
import android.content.Context;
import android.view.GestureDetector;

View file

@ -0,0 +1,21 @@
package asgardius.page.s3managermk2;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
public class SdcardCheck {
public static boolean isInstalledOnSdCard(Context context) {
PackageManager pm = context.getPackageManager();
try {
PackageInfo pi = pm.getPackageInfo(context.getPackageName(), 0);
ApplicationInfo ai = pi.applicationInfo;
return (ai.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) == ApplicationInfo.FLAG_EXTERNAL_STORAGE;
} catch (PackageManager.NameNotFoundException e) {
// ignore
}
return false;
}
}

View file

@ -1,4 +1,4 @@
package asgardius.page.s3manager;
package asgardius.page.s3managermk2;
import android.annotation.SuppressLint;
import android.content.Intent;
@ -13,26 +13,36 @@ import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import asgardius.page.s3manager.databinding.ActivitySettingsBinding;
import com.google.android.exoplayer2.database.StandaloneDatabaseProvider;
import com.google.android.exoplayer2.upstream.cache.SimpleCache;
import com.google.android.material.switchmaterial.SwitchMaterial;
import java.io.File;
import asgardius.page.s3managermk2.databinding.ActivitySettingsBinding;
public class Settings extends AppCompatActivity {
private ActivitySettingsBinding binding;
MyDbHelper dbHelper;
SQLiteDatabase db;
String videocache, videotime, buffersize;
EditText vcachepick, vtimepick, bsizepick;
String videocache, videotime, buffersize, playlisttime;
EditText vcachepick, vtimepick, bsizepick, ptimepick;
Button saveprefs, about, clearcache;
SwitchMaterial isplaylist;
StandaloneDatabaseProvider standaloneDatabaseProvider;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivitySettingsBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
vcachepick = (EditText)findViewById(R.id.videocache);
vtimepick = (EditText)findViewById(R.id.videotime);
bsizepick = (EditText)findViewById(R.id.buffersize);
ptimepick = (EditText)findViewById(R.id.playlisttime);
dbHelper = new MyDbHelper(this);
isplaylist = (SwitchMaterial) findViewById(R.id.isplaylist);
Thread getprefs = new Thread(new Runnable() {
@Override
@ -56,7 +66,18 @@ public class Settings extends AppCompatActivity {
while (cursor.moveToNext()){
buffersize = (cursor.getString(0));
}
query = "SELECT value FROM preferences where setting='isplaylist'";
cursor = db.rawQuery(query,null);
while (cursor.moveToNext()){
isplaylist.setChecked(cursor.getString(0).equals("1"));
}
query = "SELECT value FROM preferences where setting='playlisttime'";
cursor = db.rawQuery(query,null);
while (cursor.moveToNext()){
playlisttime = (cursor.getString(0));
}
db.close();
runOnUiThread(new Runnable() {
@SuppressLint("SetTextI18n")
@ -65,6 +86,7 @@ public class Settings extends AppCompatActivity {
vcachepick.setText(videocache);
vtimepick.setText(videotime);
bsizepick.setText(buffersize);
ptimepick.setText(playlisttime);
}
});
} catch (Exception e) {
@ -83,8 +105,28 @@ public class Settings extends AppCompatActivity {
});
getprefs.start();
clearcache = (Button)findViewById(R.id.clearcache);
clearcache.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
//buttonaction
try {
standaloneDatabaseProvider = new StandaloneDatabaseProvider(getApplicationContext());
SimpleCache.delete(new File(getApplicationContext().getFilesDir(), "media"), standaloneDatabaseProvider);
SimpleCache.delete(new File(getApplicationContext().getExternalFilesDirs(null)[getApplicationContext().getExternalFilesDirs(null).length-1], "media"), standaloneDatabaseProvider);
standaloneDatabaseProvider.close();
Toast.makeText(getApplicationContext(),getResources().getString(R.string.clearcache_ok), Toast.LENGTH_SHORT).show();
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(),getResources().getString(R.string.broken_database), Toast.LENGTH_SHORT).show();
}
//This launch account add screen
//addaccount(false);
}
});
//This is to add new user account
Button saveprefs = (Button)findViewById(R.id.saveprefs);
saveprefs = (Button)findViewById(R.id.saveprefs);
saveprefs.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
@ -93,19 +135,26 @@ public class Settings extends AppCompatActivity {
videocache = vcachepick.getText().toString();
videotime = vtimepick.getText().toString();
buffersize = bsizepick.getText().toString();
playlisttime = ptimepick.getText().toString();
if (videocache.equals("") || videotime.equals("") || buffersize.equals("")) {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.accountadd_null), Toast.LENGTH_SHORT).show();
} else if (videocache.equals("0") || videotime.equals("0")) {
} else if (videocache.equals("0") || videotime.equals("0") || playlisttime.equals("0")) {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.not_zero), Toast.LENGTH_SHORT).show();
} else if (Integer.parseInt(buffersize) <= 2000) {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.buffersize_error), Toast.LENGTH_SHORT).show();
} else if (Integer.parseInt(videotime) > 168) {
} else if (Integer.parseInt(videotime) > 168 || Integer.parseInt(playlisttime) > 168) {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.invalid_expiration_date), Toast.LENGTH_SHORT).show();
} else {
db = dbHelper.getWritableDatabase();
db.execSQL("UPDATE preferences SET value='" + videocache + "' where setting='videocache'");
db.execSQL("UPDATE preferences SET value='" + videotime + "' where setting='videotime'");
db.execSQL("UPDATE preferences SET value='" + buffersize + "' where setting='buffersize'");
db.execSQL("UPDATE preferences SET value='" + playlisttime + "' where setting='playlisttime'");
if(isplaylist.isChecked()) {
db.execSQL("UPDATE preferences SET value='1' where setting='isplaylist'");
} else {
db.execSQL("UPDATE preferences SET value='0' where setting='isplaylist'");
}
db.close();
mainmenu();
}
@ -119,7 +168,7 @@ public class Settings extends AppCompatActivity {
});
//This is to view app credits
Button about = (Button)findViewById(R.id.settings_button);
about = (Button)findViewById(R.id.settings_button);
about.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
@ -129,6 +178,12 @@ public class Settings extends AppCompatActivity {
});
}
@Override
public void onDestroy() {
super.onDestroy();
}
private void aboutPage () {
Intent intent = new Intent(this, WebBrowser.class);
@ -139,7 +194,6 @@ public class Settings extends AppCompatActivity {
}
private void mainmenu() {
Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("EXIT", true);

View file

@ -0,0 +1,467 @@
package asgardius.page.s3managermk2;
import androidx.appcompat.app.AppCompatActivity;
import android.app.Activity;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.regions.Region;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.S3ClientOptions;
import com.amazonaws.services.s3.model.GeneratePresignedUrlRequest;
import com.amazonaws.services.s3.model.ListObjectsRequest;
import com.amazonaws.services.s3.model.ObjectListing;
import com.amazonaws.services.s3.model.S3ObjectSummary;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
public class Share extends AppCompatActivity {
String username, password, endpoint, bucket, object, location, title, objectlist, policy;
boolean mediafile, style, publicobject;
TextView expirationtext;
ProgressBar simpleProgressBar;
Region region;
S3ClientOptions s3ClientOptions;
AWSCredentials myCredentials;
AmazonS3 s3client;
ListObjectsRequest orequest;
Calendar mycal;
EditText datepick, hourpick, minutepick;
int date, hour, minute;
Button share, copylinks, savelinks;
GeneratePresignedUrlRequest request;
Date expiration;
URL objectURL;
Uri fileuri;
Intent intent;
int videotime, playlisttime;
public static String URLify(String str) {
str = str.trim();
int length = str.length();
int trueL = length;
if(str.contains(" ")) {
for(int i = 0; i < length; i++) {
if(str.charAt(i) == ' ') {
trueL = trueL + 2;
}
}
char[] oldArr = str.toCharArray();
char[] newArr = new char[trueL];
int x = 0;
for(int i = 0; i < length; i++) {
if(oldArr[i] == ' ') {
newArr[x] = '%';
newArr[x+1] = '2';
newArr[x+2] = '0';
x += 3;
} else {
newArr[x] = oldArr[i];
x++;
}
}
str = new String(newArr, 0, trueL);
}
return str;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_share);
simpleProgressBar = (ProgressBar) findViewById(R.id.simpleProgressBar);
expirationtext = (TextView) findViewById(R.id.expirationtext);
mycal = Calendar.getInstance();
datepick = (EditText)findViewById(R.id.Date);
hourpick = (EditText)findViewById(R.id.Hour);
minutepick = (EditText)findViewById(R.id.Minute);
share = (Button)findViewById(R.id.share);
copylinks = (Button)findViewById(R.id.copy_links);
savelinks = (Button)findViewById(R.id.save_links);
endpoint = getIntent().getStringExtra("endpoint");
username = getIntent().getStringExtra("username");
password = getIntent().getStringExtra("password");
bucket = getIntent().getStringExtra("bucket");
location = getIntent().getStringExtra("region");
style = getIntent().getBooleanExtra("style", false);
object = getIntent().getStringExtra("object");
mediafile = getIntent().getBooleanExtra("mediafile", false);
videotime = getIntent().getIntExtra("videotime", 1);
playlisttime = getIntent().getIntExtra("playlisttime", 1);
title = getIntent().getStringExtra("title");
getSupportActionBar().setTitle(title);
region = Region.getRegion(location);
s3ClientOptions = S3ClientOptions.builder().build();
myCredentials = new BasicAWSCredentials(username, password);
try {
s3client = new AmazonS3Client(myCredentials, region);
} catch (Exception e) {
Toast.makeText(getApplicationContext(),e.toString(), Toast.LENGTH_SHORT).show();
}
s3client.setEndpoint(endpoint);
s3ClientOptions.setPathStyleAccess(style);
s3client.setS3ClientOptions(s3ClientOptions);
Thread getPolicy = new Thread(new Runnable() {
@Override
public void run() {
try {
//Your code goes here
policy = s3client.getBucketPolicy(bucket).getPolicyText();
publicobject = false;
if(policy.contains("arn:aws:s3:::"+bucket+"/*") && policy.contains("s3:GetObject")) {
publicobject = true;
} else if(policy.contains("s3:GetObject")) {
if((policy.contains("\"arn:aws:s3:::"+bucket+"/"+object+"\"") || policy.contains("\"arn:aws:s3:::"+bucket+"/"+object+"*\"") || policy.contains("\"arn:aws:s3:::"+bucket+"/"+object+"**\"")) && policy.contains("s3:GetObject")) {
publicobject = true;
} else {
String[] path = object.split("/");
String filepath = "";
for (int i = 0; i < path.length-1; i++) {
filepath = filepath+path[i]+"/";
//System.out.println(filepath);
if(policy.contains("\"arn:aws:s3:::"+bucket+"/"+filepath+"*\"") || policy.contains("\"arn:aws:s3:::"+bucket+"/"+filepath+"**\"")) {
publicobject = true;
i = path.length;
}
}
}
}
//System.out.println(policy);
runOnUiThread(new Runnable() {
@Override
public void run() {
//Your code goes here
if(publicobject){
expirationtext.setText(getResources().getString(R.string.expiration_not_required));
} else {
datepick.setEnabled(true);
hourpick.setEnabled(true);
minutepick.setEnabled(true);
expirationtext.setText(getResources().getString(R.string.expiration_time));
}
if(object == null || object.endsWith("/")) {
copylinks.setVisibility(View.VISIBLE);
savelinks.setVisibility(View.VISIBLE);
} else {
share.setVisibility(View.VISIBLE);
copylinks.setVisibility(View.VISIBLE);
}
simpleProgressBar.setVisibility(View.INVISIBLE);
}
});
} catch (Exception e) {
e.printStackTrace();
runOnUiThread(new Runnable() {
@Override
public void run() {
publicobject = false;
datepick.setEnabled(true);
hourpick.setEnabled(true);
minutepick.setEnabled(true);
expirationtext.setText(getResources().getString(R.string.expiration_time));
if(object == null || object.endsWith("/")) {
copylinks.setVisibility(View.VISIBLE);
savelinks.setVisibility(View.VISIBLE);
} else {
share.setVisibility(View.VISIBLE);
copylinks.setVisibility(View.VISIBLE);
}
simpleProgressBar.setVisibility(View.INVISIBLE);
}
});
//Toast.makeText(getApplicationContext(),getResources().getString(R.string.media_list_fail), Toast.LENGTH_SHORT).show();
}
}
});
getPolicy.start();
share.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
//buttonaction
try {
sharefile();
//System.out.println(URLify(objectURL.toString()));
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
shareIntent.putExtra(Intent.EXTRA_TEXT, URLify(objectURL.toString()));
startActivity(Intent.createChooser(shareIntent, "choose one"));
} catch (Exception e) {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.invalid_expiration_date), Toast.LENGTH_SHORT).show();
}
}
});
copylinks.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
//buttonaction
if(object == null || object.endsWith("/")) {
simpleProgressBar.setVisibility(View.VISIBLE);
}
Thread copyLinks = new Thread(new Runnable() {
@Override
public void run() {
try {
//load media file
if(object == null || object.endsWith("/")) {
getLinks();
runOnUiThread(new Runnable() {
@Override
public void run() {
// Sending reference and data to Adapter
simpleProgressBar.setVisibility(View.INVISIBLE);
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip;
clip = ClipData.newPlainText("name", objectlist);
clipboard.setPrimaryClip(clip);
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.S_V2) {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.copy_ok), Toast.LENGTH_SHORT).show();
}
}
});
} else {
sharefile();
runOnUiThread(new Runnable() {
@Override
public void run() {
// Sending reference and data to Adapter
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip;
clip = ClipData.newPlainText("name", URLify(objectURL.toString()));
clipboard.setPrimaryClip(clip);
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.S_V2) {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.copy_ok), Toast.LENGTH_SHORT).show();
}
}
});
}
//System.out.println("tree "+treelevel);
//System.out.println("prefix "+prefix);
} catch (Exception e) {
e.printStackTrace();
runOnUiThread(new Runnable() {
@Override
public void run() {
simpleProgressBar.setVisibility(View.INVISIBLE);
Toast.makeText(getApplicationContext(),getResources().getString(R.string.invalid_expiration_date), Toast.LENGTH_SHORT).show();
}
});
}
}
});
copyLinks.start();
}
});
savelinks.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
//buttonaction
performFileSearch("Select download location");
}
});
}
private void performFileSearch(String messageTitle) {
//uri = Uri.parse("content://com.android.externalstorage.documents/document/home");
intent = new Intent();
intent.setAction(Intent.ACTION_CREATE_DOCUMENT);
//intent.addCategory(Intent.CATEGORY_OPENABLE);
//intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
//intent.putExtra("android.provider.extra.INITIAL_URI", uri);
intent.putExtra(Intent.EXTRA_TITLE, "links.txt");
intent.setType("*/*");
((Activity) this).startActivityForResult(intent, 70);
}
@Override
public void onActivityResult(int requestCode, int resultCode, final Intent resultData) {
// The ACTION_OPEN_DOCUMENT intent was sent with the request code OPEN_DIRECTORY_REQUEST_CODE.
// If the request code seen here doesn't match, it's the response to some other intent,
// and the below code shouldn't run at all.
super.onActivityResult(requestCode, resultCode, resultData);
if (requestCode == 70) {
if (resultCode == Activity.RESULT_OK) {
// The document selected by the user won't be returned in the intent.
// Instead, a URI to that document will be contained in the return intent
// provided to this method as a parameter. Pull that uri using "resultData.getData()"
if (resultData != null && resultData.getData() != null) {
fileuri = resultData.getData();
System.out.println(fileuri.toString());
savelinks();
//System.out.println("File selected successfully");
//System.out.println("content://com.android.externalstorage.documents"+file.getPath());
} else {
Toast.makeText(Share.this, getResources().getString(R.string.file_path_fail), Toast.LENGTH_SHORT).show();
finish();
}
} else {
//System.out.println("User cancelled file browsing {}");
finish();
}
}
}
private void getLinks() {
if (datepick.getText().toString().equals("")) {
date = 0;
} else {
date = Integer.parseInt(datepick.getText().toString());
}
if (hourpick.getText().toString().equals("")) {
hour = 0;
} else {
hour = Integer.parseInt(hourpick.getText().toString());
}
if (minutepick.getText().toString().equals("")) {
minute = 0;
} else {
minute = Integer.parseInt(minutepick.getText().toString());
}
expiration = new Date();
//System.out.println("today is " + mycal.getTime());
mycal.setTime(expiration);
if (date == 0 && hour == 0 && minute == 0) {
mycal.add(Calendar.HOUR, playlisttime);
} else {
mycal.add(Calendar.DATE, date);
mycal.add(Calendar.HOUR, hour);
mycal.add(Calendar.MINUTE, minute);
}
//System.out.println("Expiration date: " + mycal.getTime());
expiration = mycal.getTime();
//System.out.println(expiration);
if (object == null) {
orequest = new ListObjectsRequest().withBucketName(bucket).withMaxKeys(1000);
} else {
orequest = new ListObjectsRequest().withBucketName(bucket).withPrefix(object).withMaxKeys(1000);
}
ObjectListing result = s3client.listObjects(orequest);
objectlist = "";
List<S3ObjectSummary> objects = result.getObjectSummaries();
for (S3ObjectSummary os : objects) {
objectlist = objectlist+PolicyCheck.getFileKey(s3client, bucket, os.getKey(), expiration, policy)+"\n";
}
while (result.isTruncated()) {
result = s3client.listNextBatchOfObjects (result);
objects = result.getObjectSummaries();
for (S3ObjectSummary os : objects) {
objectlist = objectlist+PolicyCheck.getFileKey(s3client, bucket, os.getKey(), expiration, policy)+"\n";
}
}
}
private void sharefile() {
if(publicobject) {
objectURL = s3client.getUrl(bucket, object);
} else {
if (datepick.getText().toString().equals("")) {
date = 0;
} else {
date = Integer.parseInt(datepick.getText().toString());
}
if (hourpick.getText().toString().equals("")) {
hour = 0;
} else {
hour = Integer.parseInt(hourpick.getText().toString());
}
if (minutepick.getText().toString().equals("")) {
minute = 0;
} else {
minute = Integer.parseInt(minutepick.getText().toString());
}
expiration = new Date();
//System.out.println("today is " + mycal.getTime());
mycal.setTime(expiration);
if (date == 0 && hour == 0 && minute == 0) {
if (mediafile) {
mycal.add(Calendar.HOUR, videotime);
} else {
mycal.add(Calendar.MINUTE, 15);
}
} else {
mycal.add(Calendar.DATE, date);
mycal.add(Calendar.HOUR, hour);
mycal.add(Calendar.MINUTE, minute);
}
//System.out.println("Expiration date: " + mycal.getTime());
expiration = mycal.getTime();
//System.out.println(expiration);
request = new GeneratePresignedUrlRequest(bucket, object).withExpiration(expiration);
objectURL = s3client.generatePresignedUrl(request);
}
}
private void savelinks() {
simpleProgressBar.setVisibility(View.VISIBLE);
Thread saveLinks = new Thread(new Runnable() {
@Override
public void run() {
try {
getLinks();
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(getContentResolver().openOutputStream(fileuri));
outputStreamWriter.write(objectlist);
outputStreamWriter.close();
runOnUiThread(new Runnable() {
@Override
public void run() {
// Sending reference and data to Adapter
simpleProgressBar.setVisibility(View.INVISIBLE);
Toast.makeText(getApplicationContext(),getResources().getString(R.string.save_ok), Toast.LENGTH_SHORT).show();
}
});
//System.out.println("tree "+treelevel);
//System.out.println("prefix "+prefix);
} catch (Exception e) {
e.printStackTrace();
runOnUiThread(new Runnable() {
@Override
public void run() {
simpleProgressBar.setVisibility(View.INVISIBLE);
Toast.makeText(getApplicationContext(),getResources().getString(R.string.invalid_expiration_date), Toast.LENGTH_SHORT).show();
}
});
}
}
});
saveLinks.start();
}
}

View file

@ -1,6 +1,4 @@
package asgardius.page.s3manager;
import androidx.appcompat.app.AppCompatActivity;
package asgardius.page.s3managermk2;
import android.os.Build;
import android.os.Bundle;
@ -9,18 +7,11 @@ import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.Toast;
import com.amazonaws.services.s3.model.ListObjectsRequest;
import com.amazonaws.services.s3.model.ObjectListing;
import com.amazonaws.services.s3.model.S3ObjectSummary;
import androidx.appcompat.app.AppCompatActivity;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.stream.Collectors;
public class TextViewer extends AppCompatActivity {
@ -66,11 +57,11 @@ public class TextViewer extends AppCompatActivity {
@Override
public void run() {
Toast.makeText(getApplicationContext(),getResources().getString(R.string.media_list_fail), Toast.LENGTH_SHORT).show();
Toast.makeText(getApplicationContext(),e.toString(), Toast.LENGTH_SHORT).show();
finish();
}
});
//Toast.makeText(getApplicationContext(),getResources().getString(R.string.media_list_fail), Toast.LENGTH_SHORT).show();
//Toast.makeText(getApplicationContext(),e.toString(), Toast.LENGTH_SHORT).show();
finish();
}
}

View file

@ -1,8 +1,9 @@
package asgardius.page.s3manager;
package asgardius.page.s3managermk2;
import static android.content.ContentValues.TAG;
import androidx.appcompat.app.AppCompatActivity;
import androidx.documentfile.provider.DocumentFile;
import android.annotation.SuppressLint;
import android.app.Activity;
@ -19,14 +20,18 @@ import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import com.amazonaws.AbortedException;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.regions.Region;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.S3ClientOptions;
import com.amazonaws.services.s3.model.AbortMultipartUploadRequest;
import com.amazonaws.services.s3.model.AmazonS3Exception;
import com.amazonaws.services.s3.model.CompleteMultipartUploadRequest;
import com.amazonaws.services.s3.model.InitiateMultipartUploadRequest;
import com.amazonaws.services.s3.model.InitiateMultipartUploadResult;
@ -46,9 +51,9 @@ import java.util.List;
public class Uploader extends AppCompatActivity {
String username, password, endpoint, bucket, prefix, location;
int progress;
Uri fileuri, folder;
EditText fprefix;
TextView fprefixlabel;
Region region;
S3ClientOptions s3ClientOptions;
AWSCredentials myCredentials;
@ -56,10 +61,13 @@ public class Uploader extends AppCompatActivity {
ProgressBar simpleProgressBar;
long filesize;
File ufile;
DocumentFile document;
Intent intent;
Button fileUpload;
Thread uploadFile, uploadProgress;
Thread uploadFile, uploadProgress, calculateProgress;
boolean style, isfolder;
boolean started = false;
boolean cancel = false;
long transfered = 0;
private static final long MAX_SINGLE_PART_UPLOAD_BYTES = 5 * 1024 * 1024;
private WifiManager.WifiLock mWifiLock;
@ -79,13 +87,19 @@ public class Uploader extends AppCompatActivity {
password = getIntent().getStringExtra("password");
bucket = getIntent().getStringExtra("bucket");
location = getIntent().getStringExtra("region");
style = getIntent().getBooleanExtra("style", false);
isfolder = getIntent().getBooleanExtra("isfolder", false);
prefix = getIntent().getStringExtra("prefix");
if(isfolder) {
getSupportActionBar().setTitle(getResources().getString(R.string.batch_upload_button));
} else {
getSupportActionBar().setTitle(getResources().getString(R.string.upload_button));
}
fprefix = (EditText)findViewById(R.id.fprefix);
fprefixlabel = (TextView) findViewById(R.id.fprefixlabel);
region = Region.getRegion(location);
s3ClientOptions = S3ClientOptions.builder().build();
if (!endpoint.contains(getResources().getString(R.string.aws_endpoint))) {
s3ClientOptions.setPathStyleAccess(true);
}
s3ClientOptions.setPathStyleAccess(style);
myCredentials = new BasicAWSCredentials(username, password);
s3client = new AmazonS3Client(myCredentials, region);
s3client.setEndpoint(endpoint);
@ -101,6 +115,7 @@ public class Uploader extends AppCompatActivity {
//buttonaction
if (started) {
started = false;
cancel = true;
uploadFile.interrupt();
//simpleProgressBar.setVisibility(View.INVISIBLE);
} else {
@ -122,22 +137,78 @@ public class Uploader extends AppCompatActivity {
}
//eUpload.setEnabled(false);
fileUpload.setText(getResources().getString(R.string.cancel_upload));
fprefix.setEnabled(false);
uploadFile = new Thread(new Runnable() {
@Override
public void run() {
//System.out.println(fkey);
progress = 0;
filesize = 0;
//filesize = 0;
try {
//Your code goes here
//s3client.createBucket(bucket, location);
//System.out.println(fkey);
ufile = readContentToFile(fileuri);
filesize = ufile.length();
//PutObjectRequest request = new PutObjectRequest(bucket, fkey, ufile);
//upload = s3client.putObject(request);
putS3Object(bucket, fprefix.getText().toString(), ufile);
if (isfolder) {
if(prefix.endsWith("/")) {
prefix = fprefix.getText().toString();
} else {
prefix = fprefix.getText().toString().concat("/");
}
document = DocumentFile.fromTreeUri(getApplicationContext(), fileuri);
DocumentFile[] filelist = document.listFiles();
ArrayList<String> filepath = new ArrayList<String>();
int treelevel = 0;
ArrayList<Integer> fileindex = new ArrayList<Integer>();
fileindex.add(0);
for (int i = 0; i < filelist.length && !cancel; i++) {
filepath.add(filelist[i].getName());
if(filelist[i].isDirectory()) {
treelevel++;
fileindex.add(0);
document = filelist[i];
filelist = document.listFiles();
while (treelevel >= 1 && fileindex.get(treelevel) < filelist.length+1 && !cancel) {
if(fileindex.get(treelevel) == filelist.length) {
fileindex.remove(treelevel);
document = document.getParentFile();
filelist = document.listFiles();
treelevel--;
filepath.remove(treelevel);
fileindex.set(treelevel, fileindex.get(treelevel)+1);
} else {
filepath.add(filelist[fileindex.get(treelevel)].getName());
if (filelist[fileindex.get(treelevel)].isDirectory()) {
document = filelist[fileindex.get(treelevel)];
filelist = document.listFiles();
treelevel++;
fileindex.add(0);
} else {
ufile = readContentToFile(filelist[fileindex.get(treelevel)].getUri());
putS3Object(bucket, prefix+String.join("/", filepath), ufile);
filepath.remove(treelevel);
fileindex.set(treelevel, fileindex.get(treelevel)+1);
}
}
}
} else {
ufile = readContentToFile(filelist[i].getUri());
putS3Object(bucket, prefix+String.join("/", filepath), ufile);
}
filepath.clear();
fileindex.clear();
fileindex.add(0);
}
} else {
ufile = readContentToFile(fileuri);
if(ufile.length()%MAX_SINGLE_PART_UPLOAD_BYTES == 0) {
filesize = ufile.length()/MAX_SINGLE_PART_UPLOAD_BYTES;
} else {
filesize = (ufile.length()/MAX_SINGLE_PART_UPLOAD_BYTES)+1;
}
//PutObjectRequest request = new PutObjectRequest(bucket, fkey, ufile);
//upload = s3client.putObject(request);
putS3Object(bucket, fprefix.getText().toString(), ufile);
}
runOnUiThread(new Runnable() {
@Override
@ -151,9 +222,17 @@ public class Uploader extends AppCompatActivity {
mWakeLock.release();
//System.out.println("WakeLock released");
}
simpleProgressBar.setProgress(100);
if(!cancel) {
simpleProgressBar.setProgress(100);
}
//simpleProgressBar.setVisibility(View.INVISIBLE);
fileUpload.setText(getResources().getString(R.string.upload_success));
if (cancel) {
fileUpload.setText(getResources().getString(R.string.upload_canceled));
} else if (isfolder) {
fileUpload.setText(getResources().getString(R.string.batch_upload_success));
} else {
fileUpload.setText(getResources().getString(R.string.upload_success));
}
started = false;
fileUpload.setEnabled(false);
//Toast.makeText(getApplicationContext(),getResources().getString(R.string.upload_success), Toast.LENGTH_SHORT).show();
@ -181,7 +260,12 @@ public class Uploader extends AppCompatActivity {
started = false;
//simpleProgressBar.setVisibility(View.INVISIBLE);
//fileUpload.setEnabled(true);
fileUpload.setText(getResources().getString(R.string.retry));
if (cancel) {
fileUpload.setText(getResources().getString(R.string.upload_canceled));
} else {
fileUpload.setText(getResources().getString(R.string.upload_failed));
}
fileUpload.setEnabled(false);
//Toast.makeText(getApplicationContext(),getResources().getString(R.string.media_list_fail), Toast.LENGTH_SHORT).show();
}
});
@ -253,16 +337,33 @@ public class Uploader extends AppCompatActivity {
private void performFileSearch(String messageTitle) {
//uri = Uri.parse("content://com.android.externalstorage.documents/document/home");
intent = new Intent();
intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
//intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
//intent.putExtra("android.provider.extra.INITIAL_URI", uri);
intent.setType("*/*");
if (isfolder) {
intent.setAction(Intent.ACTION_OPEN_DOCUMENT_TREE);
} else {
intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
//intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
//intent.putExtra("android.provider.extra.INITIAL_URI", uri);
intent.setType("*/*");
}
((Activity) this).startActivityForResult(intent, 100);
}
@SuppressLint("SetTextI18n")
@Override
public void onDestroy() {
if (!mWifiLock.isHeld()) {
mWifiLock.acquire();
//System.out.println("WifiLock acquired");
}
if (!mWakeLock.isHeld()) {
mWakeLock.acquire();
//System.out.println("WakeLock acquired");
}
super.onDestroy();
}
public void onActivityResult(int requestCode, int resultCode, final Intent resultData) {
// The ACTION_OPEN_DOCUMENT intent was sent with the request code OPEN_DIRECTORY_REQUEST_CODE.
// If the request code seen here doesn't match, it's the response to some other intent,
@ -276,7 +377,16 @@ public class Uploader extends AppCompatActivity {
if (resultData != null && resultData.getData() != null) {
fileuri = resultData.getData();
System.out.println(fileuri.toString());
fprefix.setText(prefix+getDisplayName(fileuri));
if (isfolder) {
fprefix.setText(prefix);
fprefix.setHint(getResources().getString(R.string.upload_prefix));
fprefixlabel.setText(getResources().getString(R.string.upload_prefix));
fileUpload.setText(getResources().getString(R.string.upload_calculate));
fileUpload.setEnabled(false);
calculateSize();
} else {
fprefix.setText(prefix+getDisplayName(fileuri));
}
//System.out.println("File selected successfully");
//System.out.println("content://com.android.externalstorage.documents"+file.getPath());
} else {
@ -331,6 +441,7 @@ public class Uploader extends AppCompatActivity {
PutObjectRequest request = new PutObjectRequest(bucket, objectKey, file);
PutObjectResult result = s3client.putObject(request);
long bytesPushed = result.getMetadata().getContentLength();
transfered++;
//LOGGER.info("Pushed {} bytes to s3://{}/{}", bytesPushed, bucket, objectKey);
}
@ -345,32 +456,120 @@ public class Uploader extends AppCompatActivity {
// Upload the file parts.
long fileOffset = 0;
for (int partNumber = 1; fileOffset < contentLength; ++partNumber) {
// Because the last part could be less than 5 MB, adjust the part size as needed.
partSize = Math.min(partSize, (contentLength - fileOffset));
try{
for (int partNumber = 1; fileOffset < contentLength && !cancel; ++partNumber) {
// Because the last part could be less than 5 MB, adjust the part size as needed.
partSize = Math.min(partSize, (contentLength - fileOffset));
// Create the request to upload a part.
UploadPartRequest uploadRequest = new UploadPartRequest()
.withBucketName(bucket)
.withKey(objectKey)
.withUploadId(initResponse.getUploadId())
.withPartNumber(partNumber)
.withFileOffset(fileOffset)
.withFile(file)
.withPartSize(partSize);
// Create the request to upload a part.
UploadPartRequest uploadRequest = new UploadPartRequest()
.withBucketName(bucket)
.withKey(objectKey)
.withUploadId(initResponse.getUploadId())
.withPartNumber(partNumber)
.withFileOffset(fileOffset)
.withFile(file)
.withPartSize(partSize);
// Upload the part and add the response's ETag to our list.
UploadPartResult uploadResult = s3client.uploadPart(uploadRequest);
//LOGGER.info("Uploading part {} of Object s3://{}/{}", partNumber, bucket, objectKey);
partETags.add(uploadResult.getPartETag());
// Upload the part and add the response's ETag to our list.
UploadPartResult uploadResult = s3client.uploadPart(uploadRequest);
//LOGGER.info("Uploading part {} of Object s3://{}/{}", partNumber, bucket, objectKey);
partETags.add(uploadResult.getPartETag());
fileOffset += partSize;
transfered = fileOffset;
fileOffset += partSize;
transfered++;
}
// Complete the multipart upload.
CompleteMultipartUploadRequest compRequest = new CompleteMultipartUploadRequest(bucket, objectKey, initResponse.getUploadId(), partETags);
s3client.completeMultipartUpload(compRequest);
} catch (AbortedException | AmazonS3Exception e) {
e.printStackTrace();
AbortMultipartUploadRequest abort = new AbortMultipartUploadRequest(bucket, objectKey, initResponse.getUploadId());
s3client.abortMultipartUpload(abort);
//Toast.makeText(getApplicationContext(),getResources().getString(R.string.media_list_fail), Toast.LENGTH_SHORT).show();
//finish();
}
}
// Complete the multipart upload.
CompleteMultipartUploadRequest compRequest = new CompleteMultipartUploadRequest(bucket, objectKey, initResponse.getUploadId(), partETags);
s3client.completeMultipartUpload(compRequest);
private void calculateSize() {
calculateProgress = new Thread(new Runnable() {
@Override
public void run() {
try {
//Your code goes here
document = DocumentFile.fromTreeUri(getApplicationContext(), fileuri);
DocumentFile[] filelist = document.listFiles();
ArrayList<String> filepath = new ArrayList<String>();
int treelevel = 0;
ArrayList<Integer> fileindex = new ArrayList<Integer>();
fileindex.add(0);
for (int i = 0; i < filelist.length; i++) {
filepath.add(filelist[i].getName());
if(filelist[i].isDirectory()) {
treelevel++;
fileindex.add(0);
document = filelist[i];
filelist = document.listFiles();
while (treelevel >= 1 && fileindex.get(treelevel) < filelist.length+1) {
if(fileindex.get(treelevel) == filelist.length) {
fileindex.remove(treelevel);
document = document.getParentFile();
filelist = document.listFiles();
treelevel--;
filepath.remove(treelevel);
fileindex.set(treelevel, fileindex.get(treelevel)+1);
} else {
filepath.add(filelist[fileindex.get(treelevel)].getName());
if (filelist[fileindex.get(treelevel)].isDirectory()) {
document = filelist[fileindex.get(treelevel)];
filelist = document.listFiles();
treelevel++;
fileindex.add(0);
} else {
filepath.remove(treelevel);
if(filelist[fileindex.get(treelevel)].length()%MAX_SINGLE_PART_UPLOAD_BYTES == 0) {
filesize = filesize+(filelist[fileindex.get(treelevel)].length()/MAX_SINGLE_PART_UPLOAD_BYTES);
} else {
filesize = filesize+((filelist[fileindex.get(treelevel)].length()/MAX_SINGLE_PART_UPLOAD_BYTES)+1);
}
fileindex.set(treelevel, fileindex.get(treelevel)+1);
}
}
}
//document = document.getParentFile();
//filelist = document.listFiles();
//treelevel--;
} else {
if(filelist[i].length()%MAX_SINGLE_PART_UPLOAD_BYTES == 0) {
filesize = filesize+(filelist[i].length()/MAX_SINGLE_PART_UPLOAD_BYTES);
} else {
filesize = filesize+((filelist[i].length()/MAX_SINGLE_PART_UPLOAD_BYTES)+1);
}
}
filepath.clear();
fileindex.clear();
fileindex.add(0);
}
runOnUiThread(new Runnable() {
@Override
public void run() {
fileUpload.setText(getResources().getString(R.string.batch_upload_button));
fileUpload.setEnabled(true);
}
});
} catch (Exception e) {
e.printStackTrace();
//Toast.makeText(getApplicationContext(),getResources().getString(R.string.media_list_fail), Toast.LENGTH_SHORT).show();
//finish();
}
}
});
calculateProgress.start();
}
}

View file

@ -1,4 +1,4 @@
package asgardius.page.s3manager;
package asgardius.page.s3managermk2;
import android.app.AppOpsManager;
import android.app.NotificationChannel;
@ -14,8 +14,10 @@ import android.os.Build;
import android.os.Bundle;
import android.os.PowerManager;
import android.support.v4.media.session.MediaSessionCompat;
import android.util.Rational;
import android.view.Display;
import android.view.View;
import android.view.WindowManager;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
@ -27,6 +29,7 @@ import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.PlaybackException;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Tracks;
import com.google.android.exoplayer2.audio.AudioAttributes;
import com.google.android.exoplayer2.database.StandaloneDatabaseProvider;
import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector;
@ -34,12 +37,13 @@ import com.google.android.exoplayer2.source.ProgressiveMediaSource;
import com.google.android.exoplayer2.ui.PlayerNotificationManager;
import com.google.android.exoplayer2.ui.StyledPlayerView;
import com.google.android.exoplayer2.upstream.DefaultHttpDataSource;
import com.google.android.exoplayer2.upstream.HttpDataSource;
import com.google.android.exoplayer2.upstream.cache.CacheDataSource;
import com.google.android.exoplayer2.upstream.cache.LeastRecentlyUsedCacheEvictor;
import com.google.android.exoplayer2.upstream.cache.SimpleCache;
import java.io.File;
import java.util.ArrayList;
import java.util.Objects;
/**
* An example full-screen activity that shows and hides the system UI (i.e.
@ -53,6 +57,7 @@ public class VideoPlayer extends AppCompatActivity {
private PowerManager.WakeLock mWakeLock;
private PowerManager powerManager;
private long maxCacheSize;
ArrayList<String> queue, names;
LeastRecentlyUsedCacheEvictor evictor;
StandaloneDatabaseProvider standaloneDatabaseProvider;
SimpleCache simpleCache;
@ -68,14 +73,18 @@ public class VideoPlayer extends AppCompatActivity {
AppOpsManager appOpsManager;
private PlayerNotificationManager playerNotificationManager;
private int notificationId = 1234;
boolean hls;
boolean isplaylist;
boolean success = false;
String videoURL;
String videoURL, title;
Rational ratio;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video_player);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
getWindow().getAttributes().layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
}
if(Build.VERSION.SDK_INT >=Build.VERSION_CODES.O){
NotificationChannel channel= new NotificationChannel("playback","Video Playback", NotificationManager.IMPORTANCE_DEFAULT);
@ -97,9 +106,13 @@ public class VideoPlayer extends AppCompatActivity {
mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "S3Manager:wake_lock");
//Get media url
videoURL = getIntent().getStringExtra("video_url");
title = getIntent().getStringExtra("title");
videocache = getIntent().getIntExtra("videocache", 40);
buffersize = getIntent().getIntExtra("buffersize", 2000);
hls = getIntent().getBooleanExtra("hls", false);
isplaylist = getIntent().getBooleanExtra("isplaylist", false);
queue = getIntent().getStringArrayListExtra("queue");
names = getIntent().getStringArrayListExtra("names");
getSupportActionBar().setTitle(title);
loadControl = new DefaultLoadControl.Builder().setBufferDurationsMs(2000, buffersize, 1500, 2000).build();
@DefaultRenderersFactory.ExtensionRendererMode int extensionRendererMode = DefaultRenderersFactory.EXTENSION_RENDERER_MODE_PREFER;
@ -114,17 +127,17 @@ public class VideoPlayer extends AppCompatActivity {
mediaSessionConnector.setPlayer(player);
mediaSession.setActive(true);
evictor = new LeastRecentlyUsedCacheEvictor(maxCacheSize);
simpleCache = new SimpleCache(
new File(this.getCacheDir(), "media"),
evictor,
standaloneDatabaseProvider);
mediaSource = new ProgressiveMediaSource.Factory(
new CacheDataSource.Factory()
.setCache(simpleCache)
.setUpstreamDataSourceFactory(new DefaultHttpDataSource.Factory()
.setUserAgent("ExoplayerDemo"))
.setFlags(CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR)
).createMediaSource(MediaItem.fromUri(Uri.parse(videoURL)));
if(SdcardCheck.isInstalledOnSdCard(this)) {
simpleCache = new SimpleCache(
new File(this.getExternalFilesDirs(null)[this.getExternalFilesDirs(null).length-1], "media"),
evictor,
standaloneDatabaseProvider);
} else {
simpleCache = new SimpleCache(
new File(this.getFilesDir(), "media"),
evictor,
standaloneDatabaseProvider);
}
playerView.setPlayer(player);
control = new StyledPlayerView.ControllerVisibilityListener() {
@Override
@ -144,15 +157,27 @@ public class VideoPlayer extends AppCompatActivity {
// Prepare the player.
player.setPlayWhenReady(true);
playerNotificationManager = new PlayerNotificationManager.Builder(this, notificationId, "playback").build();
playerNotificationManager.setUseNextActionInCompactView(true);
playerNotificationManager.setUsePreviousActionInCompactView(true);
playerNotificationManager.setMediaSessionToken(mediaSession.getSessionToken());
playerNotificationManager.setPlayer(player);
if (hls) {
MediaItem mediaItem = MediaItem.fromUri(videoURL);
player.setMediaItem(mediaItem);
if (isplaylist) {
for (int i = 0; i < queue.size(); i++) {
MediaItem mediaItem = MediaItem.fromUri(Share.URLify(queue.get(i)));
player.addMediaItem(mediaItem);
}
getSupportActionBar().setTitle(names.get(player.getCurrentMediaItemIndex()));
player.prepare();
try {
player.seekTo(names.indexOf(title), 0);
}catch (Exception e) {
System.out.println("Playing m3u file");
}
} else {
player.setMediaSource(mediaSource);
MediaItem mediaItem = MediaItem.fromUri(Share.URLify(videoURL));
player.setMediaItem(mediaItem);
player.prepare();
}
player.prepare();
// Start the playback.
player.play();
@ -164,20 +189,22 @@ public class VideoPlayer extends AppCompatActivity {
if(success) {
player.pause();
} else {
if (cause instanceof HttpDataSource.HttpDataSourceException) {
// An HTTP error occurred.
//System.out.println("Playback error F");
Toast.makeText(getApplicationContext(), getResources().getString(R.string.media_conn_fail), Toast.LENGTH_SHORT).show();
} else {
// An HTTP error occurred.
//System.out.println("Playback error F");
Toast.makeText(getApplicationContext(), getResources().getString(R.string.media_wrong_type), Toast.LENGTH_SHORT).show();
}
// An HTTP error occurred.
//System.out.println("Playback error F");
Toast.makeText(getApplicationContext(), Objects.requireNonNull(error.getCause()).toString(), Toast.LENGTH_SHORT).show();
player.release();
finish();
}
}
@Override
public void onTracksChanged(Tracks tracks) {
if(isplaylist) {
getSupportActionBar().setTitle(names.get(player.getCurrentMediaItemIndex()));
}
Player.Listener.super.onTracksChanged(tracks);
}
});
@ -231,6 +258,7 @@ public class VideoPlayer extends AppCompatActivity {
// Set the IMMERSIVE flag.
// Set the content to appear under the system bars so that the content
// doesn't resize when the system bars hide and show.
Objects.requireNonNull(getSupportActionBar()).hide();
View decorView = getWindow().getDecorView();
decorView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
@ -244,8 +272,8 @@ public class VideoPlayer extends AppCompatActivity {
private void showSystemBars() {
View decorView = getWindow().getDecorView();
decorView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
Objects.requireNonNull(getSupportActionBar()).show();
}
@ -262,7 +290,14 @@ public class VideoPlayer extends AppCompatActivity {
videoPosition = player.getCurrentPosition();
playerView.setUseController(false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
PictureInPictureParams params = new PictureInPictureParams.Builder().build();
if(player.getVideoFormat() != null) {
ratio = new Rational(Math.round(player.getVideoFormat().width*20*player.getVideoSize().pixelWidthHeightRatio), Math.round(player.getVideoFormat().height*20));
} else if(player.getAudioFormat() != null) {
ratio = new Rational(player.getAudioFormat().width, player.getAudioFormat().height);
} else {
ratio = new Rational(1, 1);
}
PictureInPictureParams params = new PictureInPictureParams.Builder().setAspectRatio(ratio).build();
this.enterPictureInPictureMode(params);
}else {
this.enterPictureInPictureMode();
@ -287,12 +322,22 @@ public class VideoPlayer extends AppCompatActivity {
@Override
public void onDestroy() {
if (mWifiLock.isHeld()) {
mWifiLock.release();
//System.out.println("WifiLock acquired");
}
if (mWakeLock.isHeld()) {
mWakeLock.release();
//System.out.println("WakeLock acquired");
}
mediaSessionConnector.setPlayer(null);
//deleteCache(this, standaloneDatabaseProvider);
mediaSession.setActive(false);
playerNotificationManager.setPlayer(null);
player.release();
playerView.setPlayer(null);
simpleCache.release();
standaloneDatabaseProvider.close();
super.onDestroy();
}
@ -302,6 +347,7 @@ public class VideoPlayer extends AppCompatActivity {
if (!playerView.getUseController()) {
playerView.setUseController(true);
}
hideSystemBars();
}
public void onUserLeaveHint() {
@ -311,35 +357,53 @@ public class VideoPlayer extends AppCompatActivity {
protected void onNewIntent(Intent intent) {
videoURL = intent.getStringExtra("video_url");
title = intent.getStringExtra("title");
videocache = intent.getIntExtra("videocache", 40);
buffersize = intent.getIntExtra("buffersize", 2000);
hls = intent.getBooleanExtra("hls", false);
mediaSource = new ProgressiveMediaSource.Factory(
new CacheDataSource.Factory()
.setCache(simpleCache)
.setUpstreamDataSourceFactory(new DefaultHttpDataSource.Factory()
.setUserAgent("ExoplayerDemo"))
.setFlags(CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR)
).createMediaSource(MediaItem.fromUri(Uri.parse(videoURL)));
if (hls) {
isplaylist = intent.getBooleanExtra("isplaylist", false);
queue = intent.getStringArrayListExtra("queue");
names = intent.getStringArrayListExtra("names");
getSupportActionBar().setTitle(title);
if (isplaylist) {
player.clearMediaItems();
for (int i = 0; i < queue.size(); i++) {
MediaItem mediaItem = MediaItem.fromUri(queue.get(i));
player.addMediaItem(mediaItem);
}
player.prepare();
player.seekTo(names.indexOf(title), 0);
} else {
MediaItem mediaItem = MediaItem.fromUri(videoURL);
player.setMediaItem(mediaItem);
} else {
player.setMediaSource(mediaSource);
player.prepare();
}
player.prepare();
// Start the playback.
player.play();
super.onNewIntent(intent);
}
public void onStop() {
if(isScreenOn(this)) {
finish();
try {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.S
&& this.getPackageManager()
.hasSystemFeature(
PackageManager.FEATURE_PICTURE_IN_PICTURE) && appOpsManager.checkOpNoThrow(
AppOpsManager.OPSTR_PICTURE_IN_PICTURE,
this.getPackageManager().getApplicationInfo(this.getPackageName(),
PackageManager.GET_META_DATA).uid, this.getPackageName())
== AppOpsManager.MODE_ALLOWED && isScreenOn(this) && this.isInPictureInPictureMode()) {
finish();
}
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
super.onStop();
}
/*static void deleteCache(Context context, StandaloneDatabaseProvider database) {
SimpleCache.delete(new File(context.getCacheDir(), "media"), database);
}*/
public void onBackPressed() {
try {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N

View file

@ -1,4 +1,4 @@
package asgardius.page.s3manager;
package asgardius.page.s3managermk2;
import androidx.appcompat.app.AppCompatActivity;

View file

@ -1,4 +1,4 @@
package asgardius.page.s3manager;
package asgardius.page.s3managermk2;
import androidx.appcompat.app.AppCompatActivity;

View file

@ -7,123 +7,137 @@
android:orientation="vertical"
tools:context=".AccountAdd">
<LinearLayout
android:id="@+id/aliasLayout"
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="10dp"
tools:ignore="MissingConstraints"
tools:layout_editor_absoluteX="20dp">
android:layout_height="wrap_content">
<EditText
android:id="@+id/alias"
android:layout_width="wrap_content"
android:layout_height="48dp"
android:layout_weight="1"
android:focusable="true"
android:hint="@string/accountadd_alias"
android:importantForAutofill="no"
android:inputType="text"
android:textColorHint="?attr/colorOnSecondary"
tools:ignore="MissingConstraints" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<EditText
android:id="@+id/pdfendpoint"
android:layout_width="wrap_content"
android:layout_height="48dp"
android:layout_weight="1"
android:focusable="true"
android:hint="@string/accountadd_pdfendpoint"
android:importantForAutofill="no"
android:inputType="textUri"
android:textColorHint="?attr/colorOnSecondary"
tools:ignore="MissingConstraints" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/accountadd_alias"
android:textAlignment="center"
android:textSize="25sp"/>
</LinearLayout>
<EditText
android:id="@+id/alias"
android:layout_width="match_parent"
android:layout_height="48dp"
android:focusable="true"
android:hint="@string/accountadd_alias"
android:inputType="text"
android:textColorHint="?attr/colorOnSecondary"/>
<LinearLayout
android:id="@+id/endpointLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="10dp"
tools:ignore="MissingConstraints"
tools:layout_editor_absoluteX="20dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/accountadd_pdfendpoint"
android:textAlignment="center"
android:textSize="25sp"/>
<EditText
android:id="@+id/endpoint"
android:layout_width="wrap_content"
android:layout_height="48dp"
android:layout_weight="1"
android:focusable="true"
android:hint="@string/accountadd_endpoint"
android:importantForAutofill="no"
android:inputType="textUri"
android:textColorHint="?attr/colorOnSecondary"
tools:ignore="MissingConstraints" />
<EditText
android:id="@+id/pdfendpoint"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_weight="1"
android:focusable="true"
android:hint="@string/accountadd_pdfendpoint"
android:inputType="textUri"
android:textColorHint="?attr/colorOnSecondary"/>
<EditText
android:id="@+id/region"
android:layout_width="wrap_content"
android:layout_height="48dp"
android:layout_weight="1"
android:focusable="true"
android:hint="@string/accountadd_region"
android:importantForAutofill="no"
android:inputType="textNoSuggestions"
android:textColorHint="?attr/colorOnSecondary"
tools:ignore="MissingConstraints" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/accountadd_endpoint"
android:textAlignment="center"
android:textSize="25sp"/>
</LinearLayout>
<EditText
android:id="@+id/endpoint"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_weight="1"
android:focusable="true"
android:hint="@string/accountadd_endpoint"
android:inputType="textUri"
android:textColorHint="?attr/colorOnSecondary"/>
<EditText
android:id="@+id/username"
android:layout_width="match_parent"
android:layout_height="48dp"
android:autofillHints="username"
android:focusable="true"
android:hint="@string/accountadd_username"
android:inputType="textNoSuggestions"
android:textColorHint="?attr/colorOnSecondary"
tools:ignore="MissingConstraints" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/accountadd_region"
android:textAlignment="center"
android:textSize="25sp"/>
<EditText
android:id="@+id/password"
android:layout_width="match_parent"
android:layout_height="48dp"
android:autofillHints="username"
android:focusable="true"
android:hint="@string/accountadd_password"
android:inputType="textPassword"
android:textColorHint="?attr/colorOnSecondary"
tools:ignore="MissingConstraints" />
<EditText
android:id="@+id/region"
android:layout_width="match_parent"
android:layout_height="48dp"
android:focusable="true"
android:hint="@string/accountadd_region"
android:inputType="textNoSuggestions"
android:textColorHint="?attr/colorOnSecondary"/>
<LinearLayout
android:id="@+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="80dp"
android:orientation="horizontal"
android:padding="10dp"
tools:ignore="MissingConstraints"
tools:layout_editor_absoluteX="20dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/accountadd_username"
android:textAlignment="center"
android:textSize="25sp"/>
<Button
android:id="@+id/addaccount"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="@string/accountadd_button"
tools:ignore="MissingConstraints" />
<EditText
android:id="@+id/username"
android:layout_width="match_parent"
android:layout_height="48dp"
android:autofillHints="username"
android:layout_weight="1"
android:focusable="true"
android:hint="@string/accountadd_username"
android:inputType="textNoSuggestions"
android:textColorHint="?attr/colorOnSecondary"/>
<Button
android:id="@+id/testaccount"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="@string/accounttest_button"
tools:ignore="MissingConstraints" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/accountadd_password"
android:textAlignment="center"
android:textSize="25sp"/>
</LinearLayout>
<EditText
android:id="@+id/password"
android:layout_width="match_parent"
android:layout_height="48dp"
android:autofillHints="password"
android:layout_weight="1"
android:focusable="true"
android:hint="@string/accountadd_password"
android:inputType="textPassword"
android:textColorHint="?attr/colorOnSecondary"/>
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/pathstyle"
android:layout_width="match_parent"
android:layout_height="70dp"
android:text="@string/path_style"
android:textSize="24sp" />
<Button
android:id="@+id/addaccount"
android:layout_width="match_parent"
android:layout_height="70dp"
android:text="@string/accountadd_button" />
<Button
android:id="@+id/testaccount"
android:layout_width="match_parent"
android:layout_height="70dp"
android:text="@string/accounttest_button" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>

View file

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".BucketPolicy">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:ignore="MissingConstraints">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/permission"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAlignment="center"
android:textSize="25sp"/>
<Button
android:id="@+id/set_public"
android:layout_width="match_parent"
android:layout_height="70dp"
android:text="@string/set_public"
android:visibility="gone" />
<Button
android:id="@+id/set_private"
android:layout_width="match_parent"
android:layout_height="70dp"
android:text="@string/set_private"
android:visibility="gone" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
<ProgressBar
android:id="@+id/simpleProgressBar"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:max="100"
android:progress="50"
android:padding="20dp"
tools:ignore="MissingConstraints"
android:indeterminate="true" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".CorsConfig">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:ignore="MissingConstraints">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/origins"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAlignment="center"
android:textSize="25sp"/>
<Button
android:id="@+id/allow_all"
android:layout_width="match_parent"
android:layout_height="70dp"
android:text="@string/allow_all"
android:visibility="gone" />
<Button
android:id="@+id/allow_pdf"
android:layout_width="match_parent"
android:layout_height="70dp"
android:text="@string/allow_pdf"
android:visibility="gone" />
<Button
android:id="@+id/delete_cors"
android:layout_width="match_parent"
android:layout_height="70dp"
android:text="@string/delete_cors"
android:visibility="gone" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
<ProgressBar
android:id="@+id/simpleProgressBar"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:max="100"
android:progress="50"
android:padding="20dp"
tools:ignore="MissingConstraints"
android:indeterminate="true" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
@ -7,42 +7,54 @@
android:orientation="vertical"
tools:context=".CreateBucket">
<TextView
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/set_bucket_name"
android:textAlignment="center"
android:textSize="30sp" />
android:layout_height="wrap_content">
<EditText
android:id="@+id/bname"
android:layout_width="match_parent"
android:layout_height="48dp"
android:focusable="true"
android:hint="@string/bucket_name"
android:importantForAutofill="no"
android:inputType="text"
android:textColorHint="?attr/colorOnSecondary"
tools:ignore="MissingConstraints" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:id="@+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="80dp"
android:orientation="horizontal"
android:padding="10dp"
tools:ignore="MissingConstraints"
tools:layout_editor_absoluteX="20dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/set_bucket_name"
android:textAlignment="center"
android:textSize="30sp" />
<Button
android:id="@+id/cbucket"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="@string/create_bucket"
tools:ignore="MissingConstraints" />
<EditText
android:id="@+id/bname"
android:layout_width="match_parent"
android:layout_height="48dp"
android:focusable="true"
android:hint="@string/bucket_name"
android:importantForAutofill="no"
android:inputType="text"
android:textColorHint="?attr/colorOnSecondary"
tools:ignore="MissingConstraints" />
</LinearLayout>
<LinearLayout
android:id="@+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="80dp"
android:orientation="horizontal"
android:padding="10dp"
tools:ignore="MissingConstraints"
tools:layout_editor_absoluteX="20dp">
<Button
android:id="@+id/cbucket"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="@string/create_bucket"
tools:ignore="MissingConstraints" />
</LinearLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
<ProgressBar
android:id="@+id/simpleProgressBar"
@ -55,4 +67,4 @@
android:visibility="invisible"
tools:ignore="MissingConstraints" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -4,9 +4,10 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/black"
tools:context=".ImageViewer">
<ImageView
<com.otaliastudios.zoom.ZoomImageView
android:id="@+id/imageViewer"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
@ -14,7 +15,9 @@
app:srcCompat="@drawable/empty"
tools:ignore="MissingConstraints"
tools:layout_editor_absoluteX="0dp"
tools:layout_editor_absoluteY="82dp" />
tools:layout_editor_absoluteY="82dp"
app:minZoom="1.0"
app:maxZoom="25.5" />
<ProgressBar
android:id="@+id/simpleProgressBar"

View file

@ -1,19 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
tools:context=".list_item">
<ImageView
android:id="@+id/image"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginTop="6dp"
android:layout_marginBottom="6dp"
android:layout_marginEnd="16dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@mipmap/ic_launcher" />
@ -22,7 +22,8 @@
android:id="@+id/imageinfo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="192dp"
android:layout_marginEnd="16dp"
android:layout_gravity="center"
android:text="TextView"
android:textSize="15sp"
android:textStyle="bold"
@ -31,4 +32,4 @@
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toEndOf="@+id/image"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>

View file

@ -7,48 +7,42 @@
android:orientation="vertical"
tools:context=".MainActivity">
<LinearLayout
android:id="@+id/linearLayout"
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="70dp"
android:layout_margin="20dp"
android:orientation="horizontal"
tools:ignore="MissingConstraints"
tools:layout_editor_absoluteX="20dp">
android:layout_height="wrap_content">
<Button
android:id="@+id/addaccount"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="@string/accountadd_button"
tools:ignore="MissingConstraints"
style="?android:attr/buttonStyle" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<Button
android:id="@+id/settings_button"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="@string/settings"
tools:ignore="MissingConstraints"
style="?android:attr/buttonStyle" />
<Button
android:id="@+id/addaccount"
android:layout_width="match_parent"
android:layout_height="70dp"
android:text="@string/accountadd_button" />
</LinearLayout>
<Button
android:id="@+id/settings_button"
android:layout_width="match_parent"
android:layout_height="70dp"
android:text="@string/settings" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/accountselect"
android:textAlignment="center"
android:textSize="25sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/accountselect"
android:textAlignment="center"
android:textSize="25sp" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/alist"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@string/account_list"
tools:layout_editor_absoluteX="27dp" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/alist"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@string/account_list"
tools:layout_editor_absoluteX="27dp" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
@ -7,6 +7,12 @@
android:orientation="vertical"
tools:context=".ObjectInfo">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
tools:ignore="MissingConstraints">
<TextView
android:id="@+id/size_info"
android:layout_width="match_parent"
@ -28,6 +34,8 @@
android:textAlignment="center"
android:textSize="25sp" />
</LinearLayout>
<ProgressBar
android:id="@+id/simpleProgressBar"
android:layout_width="fill_parent"
@ -38,4 +46,4 @@
tools:ignore="MissingConstraints"
android:indeterminate="true" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ObjectPolicy">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:ignore="MissingConstraints">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/permission"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAlignment="center"
android:textSize="25sp"/>
<Button
android:id="@+id/set_public"
android:layout_width="match_parent"
android:layout_height="70dp"
android:text="@string/set_public"
android:visibility="gone" />
<Button
android:id="@+id/set_private"
android:layout_width="match_parent"
android:layout_height="70dp"
android:text="@string/set_private"
android:visibility="gone" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
<ProgressBar
android:id="@+id/simpleProgressBar"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:max="100"
android:progress="50"
android:padding="20dp"
tools:ignore="MissingConstraints"
android:indeterminate="true" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -20,7 +20,8 @@
android:layout_height="wrap_content"
android:text="@string/videocache"
android:textAlignment="center"
android:textSize="25sp"/>
android:textSize="25sp"
android:visibility="gone" />
<EditText
android:id="@+id/videocache"
@ -29,7 +30,15 @@
android:focusable="true"
android:hint="@string/videocache"
android:inputType="number"
android:textColorHint="?attr/colorOnSecondary"/>
android:textColorHint="?attr/colorOnSecondary"
android:visibility="gone" />
<Button
android:id="@+id/clearcache"
android:layout_width="match_parent"
android:layout_height="70dp"
android:text="@string/clearcache"
android:visibility="gone" />
<TextView
android:layout_width="match_parent"
@ -65,21 +74,41 @@
android:inputType="number"
android:textColorHint="?attr/colorOnSecondary"/>
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/isplaylist"
android:layout_width="match_parent"
android:layout_height="70dp"
android:text="@string/playlist_playback"
android:textSize="24sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/playlisttime"
android:textAlignment="center"
android:textSize="25sp"/>
<EditText
android:id="@+id/playlisttime"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_weight="1"
android:focusable="true"
android:hint="@string/playlisttime"
android:inputType="number"
android:textColorHint="?attr/colorOnSecondary"/>
<Button
android:id="@+id/saveprefs"
android:layout_width="match_parent"
android:layout_height="70dp"
android:text="@string/save_settings"
android:textColor="?android:attr/colorBackground"
android:textSize="24sp" />
android:text="@string/save_settings" />
<Button
android:id="@+id/settings_button"
android:layout_width="match_parent"
android:layout_height="70dp"
android:text="@string/about_button"
android:textColor="?android:attr/colorBackground"
android:textSize="24sp" />
android:text="@string/about_button" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
@ -7,127 +7,108 @@
android:orientation="vertical"
tools:context=".Share">
<TextView
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/expiration_date"
android:textAlignment="center"
android:textSize="25sp" />
tools:ignore="MissingConstraints">
<LinearLayout
android:id="@+id/linearLayoutDate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="10dp"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/expirationtext"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAlignment="center"
android:textSize="25sp" />
<LinearLayout
android:id="@+id/linearLayoutDate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="10dp"
tools:ignore="MissingConstraints"
tools:layout_editor_absoluteX="20dp">
<EditText
android:id="@+id/Date"
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_weight="1"
android:focusable="true"
android:enabled="false"
android:hint="@string/share_date"
android:maxLength="1"
android:inputType="date"
android:textColorHint="?attr/colorOnSecondary"
tools:ignore="MissingConstraints" />
<EditText
android:id="@+id/Hour"
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_weight="1"
android:focusable="true"
android:enabled="false"
android:hint="@string/share_hour"
android:maxLength="2"
android:inputType="date"
android:textColorHint="?attr/colorOnSecondary"
tools:ignore="MissingConstraints" />
<EditText
android:id="@+id/Minute"
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_weight="1"
android:focusable="true"
android:enabled="false"
android:hint="@string/share_minute"
android:maxLength="2"
android:inputType="date"
android:textColorHint="?attr/colorOnSecondary"
tools:ignore="MissingConstraints" />
</LinearLayout>
<Button
android:id="@+id/share"
android:layout_width="match_parent"
android:layout_height="70dp"
android:text="@string/file_share"
android:visibility="gone"
tools:ignore="MissingConstraints" />
<Button
android:id="@+id/copy_links"
android:layout_width="match_parent"
android:layout_height="70dp"
android:text="@string/copy_links"
android:visibility="gone"
tools:ignore="MissingConstraints" />
<Button
android:id="@+id/save_links"
android:layout_width="match_parent"
android:layout_height="70dp"
android:text="@string/save_links"
android:visibility="gone"
tools:ignore="MissingConstraints" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
<ProgressBar
android:id="@+id/simpleProgressBar"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:max="100"
android:progress="50"
android:padding="20dp"
tools:ignore="MissingConstraints"
tools:layout_editor_absoluteX="20dp">
android:indeterminate="true" />
<EditText
android:id="@+id/Date"
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_weight="1"
android:focusable="true"
android:hint="@string/share_date"
android:maxLength="2"
android:inputType="date"
android:textColorHint="?attr/colorOnSecondary"
tools:ignore="MissingConstraints" />
<EditText
android:id="@+id/Month"
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_weight="1"
android:focusable="true"
android:hint="@string/share_month"
android:maxLength="2"
android:inputType="date"
android:textColorHint="?attr/colorOnSecondary"
tools:ignore="MissingConstraints" />
<EditText
android:id="@+id/Year"
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_weight="1"
android:focusable="true"
android:hint="@string/share_year"
android:maxLength="4"
android:inputType="date"
android:textColorHint="?attr/colorOnSecondary"
tools:ignore="MissingConstraints" />
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/expiration_time"
android:textAlignment="center"
android:textSize="25sp" />
<LinearLayout
android:id="@+id/linearLayoutTime"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="10dp"
tools:ignore="MissingConstraints"
tools:layout_editor_absoluteX="20dp">
<EditText
android:id="@+id/Hour"
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_weight="1"
android:focusable="true"
android:hint="@string/share_hour"
android:maxLength="2"
android:inputType="date"
android:textColorHint="?attr/colorOnSecondary"
tools:ignore="MissingConstraints" />
<EditText
android:id="@+id/Minute"
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_weight="1"
android:focusable="true"
android:hint="@string/share_minute"
android:maxLength="2"
android:inputType="date"
android:textColorHint="?attr/colorOnSecondary"
tools:ignore="MissingConstraints" />
</LinearLayout>
<LinearLayout
android:id="@+id/linearLayoutSubmit"
android:layout_width="match_parent"
android:layout_height="70dp"
android:layout_margin="20dp"
android:orientation="horizontal"
tools:ignore="MissingConstraints"
tools:layout_editor_absoluteX="20dp">
<Button
android:id="@+id/share"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="@string/file_share"
tools:ignore="MissingConstraints" />
<Button
android:id="@+id/open_in"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="@string/file_external"
tools:ignore="MissingConstraints" />
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -7,53 +7,66 @@
android:orientation="vertical"
tools:context=".Uploader">
<TextView
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/upload_key"
android:textAlignment="center"
android:textSize="30sp" />
android:layout_height="wrap_content">
<EditText
android:id="@+id/fprefix"
android:layout_width="match_parent"
android:layout_height="48dp"
android:focusable="true"
android:hint="@string/upload_key"
android:importantForAutofill="no"
android:inputType="text"
android:textColorHint="?attr/colorOnSecondary"
tools:ignore="MissingConstraints" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:id="@+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="80dp"
android:orientation="horizontal"
android:padding="10dp"
tools:ignore="MissingConstraints"
tools:layout_editor_absoluteX="20dp">
<TextView
android:id="@+id/fprefixlabel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/upload_key"
android:textAlignment="center"
android:textSize="30sp" />
<Button
android:id="@+id/fileupload"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="@string/upload_button"
tools:ignore="MissingConstraints" />
<EditText
android:id="@+id/fprefix"
android:layout_width="match_parent"
android:layout_height="48dp"
android:focusable="true"
android:hint="@string/upload_key"
android:importantForAutofill="no"
android:inputType="text"
android:textColorHint="?attr/colorOnSecondary"
tools:ignore="MissingConstraints" />
</LinearLayout>
<LinearLayout
android:id="@+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="80dp"
android:orientation="horizontal"
android:padding="10dp"
tools:ignore="MissingConstraints"
tools:layout_editor_absoluteX="20dp">
<ProgressBar
android:id="@+id/simpleProgressBar"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:indeterminate="false"
android:max="100"
android:padding="20dp"
android:progress="0"
android:visibility="invisible"
tools:ignore="MissingConstraints" />
<Button
android:id="@+id/fileupload"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="@string/upload_button"
tools:ignore="MissingConstraints" />
</LinearLayout>
<ProgressBar
android:id="@+id/simpleProgressBar"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:indeterminate="false"
android:max="100"
android:padding="20dp"
android:progress="0"
android:visibility="invisible"
tools:ignore="MissingConstraints" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>

View file

@ -1,46 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context=".Settings"
tools:showIn="@layout/activity_settings">
<LinearLayout
android:id="@+id/linearLayoutSubmit"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal"
tools:ignore="MissingConstraints"
tools:layout_editor_absoluteX="20dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/expiration_date"
android:textAlignment="center"
android:textSize="25sp" />
<Button
android:id="@+id/saveprefs"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="@string/accountadd_button"
tools:ignore="MissingConstraints"
style="?android:attr/buttonStyle" />
<Button
android:id="@+id/settings_button"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="@string/about_button"
tools:ignore="MissingConstraints"
style="?android:attr/buttonStyle" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>

View file

@ -5,6 +5,18 @@
android:id="@+id/upload_file"
android:title="@string/upload_file_tobucket" />
<item
android:id="@+id/upload_folder"
android:title="@string/upload_folder_tobucket" />
<item
android:id="@+id/download_bucket"
android:title="@string/download_bucket" />
<item
android:id="@+id/sharefile"
android:title="@string/create_link" />
<item
android:id="@+id/newbucket"
android:title="@string/create_bucket" />
@ -13,6 +25,18 @@
android:id="@+id/info"
android:title="@string/object_info" />
<item
android:id="@+id/copy_name"
android:title="@string/copy_name" />
<item
android:id="@+id/cors_config"
android:title="@string/cors_config" />
<item
android:id="@+id/acl_config"
android:title="@string/bucket_policy" />
<item
android:id="@+id/deletefolder"
android:title="@string/file_del" />

View file

@ -5,10 +5,30 @@
android:id="@+id/upload_file"
android:title="@string/upload_file_here" />
<item
android:id="@+id/upload_folder"
android:title="@string/upload_folder_here" />
<item
android:id="@+id/download_folder"
android:title="@string/download_folder" />
<item
android:id="@+id/sharefile"
android:title="@string/create_link" />
<item
android:id="@+id/info"
android:title="@string/object_info" />
<item
android:id="@+id/copy_name"
android:title="@string/copy_name" />
<item
android:id="@+id/acl_config"
android:title="@string/bucket_policy" />
<item
android:id="@+id/deletefolder"
android:title="@string/file_del" />

View file

@ -5,6 +5,10 @@
android:id="@+id/upload_file"
android:title="@string/upload_file_here" />
<item
android:id="@+id/upload_folder"
android:title="@string/upload_folder_here" />
<item
android:id="@+id/download_file"
android:title="@string/download_file" />
@ -17,6 +21,14 @@
android:id="@+id/info"
android:title="@string/object_info" />
<item
android:id="@+id/copy_name"
android:title="@string/copy_name" />
<item
android:id="@+id/acl_config"
android:title="@string/bucket_policy" />
<item
android:id="@+id/deletefile"
android:title="@string/file_del" />

View file

@ -11,6 +11,7 @@
<string name="bucket_name_empty">Se requiere un nombre para el bucket</string>
<string name="file_share">Compartir archivo</string>
<string name="download_file">Descargar archivo</string>
<string name="download_files">Descargar archivos</string>
<string name="cancel_download">Cancelar descarga</string>
<string name="download_success">Archivo descargado exitosamente</string>
<string name="upload_file_tobucket">Subir archivo en este bucket</string>
@ -18,12 +19,16 @@
<string name="feature_not_supported">Su dispositivo no es compatible con esta característica</string>
<string name="file_path_fail">No se encuentra el uri del archivo</string>
<string name="upload_button">Subir archivo</string>
<string name="batch_upload_button">Subir archivos</string>
<string name="upload_key">Nombre del objeto</string>
<string name="upload_prefix">Prefijo de los objetos</string>
<string name="no_file_selected">Favor de seleccionar un archivo</string>
<string name="upload_success">Archivo subido exitosamente</string>
<string name="batch_upload_success">Archivos subidos exitosamente</string>
<string name="cancel_upload">Cancelar subida</string>
<string name="retry">Reintentar</string>
<string name="download_failed">Descarga fallida</string>
<string name="upload_failed">Subida fallida</string>
<string name="success">Éxito</string>
<string name="create_bucket">Crear nuevo bucket</string>
<string name="create_bucket_success">Bucket creado exitosamente</string>
@ -57,25 +62,16 @@
<string name="accountsave_success">Cuenta editada exitosamente</string>
<string name="nosslwarning">No se permiten las conexiones sin SSL</string>
<string name="invalid_url">La URL del endpoint debe iniciar con https://</string>
<string name="explorer_test_button">Probar explorador de archivos</string>
<string name="unsupported_file">Tipo de archivo no soportado</string>
<string name="test_server_button">Conectar al servidor de pruebas</string>
<string name="media_conn_fail">No se pudo obtener el archivo remoto</string>
<string name="media_wrong_type">Archivo multimedia inválido</string>
<string name="media_list_fail">No se pudo conectar al servidor</string>
<string name="about_button">Acerca de esta app</string>
<string name="dummy_button">Botón de prueba</string>
<string name="dummy_content">Contenido de prueba</string>
<string name="accountadd_pdfendpoint">servidor pdfjs</string>
<string name="pdf_reader_notready">Necesita configurar un servidor pdf.js</string>
<string name="share_date">DD</string>
<string name="share_month">MM</string>
<string name="share_year">AAAA</string>
<string name="share_date">D</string>
<string name="share_hour">HH</string>
<string name="share_minute">MM</string>
<string name="expiration_date">Fecha de expiración</string>
<string name="expiration_time">Hora de expiración</string>
<string name="create_link">Crear enlace al archivo</string>
<string name="expiration_time">Expira dentro de</string>
<string name="create_link">Crear enlace</string>
<string name="invalid_expiration_date">La fecha de caducidad debe ser inferior a 7 días</string>
<string name="file_size">Tamaño del archivo</string>
<string name="object_info">Propiedades</string>
@ -85,13 +81,50 @@
<string name="file_count">Archivos</string>
<string name="null_expiration_date">Debe establecer una fecha de expiración para compartir archivos</string>
<string name="download_canceled">Descarga cancelada</string>
<string name="upload_canceled">Subida cancelada</string>
<string name="settings">Ajustes</string>
<string name="save_settings">Guardar ajustes</string>
<string name="videocache">Tamaño máximo de cache multimedia (en MiB)</string>
<string name="videotime">Tiempo de expiración para visor multimedia (en horas)</string>
<string name="playlist_playback">Habilitar listas de reproducción</string>
<string name="playlisttime">Tiempo de expiración para listas de reproducción (en horas)</string>
<string name="buffersize">Tamaño del buffer del reproductor multimedia (en milisegundos)</string>
<string name="buffersize_error">El tamaño del búfer debe ser de al menos 2001 milisegundos</string>
<string name="mediaplayer_multierror">Solo se puede reproducir un archivo multimedia a la vez</string>
<string name="playback_channel_name">Reproduccion de video</string>
<string name="not_zero">este valor no puede ser cero</string>
<string name="path_style">Acceso de estilo de ruta</string>
<string name="cors_config">Política CORS</string>
<string name="cors_status">Orígenes permitidos</string>
<string name="cors_all">Permitidos todos los orígenes</string>
<string name="cors_pdf">Uso de endpoint PDF permitido</string>
<string name="cors_npdf">Uso de endpoint PDF no permitido</string>
<string name="cors_none">Política CORS no encontrada</string>
<string name="allow_all">Permitir todo</string>
<string name="allow_pdf">Permitir pdf</string>
<string name="delete_cors">Eliminar CORS</string>
<string name="policy_error">No se pudo cambiar la política</string>
<string name="policy_ok">Política cambiada exitosamente</string>
<string name="download_bucket">Descargar contenido del bucket</string>
<string name="download_folder">Descargar contenido de la carpeta</string>
<string name="batch_download_success">Archivos descargados exitosamente</string>
<string name="copy_name">Copiar nombre al portapapeles</string>
<string name="copy_ok">Copiado al portapapeles</string>
<string name="upload_calculate">Calculando tamaño de la carpeta</string>
<string name="picture_too_big">Imagen demasiado grande</string>
<string name="save_links">Guardar enlaces en archivo</string>
<string name="copy_links">Copiar enlaces al potapapeles</string>
<string name="save_ok">Archivo guardado exitosamente</string>
<string name="bucket_policy">Permisos de acceso</string>
<string name="public_bucket">Bucket público</string>
<string name="private_bucket">Bucket privado</string>
<string name="public_object">Objeto público</string>
<string name="private_object">Objeto privado</string>
<string name="custom_policy">Política personalizada</string>
<string name="set_public">Establecer como público</string>
<string name="set_private">Establecer como privado</string>
<string name="parent_policy">Política establecida por carpeta padre</string>
<string name="expiration_not_required">Fecha de expiración no requerida</string>
<string name="clearcache">Limpiar Cache de Video</string>
<string name="clearcache_ok">Cache limpiada exitosamente</string>
</resources>

View file

@ -1,22 +1,18 @@
<resources>
<string name="app_name" translatable="false">S3 Manager</string>
<string name="aws_endpoint" translatable="false">.amazonaws.com</string>
<string name="endpoint_url" translatable="false">https://s3.asgardius.company</string>
<string name="pdf_reader" translatable="false">https://office.asgardius.company/pdfjs</string>
<string name="pdf_reader_notready">You need to setup a pdf.js server</string>
<string name="access_key" translatable="false">google</string>
<string name="account_list">Account list</string>
<string name="bucket_list">Bucket list</string>
<string name="object_list">Object list</string>
<string name="Image">Image</string>
<string name="expiration_date">Expiration date</string>
<string name="expiration_time">Expiration time</string>
<string name="expiration_time">Expires within</string>
<string name="share_hour">HH</string>
<string name="share_minute">MM</string>
<string name="share_date">DD</string>
<string name="share_month">MM</string>
<string name="share_year">YYYY</string>
<string name="create_link">Create file link</string>
<string name="share_date">D</string>
<string name="create_link">Create link</string>
<string name="invalid_expiration_date">Expiration date must be at most 7 days</string>
<string name="null_expiration_date">You must set an expiration date to share files</string>
<string name="broken_database">Local database is corrupted. Please reinstall this app</string>
@ -27,20 +23,29 @@
<string name="file_share">Share file</string>
<string name="file_external">Open in</string>
<string name="download_file">Download file</string>
<string name="download_files">Download files</string>
<string name="download_bucket">Download bucket content</string>
<string name="download_folder">Download folder content</string>
<string name="cancel_download">Cancel download</string>
<string name="download_success">File downloaded successfully</string>
<string name="batch_download_success">Files downloaded successfully</string>
<string name="upload_file_tobucket">Upload file to this bucket</string>
<string name="upload_folder_tobucket">Upload folder to this bucket</string>
<string name="feature_not_supported">Your device is not compatible with this feature</string>
<string name="file_path_fail">File uri not found</string>
<string name="upload_button">Upload file</string>
<string name="batch_upload_button">Upload files</string>
<string name="upload_key">Object name</string>
<string name="upload_prefix">Object prefix</string>
<string name="no_file_selected">Please select a file</string>
<string name="upload_success">File uploaded successfully</string>
<string name="batch_upload_success">Files uploaded successfully</string>
<string name="cancel_upload">Cancel Upload</string>
<string name="retry">Retry</string>
<string name="download_failed">Download failed</string>
<string name="download_canceled">Download canceled</string>
<string name="upload_failed">Upload failed</string>
<string name="upload_canceled">Upload canceled</string>
<string name="success">Success</string>
<string name="object_info">Properties</string>
<string name="file_size">File Size</string>
@ -80,22 +85,48 @@
<string name="accountsave_success">Account edited successfully</string>
<string name="nosslwarning">Connections without SSL are not allowed</string>
<string name="invalid_url">Endpoint URL must start with https://</string>
<string name="explorer_test_button">File Explorer Test</string>
<string name="unsupported_file">Unsupported file type</string>
<string name="test_server_button">Connect to test server</string>
<string name="media_conn_fail">Cannot retrieve remote file</string>
<string name="media_wrong_type">Invalid media file</string>
<string name="media_list_fail">Cannot connect to server</string>
<string name="about_button">About this app</string>
<string name="dummy_button">Dummy Button</string>
<string name="dummy_content">DUMMY\nCONTENT</string>
<string name="settings">Settings</string>
<string name="save_settings">Save settings</string>
<string name="videocache">Max media cache size (in MiB)</string>
<string name="videotime">Expiration time for media viewer (in hours)</string>
<string name="buffersize">Media player buffer size (in milliseconds)</string>
<string name="buffersize_error">Buffer size must be at least 2001 milliseconds</string>
<string name="playlist_playback">Enable playlists</string>
<string name="playlisttime">Expiration time for media playlists (in hours)</string>
<string name="mediaplayer_multierror">Only one media file can be played at once</string>
<string name="playback_channel_name">Video Playback</string>
<string name="not_zero">This value cannot be zero</string>
<string name="path_style">Path style access</string>
<string name="cors_config">CORS policy</string>
<string name="cors_status">Allowed origins</string>
<string name="cors_all">All origins allowed</string>
<string name="cors_pdf">PDF Endpoint allowed</string>
<string name="cors_npdf">PDF Endpoint not allowed</string>
<string name="cors_none">CORS policy not found</string>
<string name="allow_all">Allow all</string>
<string name="allow_pdf">Allow pdf</string>
<string name="delete_cors">Delete CORS</string>
<string name="policy_error">Cannot change policy</string>
<string name="policy_ok">Policy changed successfully</string>
<string name="copy_name">Copy name to clipboard</string>
<string name="copy_ok">Copied to clipboard</string>
<string name="upload_calculate">Calculating folder size</string>
<string name="picture_too_big">Picture too big</string>
<string name="save_links">Save links to file</string>
<string name="save_ok">File saved successfully</string>
<string name="copy_links">Copy links to clipboard</string>
<string name="bucket_policy">Access permissions</string>
<string name="public_bucket">Public bucket</string>
<string name="private_bucket">Private bucket</string>
<string name="public_object">Public object</string>
<string name="private_object">Private object</string>
<string name="custom_policy">Custom policy</string>
<string name="set_public">Set as public</string>
<string name="set_private">Set as private</string>
<string name="parent_policy">Policy set by parent folder</string>
<string name="expiration_not_required">Expiration date not required</string>
<string name="clearcache">Clear Video Cache</string>
<string name="clearcache_ok">Cache clean successfully</string>
</resources>

View file

@ -1,4 +1,4 @@
package asgardius.page.s3manager;
package asgardius.page.s3managermk2;
import org.junit.Test;

View file

@ -1,7 +1,7 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id 'com.android.application' version '7.3.1' apply false
id 'com.android.library' version '7.3.1' apply false
id 'com.android.application' version '8.5.2' apply false
id 'com.android.library' version '8.5.2' apply false
}
task clean(type: Delete) {

View file

@ -0,0 +1 @@
* Fix background playback issues

View file

@ -0,0 +1 @@
* Fix background playback issues

View file

@ -0,0 +1 @@
* UI fixes

View file

@ -0,0 +1,2 @@
* Account edit screen redesign
* Add option to choose between virtual host style and path style for buckets (virtual host will be used by default)

View file

@ -0,0 +1,2 @@
* CORS configuration (currently you can allow pdf endpoint, allow all origins or delete policy)
* Fixed UI issues when using app in free form mode

View file

@ -0,0 +1 @@
* Fixed Picture in Picture issue when playing anamorphic videos

View file

@ -0,0 +1 @@
* Fixed video being closed when app is on freeform mode

View file

@ -0,0 +1,3 @@
* Freeform mode improvements
* User interface more consistent
* File sharing easier to use

View file

@ -0,0 +1 @@
* Folder download function added

View file

@ -0,0 +1,3 @@
* UI fixes
* Copy file name to clipboard
* Folder upload function added

View file

@ -0,0 +1 @@
* Enhanced picture viewer

View file

@ -0,0 +1,2 @@
* Add option to play all media items on current folder
* Add option to share entire folders and save on clipboard or txt file

View file

@ -0,0 +1 @@
* Delete cached media when is not longer needed

View file

@ -0,0 +1 @@
* Fix app setting validation

View file

@ -0,0 +1 @@
* UI fixes

View file

@ -0,0 +1 @@
* UI fixes

View file

@ -0,0 +1 @@
* UI fixes

View file

@ -0,0 +1 @@
* UI fixes

View file

@ -0,0 +1,2 @@
* UI fixes
* Better support for notched devices

View file

@ -0,0 +1 @@
* Set bucket as public or private

View file

@ -0,0 +1 @@
* Set object as public or private

View file

@ -0,0 +1,3 @@
* Check policy per object at creating share links
* Cache reuse for public media files
* Button to remove media cache inside ths app

View file

@ -0,0 +1 @@
* Fix wakelock not being released at closing video player

View file

@ -0,0 +1 @@
* M3U Playlist support

View file

@ -0,0 +1 @@
* Fix UI issue at media player screen

View file

@ -0,0 +1 @@
* Libraries updated

View file

@ -0,0 +1 @@
* Upgrade libraries

View file

@ -0,0 +1 @@
* Allow move app to SD Card

View file

@ -0,0 +1,2 @@
* Dependencies upgraded
* Fixed large file list being truncate

View file

@ -3,7 +3,7 @@ File Explorer to manage servers compatible with S3 Object Storage Protocol
Current feature list
<li>Audio and Video playback (opus, ogg, oga, mp3, m4a, flac, mka, mkv, mp4, m4v, webm)</li>
<li>Picture preview (jpg, jpeg, png, gif)</li>
<li>Picture preview (jpg, jpeg, png, gif, webp)</li>
<li>Plain text file preview (txt, md)</li>
<li>Webpage viewer (htm, html)</li>
<li>Multiple account support</li>
@ -14,10 +14,15 @@ Current feature list
<li>Delete folders</li>
<li>File upload</li>
<li>File download</li>
<li>Download folder content</li>
<li>Upload folder content</li>
<li>pdf file reader using user provided pdf.js server</li>
<li>file sharing links</li>
<li>get object info</li>
<li>get bucket info</li>
<li>Set CORS policy</li>
<li>Set bucket as public or private</li>
<li>Set object as public or private</li>
Planned feature list
@ -40,17 +45,22 @@ Knnown issues
Known supported providers
<li>Amazon Web Services</li>
<li>Scaleway Elements (partial)</li>
<li>Oracle Cloud (partial)</li>
<li>Wasabi Cloud</li>
<li>MinIO</li>
<li>Scaleway Elements</li>
<li>Wasabi Cloud (Provider broke access control intentionally since March 13 2023)</li>
<li>Backblaze B2</li>
<li>Cloudflare R2 (partial)</li>
<li>MinIO **</li>
<li>Garage **</li>
Known not supported providers
<li>Google Cloud</li>
<li>Google Cloud (Not compatible with S3v4)</li>
<li>Oracle Cloud (compatibility issues with S3v4)</li>
** Extra steps required (read documentation)
Please report all issues at https://forum.asgardius.company/t/s3-manager
https://wiki-es.asgardius.company/index.php?title=Documentacion_Asgardius_S3_Manager
You can find app documentation at https://wiki-en.asgardius.company/index.php?title=Asgardius_S3_Manager_Documentation (english) or https://wiki-es.asgardius.company/index.php?title=Documentacion_Asgardius_S3_Manager (spanish)
This app has nonfreenet antifeature because its compatibility list.
You can use MinIO to have a FOSS selfhosted server to use with this app
You can use MinIO or Garage to have a FOSS selfhosted server to use with this app

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 312 KiB

After

Width:  |  Height:  |  Size: 317 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 548 KiB

After

Width:  |  Height:  |  Size: 1.2 MiB

View file

@ -18,4 +18,6 @@ android.useAndroidX=true
# Enables namespacing of each library's R class so that its R class includes only the
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true
android.nonTransitiveRClass=true
android.defaults.buildfeatures.buildconfig=true
android.nonFinalResIds=false

View file

@ -1,6 +1,6 @@
#Sat Aug 27 12:12:23 MST 2022
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME