Compare commits
16 Commits
Author | SHA1 | Date | |
---|---|---|---|
7bbf9eb8d7 | |||
f39ff35e93 | |||
7ce4b9830b | |||
6a460b2952 | |||
6a1ed20e07 | |||
96540f4a50 | |||
778415cf0b | |||
d87296a534 | |||
f6b652fb7e | |||
211fd26dca | |||
92e9c35584 | |||
3df644e6a8 | |||
5444d765e7 | |||
38eff704cd | |||
057038cca7 | |||
cba7fc2555 |
179
.gitea/workflows/publish.yml
Normal file
179
.gitea/workflows/publish.yml
Normal file
@ -0,0 +1,179 @@
|
||||
name: 🚀 Créer une nouvelle version
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: 'Nom du tag (ex: v1.2.3)'
|
||||
required: true
|
||||
build_apk:
|
||||
description: 'Compiler et publier l’APK ?'
|
||||
required: true
|
||||
default: 'oui'
|
||||
type: choice
|
||||
options:
|
||||
- oui
|
||||
- non
|
||||
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: 📦 Cloner le dépôt
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0 # important pour récupérer tout l'historique
|
||||
|
||||
- name: 🔧 Préparation de Git (tags)
|
||||
run: git fetch --tags
|
||||
|
||||
- name: 🏷️ Créer le tag si nécessaire
|
||||
run: |
|
||||
TAG="${{ github.event.inputs.tag }}"
|
||||
if git rev-parse "$TAG" >/dev/null 2>&1; then
|
||||
echo "Le tag $TAG existe déjà, pas besoin de le créer."
|
||||
else
|
||||
git config user.name "github-actions"
|
||||
git config user.email "github-actions@github.com"
|
||||
git tag "$TAG"
|
||||
git push origin "$TAG"
|
||||
fi
|
||||
|
||||
- name: 🔖 Détection du tag précédent
|
||||
id: tag-precedent
|
||||
run: |
|
||||
TARGET_TAG="${{ github.event.inputs.tag }}"
|
||||
TAGS=$(git tag --sort=creatordate)
|
||||
|
||||
if [ -z "$TAGS" ]; then
|
||||
echo "Aucun tag existant détecté."
|
||||
echo "tag_precedent=" >> $GITHUB_OUTPUT
|
||||
exit 0
|
||||
fi
|
||||
|
||||
PREV_TAG=""
|
||||
|
||||
for tag in $TAGS; do
|
||||
if [ "$tag" != "$TARGET_TAG" ]; then
|
||||
PREV_TAG=$tag
|
||||
else
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
echo "tag_precedent=$PREV_TAG" | tee -a $GITHUB_OUTPUT
|
||||
|
||||
- name: 📝 Liste des modifications
|
||||
id: changelog
|
||||
run: |
|
||||
PREV_TAG="${{ steps.tag-precedent.outputs.tag_precedent }}"
|
||||
TARGET_TAG="${{ github.event.inputs.tag }}"
|
||||
|
||||
if [ -z "$PREV_TAG" ]; then
|
||||
LOG=$(git log --oneline)
|
||||
else
|
||||
if git rev-parse "$TARGET_TAG" >/dev/null 2>&1; then
|
||||
LOG=$(git log "$PREV_TAG".."$TARGET_TAG" --oneline)
|
||||
else
|
||||
LOG=$(git log "$PREV_TAG"..HEAD --oneline)
|
||||
fi
|
||||
fi
|
||||
echo "$LOG"
|
||||
|
||||
echo "modifications<<EOF" >> $GITHUB_OUTPUT
|
||||
echo "$LOG" >> $GITHUB_OUTPUT
|
||||
echo "EOF" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: 📦 Création de la version sur Gitea
|
||||
id: creation-release
|
||||
env:
|
||||
REGISTRY_URL: ${{ vars.REGISTRY_URL }}
|
||||
REPO: ${{ vars.REGISTRY_REPOSITORY }}
|
||||
TOKEN: ${{ secrets.REGISTRY_PASSWORD }}
|
||||
COMMITS: ${{ steps.changelog.outputs.modifications }}
|
||||
run: |
|
||||
TAG_NAME="${{ github.event.inputs.tag }}"
|
||||
|
||||
# Échappement du contenu pour JSON
|
||||
DESCRIPTION="Changelog:"$'\n'"$COMMITS"
|
||||
ESCAPED_DESCRIPTION=$(printf '%s\n' "$DESCRIPTION" | jq -Rsa .)
|
||||
|
||||
REPONSE=$(curl -s -X POST "https://$REGISTRY_URL/api/v1/repos/$REPO/releases" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: token $TOKEN" \
|
||||
-d "{
|
||||
\"tag_name\": \"$TAG_NAME\",
|
||||
\"name\": \"Version $TAG_NAME\",
|
||||
\"body\": $ESCAPED_DESCRIPTION
|
||||
}")
|
||||
|
||||
echo "$REPONSE"
|
||||
|
||||
ID_RELEASE=$(echo "$REPONSE" | jq -r .id)
|
||||
echo "id_release=$ID_RELEASE" >> $GITHUB_OUTPUT
|
||||
|
||||
|
||||
- name: 🔍️ Extraire les informations de l’application
|
||||
id: extraire-info-gradle
|
||||
if: ${{ github.event.inputs.build_apk == 'oui' }}
|
||||
run: |
|
||||
APP_NAME=$(grep 'rootProject.name' settings.gradle | sed -E 's/.*= "(.*)"/\1/')
|
||||
COMPILE_SDK_VERSION=$(grep 'compileSdk' app/build.gradle | grep -oE '[0-9]+')
|
||||
|
||||
{
|
||||
echo "app_name=$APP_NAME"
|
||||
echo "sdk=$COMPILE_SDK_VERSION"
|
||||
} | tee -a $GITHUB_OUTPUT
|
||||
|
||||
- name: ☕ Configurer Java
|
||||
if: ${{ github.event.inputs.build_apk == 'oui' }}
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '17'
|
||||
|
||||
- name: 🤖 Installer Android SDK
|
||||
if: ${{ github.event.inputs.build_apk == 'oui' }}
|
||||
uses: android-actions/setup-android@v3
|
||||
with:
|
||||
api-level: ${{ steps.extraire-info-gradle.outputs.sdk }}
|
||||
build-tools-version: ${{ steps.extraire-info-gradle.outputs.sdk }}.0.3
|
||||
|
||||
- name: 🛠️ Compilation de l’application (APK)
|
||||
if: ${{ github.event.inputs.build_apk == 'oui' }}
|
||||
run: ./gradlew assembleRelease
|
||||
|
||||
- name: 🏷️ Renommer l’APK avec le nom de l’application et le tag
|
||||
id: renommer-apk
|
||||
if: ${{ github.event.inputs.build_apk == 'oui' }}
|
||||
run: |
|
||||
APP_NAME=${{ steps.extraire-info-gradle.outputs.app_name }}
|
||||
TAG=${{ github.event.inputs.tag }}
|
||||
APK_DIR="app/build/outputs/apk/release"
|
||||
|
||||
APKs=""
|
||||
for apk in "$APK_DIR"/*.apk; do
|
||||
BASENAME=$(basename "$apk") # ex: app-release-unsigned.apk
|
||||
SUFFIX=${BASENAME#app} # ex: -release-unsigned.apk
|
||||
NEW_NAME="${APP_NAME}${SUFFIX%\.apk}_${TAG}.apk" # ex: MonApp-release-unsigned_v1.2.3.apk
|
||||
mv "$apk" "$APK_DIR/$NEW_NAME"
|
||||
APKs+=" $APK_DIR/$NEW_NAME"
|
||||
done
|
||||
echo "📦 Liste des apks : $APKs"
|
||||
echo "apk_files=$APKs" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: 📤 Téléversement de l’APK dans la version
|
||||
if: ${{ github.event.inputs.build_apk == 'oui' }}
|
||||
env:
|
||||
REGISTRY_URL: ${{ vars.REGISTRY_URL }}
|
||||
REPO: ${{ vars.REGISTRY_REPOSITORY }}
|
||||
TOKEN: ${{ secrets.REGISTRY_PASSWORD }}
|
||||
RELEASE_ID: ${{ steps.creation-release.outputs.id_release }}
|
||||
run: |
|
||||
for apk in ${{ steps.renommer-apk.outputs.apk_files }}; do
|
||||
curl -s -X POST "https://$REGISTRY_URL/api/v1/repos/$REPO/releases/$RELEASE_ID/assets" \
|
||||
-H "Authorization: token $TOKEN" \
|
||||
-F attachment=@"$apk"
|
||||
done
|
1
.idea/.name
generated
Normal file
1
.idea/.name
generated
Normal file
@ -0,0 +1 @@
|
||||
LocalTransfer
|
6
.idea/AndroidProjectSystem.xml
generated
Normal file
6
.idea/AndroidProjectSystem.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="AndroidProjectSystem">
|
||||
<option name="providerId" value="com.android.tools.idea.GradleProjectSystem" />
|
||||
</component>
|
||||
</project>
|
2
.idea/compiler.xml
generated
2
.idea/compiler.xml
generated
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<bytecodeTargetLevel target="1.8" />
|
||||
<bytecodeTargetLevel target="17" />
|
||||
</component>
|
||||
</project>
|
10
.idea/deploymentTargetSelector.xml
generated
Normal file
10
.idea/deploymentTargetSelector.xml
generated
Normal 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>
|
7
.idea/gradle.xml
generated
7
.idea/gradle.xml
generated
@ -4,18 +4,15 @@
|
||||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
<option name="testRunner" value="PLATFORM" />
|
||||
<option name="distributionType" value="DEFAULT_WRAPPED" />
|
||||
<option name="testRunner" value="CHOOSE_PER_TEST" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="gradleJvm" value="1.8" />
|
||||
<option name="gradleJvm" value="#GRADLE_LOCAL_JAVA_HOME" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
<option value="$PROJECT_DIR$/app" />
|
||||
</set>
|
||||
</option>
|
||||
<option name="resolveModulePerSourceSet" value="false" />
|
||||
<option name="useQualifiedModuleNames" value="true" />
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
|
10
.idea/migrations.xml
generated
Normal file
10
.idea/migrations.xml
generated
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectMigrations">
|
||||
<option name="MigrateToGradleLocalJavaHome">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
</set>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
22
.idea/misc.xml
generated
22
.idea/misc.xml
generated
@ -1,11 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DesignSurface">
|
||||
<option name="filePathToZoomLevelMap">
|
||||
<map>
|
||||
<entry key="app/src/main/res/layout/file_info.xml" value="0.24479166666666666" />
|
||||
<entry key="app/src/main/res/layout/layout.xml" value="0.35989583333333336" />
|
||||
<entry key="app/src/main/res/layout/settings_activity.xml" value="0.215625" />
|
||||
<entry key="app/src/main/res/xml/network_security_config.xml" value="0.35989583333333336" />
|
||||
<entry key="app/src/main/res/xml/root_preferences.xml" value="0.35833333333333334" />
|
||||
</map>
|
||||
</option>
|
||||
</component>
|
||||
<component name="NullableNotNullManager">
|
||||
<option name="myDefaultNullable" value="org.jetbrains.annotations.Nullable" />
|
||||
<option name="myDefaultNotNull" value="androidx.annotation.NonNull" />
|
||||
<option name="myNullables">
|
||||
<value>
|
||||
<list size="14">
|
||||
<list size="16">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
|
||||
<item index="1" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
|
||||
<item index="2" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
|
||||
@ -20,12 +31,14 @@
|
||||
<item index="11" class="java.lang.String" itemvalue="org.eclipse.jdt.annotation.Nullable" />
|
||||
<item index="12" class="java.lang.String" itemvalue="io.reactivex.annotations.Nullable" />
|
||||
<item index="13" class="java.lang.String" itemvalue="io.reactivex.rxjava3.annotations.Nullable" />
|
||||
<item index="14" class="java.lang.String" itemvalue="org.jspecify.annotations.Nullable" />
|
||||
<item index="15" class="java.lang.String" itemvalue="jakarta.annotation.Nullable" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
<option name="myNotNulls">
|
||||
<value>
|
||||
<list size="13">
|
||||
<list size="16">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
|
||||
<item index="1" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
|
||||
<item index="2" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
|
||||
@ -39,11 +52,14 @@
|
||||
<item index="10" class="java.lang.String" itemvalue="org.eclipse.jdt.annotation.NonNull" />
|
||||
<item index="11" class="java.lang.String" itemvalue="io.reactivex.annotations.NonNull" />
|
||||
<item index="12" class="java.lang.String" itemvalue="io.reactivex.rxjava3.annotations.NonNull" />
|
||||
<item index="13" class="java.lang.String" itemvalue="lombok.NonNull" />
|
||||
<item index="14" class="java.lang.String" itemvalue="org.jspecify.annotations.NonNull" />
|
||||
<item index="15" class="java.lang.String" itemvalue="jakarta.annotation.Nonnull" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="temurin-17" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
|
11
.idea/runConfigurations.xml
generated
11
.idea/runConfigurations.xml
generated
@ -3,9 +3,14 @@
|
||||
<component name="RunConfigurationProducerService">
|
||||
<option name="ignoredProducers">
|
||||
<set>
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
|
||||
<option value="com.intellij.execution.junit.AbstractAllInDirectoryConfigurationProducer" />
|
||||
<option value="com.intellij.execution.junit.AllInPackageConfigurationProducer" />
|
||||
<option value="com.intellij.execution.junit.PatternConfigurationProducer" />
|
||||
<option value="com.intellij.execution.junit.TestInClassConfigurationProducer" />
|
||||
<option value="com.intellij.execution.junit.UniqueIdConfigurationProducer" />
|
||||
<option value="com.intellij.execution.junit.testDiscovery.JUnitTestDiscoveryConfigurationProducer" />
|
||||
<option value="org.jetbrains.kotlin.idea.junit.KotlinJUnitRunConfigurationProducer" />
|
||||
<option value="org.jetbrains.kotlin.idea.junit.KotlinPatternConfigurationProducer" />
|
||||
</set>
|
||||
</option>
|
||||
</component>
|
||||
|
@ -1,42 +1,38 @@
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 30
|
||||
buildToolsVersion "30.0.2"
|
||||
|
||||
compileSdk 35
|
||||
defaultConfig {
|
||||
applicationId "com.localtransfer"
|
||||
minSdkVersion 24
|
||||
targetSdkVersion 30
|
||||
minSdkVersion 27
|
||||
targetSdkVersion 35
|
||||
versionCode 1
|
||||
versionName "2.0"
|
||||
versionName "3.0"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
minifyEnabled true
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
sourceCompatibility JavaVersion.VERSION_17
|
||||
targetCompatibility JavaVersion.VERSION_17
|
||||
}
|
||||
namespace 'com.localtransfer'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: "libs", include: ["*.jar"])
|
||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||
implementation 'com.google.android.material:material:1.2.1'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
|
||||
implementation 'androidx.appcompat:appcompat:1.7.1'
|
||||
implementation 'com.google.android.material:material:1.12.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.2.1'
|
||||
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
|
||||
implementation 'androidx.preference:preference:1.1.1'
|
||||
implementation 'androidx.preference:preference:1.2.1'
|
||||
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||
testImplementation 'junit:junit:4.13.1'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
|
||||
implementation 'lib.kashif:folderpicker:2.4'
|
||||
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.2.1'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
package com.localtransfer;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ExampleInstrumentedTest {
|
||||
@Test
|
||||
public void useAppContext() {
|
||||
// Context of the app under test.
|
||||
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
|
||||
assertEquals("com.localtransfer", appContext.getPackageName());
|
||||
}
|
||||
}
|
@ -1,23 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.localtransfer">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
|
||||
<uses-permission
|
||||
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||
android:maxSdkVersion="28" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
android:requestLegacyExternalStorage="true"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
<service
|
||||
android:name=".TransferService"
|
||||
android:enabled="true"
|
||||
android:exported="true"></service>
|
||||
|
||||
android:exported="false"
|
||||
android:foregroundServiceType="dataSync" />
|
||||
<!-- android:usesCleartextTraffic="true" -->
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${applicationId}"
|
||||
@ -30,9 +35,10 @@
|
||||
|
||||
<activity
|
||||
android:name=".SettingsActivity"
|
||||
android:label="@string/title_activity_settings"></activity>
|
||||
android:label="@string/title_activity_settings" />
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/AppTheme.NoActionBar">
|
||||
<intent-filter>
|
||||
|
289
app/src/main/java/com/localtransfer/DownloadFile.java
Normal file
289
app/src/main/java/com/localtransfer/DownloadFile.java
Normal file
@ -0,0 +1,289 @@
|
||||
package com.localtransfer;
|
||||
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.content.ContentUris;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Environment;
|
||||
import android.provider.MediaStore;
|
||||
import android.util.Log;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.LinearInterpolator;
|
||||
import android.widget.Button;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import androidx.core.content.FileProvider;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.sql.Timestamp;
|
||||
|
||||
public class DownloadFile extends Transfer {
|
||||
|
||||
public String href;
|
||||
|
||||
public String mime;
|
||||
|
||||
public String type;
|
||||
|
||||
public Uri uri;
|
||||
|
||||
private Button button;
|
||||
|
||||
public DownloadFile(Integer id) {
|
||||
this.id = id;
|
||||
instances.add(this);
|
||||
info = "Download complete";
|
||||
state = STATE_NOT_REQUESTED;
|
||||
drawable = R.drawable.ic_download_24;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startTransfer() {
|
||||
super.startTransfer();
|
||||
|
||||
startedTime = new Timestamp(System.currentTimeMillis());
|
||||
|
||||
state = STATE_RUNNING;
|
||||
|
||||
buttonProgressStart();
|
||||
|
||||
if (uri == null && android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(MediaStore.MediaColumns.DISPLAY_NAME, name);
|
||||
values.put(MediaStore.MediaColumns.MIME_TYPE, mime);
|
||||
values.put(MediaStore.MediaColumns.RELATIVE_PATH, Transfer.shared_storage);
|
||||
uri = resolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, values);
|
||||
}
|
||||
try {
|
||||
downloadFile();
|
||||
} catch (IOException | NullPointerException e) {
|
||||
final String ExceptionName = e.getClass().getSimpleName();
|
||||
final String ExceptionMess = e.getMessage();
|
||||
e.printStackTrace();
|
||||
|
||||
state = Transfer.STATE_FAILED;
|
||||
progressEnd();
|
||||
buttonProgressEnd();
|
||||
|
||||
if(ExceptionName != null && ExceptionMess != null) {
|
||||
errorSnackbar(ExceptionName + ": " + ExceptionMess);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public boolean exist(Context context) {
|
||||
if (!Transfer.use_shared_storage){
|
||||
File file = new File(activity.getFilesDir(), name);
|
||||
|
||||
uri = FileProvider.getUriForFile(activity, activity.getPackageName(), file);
|
||||
|
||||
if (file.exists() && file.length() == size)
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
|
||||
Cursor cursor = context.getContentResolver().query(MediaStore.Downloads.EXTERNAL_CONTENT_URI, null, null, null, null);
|
||||
while (cursor.moveToNext()) {
|
||||
String MediaStore_File_name = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Downloads.DISPLAY_NAME));
|
||||
long MediaStore_File_size = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Downloads.SIZE));
|
||||
if(MediaStore_File_name.equals(name) && MediaStore_File_size == size) {
|
||||
int cursor_id = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Downloads._ID));
|
||||
uri = ContentUris.withAppendedId(MediaStore.Downloads.EXTERNAL_CONTENT_URI, cursor_id);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
String save_location = null;
|
||||
if (mime.equals("text/plain"))
|
||||
save_location = context.getCacheDir().toString();
|
||||
else
|
||||
save_location = Environment.getExternalStorageDirectory() + "/" + Transfer.shared_storage;
|
||||
new File(save_location).mkdirs();
|
||||
File file = new File(save_location, name);
|
||||
try {
|
||||
file.createNewFile();
|
||||
} catch (IOException e) {
|
||||
final String ExceptionName = e.getClass().getSimpleName();
|
||||
final String ExceptionMess = e.getMessage();
|
||||
e.printStackTrace();
|
||||
|
||||
if(ExceptionName != null && ExceptionMess != null) {
|
||||
errorSnackbar(ExceptionName + ": " + ExceptionMess);
|
||||
}
|
||||
}
|
||||
uri = Uri.fromFile(file);
|
||||
if (file.exists() && file.length() == size)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setButton(Button button) {
|
||||
this.button = button;
|
||||
if (this.state == STATE_STANDBY) {
|
||||
buttonProgressStart();
|
||||
}
|
||||
}
|
||||
|
||||
public InputStream getThumbnail() {
|
||||
InputStream thumbnail = null;
|
||||
URL url;
|
||||
try {
|
||||
String query = URLEncoder.encode(href, StandardCharsets.UTF_8.toString());
|
||||
String serverUrl = root + "/thumbnail.php?file=" + query;
|
||||
url = new URL(protocol, host, port, serverUrl);
|
||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setRequestMethod("GET");
|
||||
conn.setConnectTimeout(2000);
|
||||
|
||||
conn.connect();
|
||||
|
||||
thumbnail = conn.getInputStream();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return thumbnail;
|
||||
}
|
||||
|
||||
public void downloadFile() throws IOException {
|
||||
|
||||
URL url = null;
|
||||
HttpURLConnection conn = null;
|
||||
int maxBufferSize = 1 * 1024 * 1024;
|
||||
byte[] buffer = new byte[maxBufferSize];
|
||||
int bufferLength;
|
||||
loaded = 0;
|
||||
|
||||
String[] parts = href.split("/");
|
||||
String path = "";
|
||||
for(int i=0; i< parts.length - 1; i++) {
|
||||
path = path + parts[i] + "/";
|
||||
}
|
||||
String query = URLEncoder.encode(parts[parts.length - 1], StandardCharsets.UTF_8.toString());
|
||||
url = new URL(protocol, host, port, path + query.replace("+", "%20"));
|
||||
conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setDoOutput(true);
|
||||
conn.setRequestMethod("GET");
|
||||
conn.setConnectTimeout(2000);
|
||||
|
||||
Log.d("URL", url.toString());
|
||||
|
||||
conn.connect();
|
||||
|
||||
int responseCode = conn.getResponseCode();
|
||||
|
||||
if (responseCode == HttpURLConnection.HTTP_OK) {
|
||||
|
||||
OutputStream fileOutput = activity.getContentResolver().openOutputStream(uri);
|
||||
InputStream in = conn.getInputStream();
|
||||
|
||||
while ((bufferLength = in.read(buffer)) > 0) {
|
||||
fileOutput.write(buffer, 0, bufferLength);
|
||||
loaded+= bufferLength;
|
||||
percent = ((loaded * 100) / size);
|
||||
progressUpdateDelay();
|
||||
buttonProgressUpdate();
|
||||
}
|
||||
fileOutput.close();
|
||||
|
||||
conn.disconnect();
|
||||
|
||||
message = "File " + name + " successful download";
|
||||
state = Transfer.STATE_SUCCESS;
|
||||
progressEnd();
|
||||
buttonProgressEnd();
|
||||
|
||||
}
|
||||
else {
|
||||
String s = conn.getResponseMessage();
|
||||
throw new HttpErrorException("error code: " + responseCode + " " + s);
|
||||
}
|
||||
|
||||
conn.disconnect();
|
||||
}
|
||||
|
||||
public String deleteFile() throws IOException {
|
||||
|
||||
URL url = null;
|
||||
HttpURLConnection conn = null;
|
||||
|
||||
String message;
|
||||
|
||||
String query = URLEncoder.encode(name, StandardCharsets.UTF_8.toString());
|
||||
String serverUrl = root + "/delete.php?file=" + query;
|
||||
url = new URL(protocol, host, port, serverUrl);
|
||||
conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setRequestMethod("GET");
|
||||
conn.setConnectTimeout(2000);
|
||||
|
||||
conn.connect();
|
||||
|
||||
int responseCode = conn.getResponseCode();
|
||||
|
||||
if (responseCode == HttpURLConnection.HTTP_OK) {
|
||||
|
||||
message = "File " + name + " successful deleted";
|
||||
}
|
||||
else {
|
||||
String s = conn.getResponseMessage();
|
||||
throw new HttpErrorException("error code: " + responseCode + " " + s);
|
||||
}
|
||||
|
||||
conn.disconnect();
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
public void buttonProgressStart() {
|
||||
activity.runOnUiThread(() -> {
|
||||
final Drawable image = Transfer.activity.getDrawable(R.drawable.ic_spinner_rotate);
|
||||
|
||||
if(button != null) {
|
||||
int h = image.getIntrinsicHeight();
|
||||
int w = image.getIntrinsicWidth();
|
||||
image.setBounds(0, 0, w, h);
|
||||
button.setCompoundDrawables(button.getCompoundDrawables()[0], null, image, null);
|
||||
ObjectAnimator anim = ObjectAnimator.ofInt(image, "level", 0, 10000);
|
||||
anim.setDuration(1000);
|
||||
anim.setRepeatCount(Animation.INFINITE);
|
||||
anim.setInterpolator(new LinearInterpolator());
|
||||
anim.start();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void buttonProgressUpdate(){
|
||||
activity.runOnUiThread(() -> {
|
||||
if (app_started && button != null)
|
||||
button.setText(String.format("Download in progress %d%%", percent));
|
||||
});
|
||||
}
|
||||
|
||||
public void buttonProgressEnd() {
|
||||
activity.runOnUiThread(() -> {
|
||||
if (button != null) {
|
||||
final LinearLayout layout = (LinearLayout) button.getParent();
|
||||
layout.findViewById(R.id.file_view).setVisibility(LinearLayout.VISIBLE);
|
||||
layout.findViewById(R.id.file_share).setVisibility(LinearLayout.VISIBLE);
|
||||
button.setVisibility(LinearLayout.GONE);
|
||||
button.setEnabled(true);
|
||||
|
||||
button.setText(activity.getString(R.string.file_download));
|
||||
button.setCompoundDrawables(button.getCompoundDrawables()[0], null, null, null);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -2,31 +2,33 @@ package com.localtransfer;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.app.Notification;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import android.os.Environment;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.app.NotificationManagerCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
|
||||
@ -59,7 +61,18 @@ public class MainActivity extends AppCompatActivity {
|
||||
}
|
||||
});
|
||||
|
||||
checkAndRequestPermissions();
|
||||
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.Q) {
|
||||
checkAndRequestPermissions();
|
||||
}
|
||||
|
||||
|
||||
Transfer.notifBuilder = new Notification.Builder(this);
|
||||
Transfer.notifiManager = NotificationManagerCompat.from(this);
|
||||
Transfer.inflater = (LayoutInflater) this.getSystemService(this.LAYOUT_INFLATER_SERVICE);
|
||||
Transfer.resolver = this.getContentResolver();
|
||||
|
||||
Intent notificationIntent = new Intent(this, MainActivity.class);
|
||||
Transfer.pendingIntent = PendingIntent.getActivity(this,0, notificationIntent, PendingIntent.FLAG_IMMUTABLE);
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
|
||||
@ -68,7 +81,8 @@ public class MainActivity extends AppCompatActivity {
|
||||
.putString("host", getString(R.string.server_host_def))
|
||||
.putString("port", getString(R.string.server_port_def))
|
||||
.putString("root", getString(R.string.server_root_def))
|
||||
.putString("local_storage", getString(R.string.local_storage_def))
|
||||
.putString("shared_storage", getString(R.string.shared_storage_def))
|
||||
.putBoolean("use_shared_storage", false)
|
||||
.apply();
|
||||
|
||||
Transfer.parameter(this);
|
||||
@ -82,10 +96,10 @@ public class MainActivity extends AppCompatActivity {
|
||||
viewPager.setCurrentItem(2);
|
||||
if ("text/plain".equals(type)) {
|
||||
String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
|
||||
Transfer.handleSendText(sharedText);
|
||||
UploadFile.handleSendText(sharedText);
|
||||
} else {
|
||||
Uri uri = intent.getParcelableExtra(Intent.EXTRA_STREAM);
|
||||
Transfer.handleSendFile(uri);
|
||||
UploadFile.handleSendFile(uri);
|
||||
}
|
||||
} else if (Intent.ACTION_SEND_MULTIPLE.equals(action) && type != null) {
|
||||
viewPager.setCurrentItem(2);
|
||||
@ -93,7 +107,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
int nbItem = fileUris.size();
|
||||
Toast.makeText(this, "You select " + nbItem + " files", Toast.LENGTH_SHORT).show();
|
||||
if (fileUris != null)
|
||||
for(Uri uri : fileUris) Transfer.handleSendFile(uri);
|
||||
for(Uri uri : fileUris) UploadFile.handleSendFile(uri);
|
||||
}
|
||||
|
||||
}
|
||||
@ -111,7 +125,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
|
||||
if (type != null) {
|
||||
String sharedText = data.getStringExtra(Intent.EXTRA_TEXT);
|
||||
Transfer.handleSendText(sharedText);
|
||||
UploadFile.handleSendText(sharedText);
|
||||
}
|
||||
else {
|
||||
ArrayList<Uri> fileUris = new ArrayList<>();
|
||||
@ -127,7 +141,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
fileUris.add(uri);
|
||||
}
|
||||
for (Uri uri : fileUris) {
|
||||
Transfer.handleSendFile(uri);
|
||||
UploadFile.handleSendFile(uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -137,14 +151,14 @@ public class MainActivity extends AppCompatActivity {
|
||||
public void onResume(){
|
||||
super.onResume();
|
||||
|
||||
Progress.app_started = true;
|
||||
Transfer.app_started = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause(){
|
||||
super.onPause();
|
||||
|
||||
Progress.app_started = false;
|
||||
Transfer.app_started = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -182,7 +196,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
startActivity(settings);
|
||||
break;
|
||||
case R.id.action_folder:
|
||||
String save_location = Environment.getExternalStorageDirectory() + "/" + Transfer.local_storage;
|
||||
String save_location = Environment.getExternalStorageDirectory() + "/" + Transfer.shared_storage;
|
||||
Uri selectedUri = Uri.parse(save_location.toString());
|
||||
boolean intentSuccess = false;
|
||||
try {
|
||||
@ -213,7 +227,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
|
||||
public static final int REQUEST_ID_READ_EXTERNAL_STORAGE = 2001;
|
||||
|
||||
private boolean checkAndRequestPermissions() {
|
||||
private boolean checkAndRequestPermissions() {
|
||||
|
||||
if (ContextCompat.checkSelfPermission(
|
||||
this, Manifest.permission.READ_EXTERNAL_STORAGE) ==
|
||||
@ -230,6 +244,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
public void onRequestPermissionsResult(int requestCode,
|
||||
String permissions[],
|
||||
int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
switch (requestCode) {
|
||||
case REQUEST_ID_READ_EXTERNAL_STORAGE:
|
||||
if (grantResults.length > 0 &&
|
||||
|
@ -1,161 +0,0 @@
|
||||
package com.localtransfer;
|
||||
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.app.Notification;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.LinearInterpolator;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.core.app.NotificationManagerCompat;
|
||||
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
|
||||
import java.util.ConcurrentModificationException;
|
||||
|
||||
public class Progress {
|
||||
|
||||
private static Notification.Builder bl = new Notification.Builder(Transfer.activity);
|
||||
private static NotificationManagerCompat notifiManager = NotificationManagerCompat.from(Transfer.activity);
|
||||
private static final LayoutInflater inflater = (LayoutInflater) Transfer.activity.getSystemService(Transfer.activity.LAYOUT_INFLATER_SERVICE);
|
||||
|
||||
private static Intent notificationIntent = new Intent(Transfer.activity, MainActivity.class);
|
||||
private static PendingIntent pendingIntent = PendingIntent.getActivity(Transfer.activity,0, notificationIntent, 0);
|
||||
|
||||
public static View root;
|
||||
public static boolean fragment_on = false;
|
||||
public static boolean app_started = false;
|
||||
|
||||
private static long savedTimeMillis;
|
||||
|
||||
public static void PreProgress(Transfer tr) {
|
||||
Transfer.activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
final Drawable image = Transfer.activity.getDrawable(R.drawable.ic_spinner_rotate);
|
||||
|
||||
if(tr.button != null) {
|
||||
int h = image.getIntrinsicHeight();
|
||||
int w = image.getIntrinsicWidth();
|
||||
image.setBounds(0, 0, w, h);
|
||||
tr.button.setCompoundDrawables(tr.button.getCompoundDrawables()[0], null, image, null);
|
||||
ObjectAnimator anim = ObjectAnimator.ofInt(image, "level", 0, 10000);
|
||||
anim.setDuration(1000);
|
||||
anim.setRepeatCount(Animation.INFINITE);
|
||||
anim.setInterpolator(new LinearInterpolator());
|
||||
anim.start();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void ProgressUpdateDelay(Transfer tr) {
|
||||
// Run only every second to reduce CPU usage
|
||||
if (System.currentTimeMillis() > (savedTimeMillis + 1000)) {
|
||||
savedTimeMillis = System.currentTimeMillis();
|
||||
ProgressUpdate(tr);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ProgressUpdate(Transfer tr){
|
||||
Transfer.activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
if (Progress.app_started && tr.button != null)
|
||||
tr.button.setText(String.format("Download in progress %d%%", tr.percent));
|
||||
|
||||
try {
|
||||
|
||||
bl.setSmallIcon(R.drawable.ic_upload_and_download_from_the_cloud)
|
||||
.setContentTitle(tr.fileName)
|
||||
.setContentText(String.format("%d%% %s/%s", tr.percent, tr.loadedHuman, tr.fileSizeHuman))
|
||||
.setProgress(100, (int) tr.percent, false)
|
||||
.setContentIntent(pendingIntent);
|
||||
notifiManager.notify(Transfer.NOTIF_SERVICE, bl.build());
|
||||
|
||||
if (app_started && fragment_on)
|
||||
showProgressFragment(tr);
|
||||
|
||||
} catch (ConcurrentModificationException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void PostProgress(Transfer tr) {
|
||||
ProgressUpdate(tr);
|
||||
Transfer.activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
notifiManager.cancel(Transfer.NOTIF_SERVICE);
|
||||
|
||||
if (!app_started) {
|
||||
bl.setSmallIcon(R.drawable.ic_upload_and_download_from_the_cloud)
|
||||
.setContentTitle(tr.fileName)
|
||||
.setContentText(tr.info)
|
||||
.setProgress(0, 0, false)
|
||||
.setContentIntent(pendingIntent);
|
||||
notifiManager.notify(tr.id, bl.build());
|
||||
}
|
||||
|
||||
if (tr.button != null) {
|
||||
final LinearLayout layout = (LinearLayout) tr.button.getParent();
|
||||
layout.findViewById(R.id.file_view).setVisibility(LinearLayout.VISIBLE);
|
||||
layout.findViewById(R.id.file_share).setVisibility(LinearLayout.VISIBLE);
|
||||
tr.button.setVisibility(LinearLayout.GONE);
|
||||
tr.button.setEnabled(true);
|
||||
|
||||
tr.button.setText(Transfer.activity.getString(R.string.file_download));
|
||||
tr.button.setCompoundDrawables(tr.button.getCompoundDrawables()[0], null, null, null);
|
||||
}
|
||||
|
||||
System.out.println(tr.message);
|
||||
/*Snackbar.make(Transfer.activity.findViewById(R.id.view_pager), tr.message, Snackbar.LENGTH_LONG)
|
||||
.setAction("Action", null).show();*/
|
||||
Toast.makeText(Transfer.activity, tr.message, Toast.LENGTH_SHORT).show();
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void showProgressFragment(Transfer tr){
|
||||
|
||||
LinearLayout groot = root.findViewById(R.id.groot);
|
||||
|
||||
final View progress;
|
||||
|
||||
if (groot.findViewById(tr.id) != null) {
|
||||
progress = groot.findViewById(tr.id);
|
||||
} else {
|
||||
progress = inflater.inflate(R.layout.progress, null);
|
||||
progress.setId(tr.id);
|
||||
Transfer.activity.runOnUiThread(() -> {
|
||||
groot.addView(progress, 0);
|
||||
});
|
||||
}
|
||||
|
||||
((ProgressBar) progress.findViewById(R.id.progressBar)).setProgress((int) tr.percent);
|
||||
((ImageView) progress.findViewById(R.id.transferType)).setImageResource(tr.drawable);
|
||||
((TextView) progress.findViewById(R.id.progressText)).setText(tr.percent + " %");
|
||||
((TextView) progress.findViewById(R.id.fileName)).setText(tr.fileName);
|
||||
((TextView) progress.findViewById(R.id.fileSize)).setText(String.format("%s/%s", tr.loadedHuman, tr.fileSizeHuman));
|
||||
|
||||
if (tr.state == Transfer.STATE_SUCCESS)
|
||||
((TextView) progress.findViewById(R.id.fileName)).setTextColor(Color.GREEN);
|
||||
else if (tr.state == Transfer.STATE_FAILED)
|
||||
((TextView) progress.findViewById(R.id.fileName)).setTextColor(Color.RED);
|
||||
}
|
||||
}
|
@ -1,8 +1,10 @@
|
||||
package com.localtransfer;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.util.Log;
|
||||
@ -10,11 +12,12 @@ import android.view.MenuItem;
|
||||
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceFragmentCompat;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import lib.folderpicker.FolderPicker;
|
||||
import androidx.preference.SwitchPreference;
|
||||
|
||||
public class SettingsActivity extends AppCompatActivity {
|
||||
|
||||
@ -42,18 +45,72 @@ public class SettingsActivity extends AppCompatActivity {
|
||||
setPreferencesFromResource(R.xml.root_preferences, rootKey);
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
|
||||
directory = findPreference("local_storage");
|
||||
directory.setSummary(prefs.getString("local_storage", null));
|
||||
|
||||
directory = findPreference("shared_storage");
|
||||
directory.setSummary(prefs.getString("shared_storage", null));
|
||||
|
||||
SwitchPreference shared;
|
||||
shared = findPreference("use_shared_storage");
|
||||
if(shared.isChecked()) {
|
||||
if(checkAndRequestPermissions())
|
||||
directory.setVisible(true);
|
||||
else
|
||||
shared.setChecked(false);
|
||||
}
|
||||
else
|
||||
directory.setVisible(false);
|
||||
|
||||
shared.setOnPreferenceClickListener(preference -> {
|
||||
if(shared.isChecked()) {
|
||||
if(checkAndRequestPermissions())
|
||||
directory.setVisible(true);
|
||||
else
|
||||
shared.setChecked(false);
|
||||
}
|
||||
else
|
||||
directory.setVisible(false);
|
||||
return false;
|
||||
});
|
||||
directory.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
Intent intent = new Intent(getContext(), FolderPicker.class);
|
||||
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
|
||||
intent.addCategory(Intent.CATEGORY_DEFAULT);
|
||||
startActivityForResult(intent, REQUEST_DIRECTORY_PICKER);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private boolean checkAndRequestPermissions() {
|
||||
|
||||
if (ContextCompat.checkSelfPermission(
|
||||
getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE) ==
|
||||
PackageManager.PERMISSION_GRANTED) {
|
||||
Log.d("READ_EXTERNAL_STORAGE", "already granted");
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
ActivityCompat.requestPermissions(getActivity(), new String[] {android.Manifest.permission.READ_EXTERNAL_STORAGE}, MainActivity.REQUEST_ID_READ_EXTERNAL_STORAGE);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode,
|
||||
String permissions[],
|
||||
int[] grantResults) {
|
||||
switch (requestCode) {
|
||||
case MainActivity.REQUEST_ID_READ_EXTERNAL_STORAGE:
|
||||
if (grantResults.length > 0 &&
|
||||
grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
Log.d("READ_EXTERNAL_STORAGE", "granted");
|
||||
} else {
|
||||
Log.d("READ_EXTERNAL_STORAGE", "No granted");
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
@ -65,7 +122,7 @@ public class SettingsActivity extends AppCompatActivity {
|
||||
String save_location = currentPath.replace(Environment.getExternalStorageDirectory() + "/", "");
|
||||
Log.d("Path", save_location);
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
|
||||
prefs.edit().putString("local_storage", save_location).apply();
|
||||
prefs.edit().putString("shared_storage", save_location).apply();
|
||||
directory.setSummary(save_location);
|
||||
}
|
||||
}
|
||||
|
@ -1,453 +1,282 @@
|
||||
package com.localtransfer;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.provider.OpenableColumns;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import static java.lang.Integer.valueOf;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.content.FileProvider;
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.app.Notification;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Color;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.app.NotificationManagerCompat;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.ProtocolException;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.sql.Timestamp;
|
||||
import java.text.CharacterIterator;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.text.StringCharacterIterator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.ConcurrentModificationException;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
import static java.lang.Integer.valueOf;
|
||||
|
||||
public class Transfer {
|
||||
|
||||
protected static Notification.Builder notifBuilder;
|
||||
protected static NotificationManagerCompat notifiManager;
|
||||
protected static LayoutInflater inflater;
|
||||
protected static ContentResolver resolver;
|
||||
|
||||
protected static PendingIntent pendingIntent;
|
||||
|
||||
public static View fragment_progress;
|
||||
public static boolean fragment_on = false;
|
||||
public static boolean app_started = false;
|
||||
|
||||
protected static long savedTimeMillis;
|
||||
|
||||
public static String host;
|
||||
public static Integer port;
|
||||
public static String root;
|
||||
public static String protocol;
|
||||
public static String local_storage;
|
||||
public static String shared_storage;
|
||||
public static boolean use_shared_storage;
|
||||
|
||||
public static Activity activity;
|
||||
|
||||
public static final int STATE_STANDBY = 100;
|
||||
public static final int STATE_RUNNING = 101;
|
||||
public static final int STATE_SUCCESS = 102;
|
||||
public static final int STATE_FAILED = 103;
|
||||
|
||||
public static final int TYPE_DOWNLOAD = 200;
|
||||
public static final int TYPE_UPLOAD = 201;
|
||||
|
||||
public static final int NOTIF_SERVICE = 1000;
|
||||
public static final int NOTIF_GROUP = 1001;
|
||||
|
||||
public static boolean runningTransfer = false;
|
||||
|
||||
private static List<Transfer> instances = new ArrayList<>();
|
||||
|
||||
public static List getInstances() {
|
||||
return instances;
|
||||
}
|
||||
|
||||
public int state;
|
||||
public String error;
|
||||
|
||||
public int type;
|
||||
|
||||
public Integer id;
|
||||
public int drawable;
|
||||
public String info;
|
||||
public String message;
|
||||
public String fileName;
|
||||
|
||||
public long fileSize;
|
||||
public String fileSizeHuman;
|
||||
public String sizeSI;
|
||||
|
||||
public long loaded;
|
||||
public String loadedHuman = "0";
|
||||
public String loadedSI = "0";
|
||||
public long percent;
|
||||
|
||||
public Transfer(int type) {
|
||||
public static final int NOTIF_SERVICE = 1000;
|
||||
|
||||
id = View.generateViewId();
|
||||
public static final int STATE_NOT_REQUESTED = 100;
|
||||
public static final int STATE_STANDBY = 110;
|
||||
public static final int STATE_RUNNING = 120;
|
||||
public static final int STATE_SUCCESS = 130;
|
||||
public static final int STATE_FAILED = 140;
|
||||
|
||||
switch (type) {
|
||||
case TYPE_DOWNLOAD:
|
||||
drawable = R.drawable.ic_download_24;
|
||||
info = "Download complete";
|
||||
break;
|
||||
case TYPE_UPLOAD:
|
||||
drawable = R.drawable.ic_upload_24;
|
||||
info = "Upload complete";
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unexpected value: " + type);
|
||||
public static Thread thread = new Thread();
|
||||
|
||||
Integer id;
|
||||
|
||||
public String name;
|
||||
|
||||
public long size;
|
||||
|
||||
Timestamp addedTime;
|
||||
Timestamp startedTime;
|
||||
|
||||
static List<Transfer> instances = new ArrayList<>();
|
||||
|
||||
public static List<Transfer> getInstances() {
|
||||
List<Transfer> in = new ArrayList<>();
|
||||
for (Transfer file: instances) {
|
||||
//if(Arrays.asList(STATE_STANDBY, STATE_RUNNING, STATE_SUCCESS, STATE_FAILED).contains(file.state)) {
|
||||
if(file.state == STATE_STANDBY ||
|
||||
file.state == STATE_RUNNING ||
|
||||
file.state == STATE_SUCCESS ||
|
||||
file.state == STATE_FAILED) {
|
||||
in.add(file);
|
||||
}
|
||||
}
|
||||
|
||||
state = STATE_STANDBY;
|
||||
this.type = type;
|
||||
|
||||
//in.sort(Comparator.comparing(Transfer::getAddedTime).reversed());
|
||||
in.sort(Comparator.comparing(e -> e.addedTime));
|
||||
return in;
|
||||
}
|
||||
|
||||
public void AddTransfer() {
|
||||
instances.add(this);
|
||||
|
||||
if(!runningTransfer) {
|
||||
Intent serviceIntent = new Intent(activity, TransferService.class);
|
||||
ContextCompat.startForegroundService(activity, serviceIntent);
|
||||
runningTransfer = true;
|
||||
new Thread(() -> StartTransfer(this)).start();
|
||||
public static Transfer getFileById(int id) {
|
||||
for (Object obj: instances) {
|
||||
Transfer p = (Transfer) obj;
|
||||
if (p.id == id) return p;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void StartTransfer(Transfer tr) {
|
||||
try {
|
||||
switch (tr.type) {
|
||||
case Transfer.TYPE_DOWNLOAD:
|
||||
tr.downloadFile();
|
||||
break;
|
||||
case Transfer.TYPE_UPLOAD:
|
||||
tr.uploadFile();
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unexpected value: " + tr.type);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
final String ExceptionName = e.getClass().getSimpleName();
|
||||
final String ExceptionMess = e.getMessage();
|
||||
|
||||
tr.state = Transfer.STATE_FAILED;
|
||||
tr.error = ExceptionName + ": " + ExceptionMess;
|
||||
Progress.PostProgress(tr);
|
||||
|
||||
if(ExceptionName != null && ExceptionMess != null) {
|
||||
Transfer.error(ExceptionMess);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
try {
|
||||
for (Object obj : Transfer.getInstances()) {
|
||||
Transfer transfer = (Transfer) obj;
|
||||
if (transfer.state == Transfer.STATE_STANDBY)
|
||||
StartTransfer(transfer);
|
||||
}
|
||||
} catch (ConcurrentModificationException e) {
|
||||
e.printStackTrace();
|
||||
try {
|
||||
Thread.sleep(10);
|
||||
} catch (InterruptedException InterrupEx) {
|
||||
InterrupEx.printStackTrace();
|
||||
}
|
||||
for (Object obj : Transfer.getInstances()) {
|
||||
Transfer transfer = (Transfer) obj;
|
||||
if (transfer.state == Transfer.STATE_STANDBY)
|
||||
StartTransfer(transfer);
|
||||
}
|
||||
}
|
||||
|
||||
Intent serviceIntent = new Intent(Transfer.activity, TransferService.class);
|
||||
Transfer.activity.stopService(serviceIntent);
|
||||
Transfer.runningTransfer = false;
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public static void parameter(Context context) {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
|
||||
host = prefs.getString("host", null);
|
||||
port = valueOf(prefs.getString("port", null));
|
||||
root = prefs.getString("root", null);
|
||||
local_storage = prefs.getString("local_storage", null);
|
||||
shared_storage = prefs.getString("shared_storage", null);
|
||||
use_shared_storage = prefs.getBoolean("use_shared_storage", false);
|
||||
if(prefs.getBoolean("protocol", false))
|
||||
protocol = "https";
|
||||
else
|
||||
protocol = "http";
|
||||
String portValue = prefs.getString("port", null);
|
||||
if(portValue.equals("")){
|
||||
if(protocol.equals("http"))
|
||||
port = 80;
|
||||
else if(protocol.equals("https"))
|
||||
port = 443;
|
||||
}
|
||||
else
|
||||
port = valueOf(portValue);
|
||||
}
|
||||
|
||||
public Uri uri;
|
||||
public void AddTransfer() {
|
||||
|
||||
public static void handleSendFile(Uri uri) {
|
||||
if (uri != null) {
|
||||
Transfer tr = new Transfer(Transfer.TYPE_UPLOAD);
|
||||
tr.uri = uri;
|
||||
state = STATE_STANDBY;
|
||||
|
||||
Cursor cursor = activity.getContentResolver().query(uri, null, null, null, null);
|
||||
cursor.moveToFirst();
|
||||
addedTime = new Timestamp(System.currentTimeMillis());
|
||||
|
||||
tr.fileName = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
|
||||
tr.fileSize = cursor.getLong(cursor.getColumnIndex(OpenableColumns.SIZE));
|
||||
tr.fileSizeHuman = Transfer.humanReadableByteCountBin(tr.fileSize);
|
||||
Thread.State state = thread.getState();
|
||||
|
||||
tr.AddTransfer();
|
||||
if(state == Thread.State.NEW || state == Thread.State.TERMINATED) {
|
||||
thread = new Thread(startTransfers);
|
||||
thread.start();
|
||||
|
||||
/*Intent serviceIntent = new Intent(activity, TransferService.class);
|
||||
ContextCompat.startForegroundService(activity, serviceIntent);*/
|
||||
}
|
||||
}
|
||||
|
||||
public static void handleSendText(String sharedText) {
|
||||
if (sharedText != null) {
|
||||
SimpleDateFormat sdfDate = new SimpleDateFormat("yyyyMMdd_HHmmss");
|
||||
Date now = new Date();
|
||||
String strDate = sdfDate.format(now);
|
||||
Uri uri = null;
|
||||
public void startTransfer() {
|
||||
|
||||
}
|
||||
|
||||
public static Runnable startTransfers = () -> {
|
||||
try {
|
||||
for (Transfer transfer : getInstances()) {
|
||||
if (transfer.state == Transfer.STATE_STANDBY) {
|
||||
transfer.startTransfer();
|
||||
thread.run(); // restart thread for another potential standby transfer
|
||||
break; // ignore remainder instance
|
||||
}
|
||||
}
|
||||
} catch (ConcurrentModificationException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
/*Intent serviceIntent = new Intent(Transfer.activity, TransferService.class);
|
||||
Transfer.activity.stopService(serviceIntent);*/
|
||||
};
|
||||
|
||||
public void progressUpdateDelay() {
|
||||
// Run only every second to reduce CPU usage
|
||||
if (System.currentTimeMillis() > (savedTimeMillis + 1000)) {
|
||||
savedTimeMillis = System.currentTimeMillis();
|
||||
progressUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
private void progressUpdate(){
|
||||
|
||||
loadedSI = Transfer.humanReadableByteCountBin(loaded);
|
||||
|
||||
activity.runOnUiThread(() -> {
|
||||
|
||||
try {
|
||||
File outputFile = new File(activity.getCacheDir(), strDate + ".txt");
|
||||
FileOutputStream fileOut = new FileOutputStream(outputFile);
|
||||
OutputStreamWriter OutWriter = new OutputStreamWriter(fileOut);
|
||||
OutWriter.append(sharedText);
|
||||
OutWriter.close();
|
||||
|
||||
fileOut.flush();
|
||||
fileOut.close();
|
||||
notifBuilder.setSmallIcon(R.drawable.ic_upload_and_download_from_the_cloud)
|
||||
.setContentTitle(name)
|
||||
.setContentText(String.format("%d%% %s/%s", percent, loadedSI, sizeSI))
|
||||
.setProgress(100, (int) percent, false)
|
||||
.setContentIntent(pendingIntent);
|
||||
if (ActivityCompat.checkSelfPermission(activity, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
|
||||
// TODO: Consider calling
|
||||
// ActivityCompat#requestPermissions
|
||||
// here to request the missing permissions, and then overriding
|
||||
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
|
||||
// int[] grantResults)
|
||||
// to handle the case where the user grants the permission. See the documentation
|
||||
// for ActivityCompat#requestPermissions for more details.
|
||||
return;
|
||||
}
|
||||
notifiManager.notify(Transfer.NOTIF_SERVICE, notifBuilder.build());
|
||||
|
||||
uri = FileProvider.getUriForFile(activity, activity.getPackageName(), outputFile);
|
||||
if (app_started && fragment_on)
|
||||
showProgressFragment();
|
||||
|
||||
} catch (IOException e) {
|
||||
} catch (ConcurrentModificationException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
handleSendFile(uri);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public String uploadFile() throws IOException {
|
||||
URL url = null;
|
||||
HttpURLConnection conn = null;
|
||||
DataOutputStream request = null;
|
||||
String boundary = "*****";
|
||||
int maxBufferSize = 1 * 1024 * 1024;
|
||||
byte[] buffer = new byte[maxBufferSize];
|
||||
int bufferLength;
|
||||
loaded = 0;
|
||||
public void progressEnd() {
|
||||
progressUpdate();
|
||||
activity.runOnUiThread(() -> {
|
||||
|
||||
String fileNameUTF8 = new String(fileName.getBytes(), StandardCharsets.ISO_8859_1);
|
||||
notifiManager.cancel(Transfer.NOTIF_SERVICE);
|
||||
|
||||
String type = activity.getContentResolver().getType(uri);
|
||||
|
||||
url = new URL(protocol, host, port, root + "/upload.php");
|
||||
|
||||
url = checkRedirection(url);
|
||||
|
||||
Progress.PreProgress(this);
|
||||
|
||||
if(url != null) {
|
||||
|
||||
Log.d("URL", url.toString());
|
||||
|
||||
conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setDoInput(true); // Allow Inputs
|
||||
conn.setDoOutput(true); // Allow Outputs
|
||||
conn.setUseCaches(false); // Don't use a Cached Copy
|
||||
conn.setChunkedStreamingMode(maxBufferSize);
|
||||
conn.setRequestMethod("POST");
|
||||
conn.setRequestProperty("Connection", "keep-alive");
|
||||
conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
|
||||
|
||||
conn.connect();
|
||||
|
||||
request = new DataOutputStream(conn.getOutputStream());
|
||||
|
||||
request.writeBytes("--" + boundary + "\r\n");
|
||||
request.writeBytes("Content-Disposition: form-data; name=\"file\"; filename=\"" + fileNameUTF8 + "\"\r\n");
|
||||
request.writeBytes("Content-Type: " + type + "\r\n\r\n");
|
||||
|
||||
InputStream in = activity.getContentResolver().openInputStream(uri);
|
||||
|
||||
while ((bufferLength = in.read(buffer)) > 0) {
|
||||
request.write(buffer, 0, bufferLength);
|
||||
loaded+= (long) bufferLength;
|
||||
loadedHuman = Transfer.humanReadableByteCountBin(loaded);
|
||||
percent = ((loaded * 100) / fileSize);
|
||||
Progress.ProgressUpdateDelay(this);
|
||||
if (!app_started) {
|
||||
notifBuilder.setSmallIcon(R.drawable.ic_upload_and_download_from_the_cloud)
|
||||
.setContentTitle(name)
|
||||
.setContentText(info)
|
||||
.setProgress(0, 0, false)
|
||||
.setContentIntent(pendingIntent);
|
||||
notifiManager.notify(id, notifBuilder.build());
|
||||
}
|
||||
|
||||
request.writeBytes("\r\n");
|
||||
request.writeBytes("--" + boundary + "--\r\n");
|
||||
System.out.println(message);
|
||||
/*Snackbar.make(Transfer.activity.findViewById(R.id.view_pager), tr.message, Snackbar.LENGTH_LONG)
|
||||
.setAction("Action", null).show();*/
|
||||
Toast.makeText(activity, message, Toast.LENGTH_SHORT).show();
|
||||
|
||||
in.close();
|
||||
|
||||
int responseCode = conn.getResponseCode();
|
||||
|
||||
if (responseCode == HttpURLConnection.HTTP_OK) {
|
||||
message = "File " + fileName + " successful upload";
|
||||
state = Transfer.STATE_SUCCESS;
|
||||
Progress.PostProgress(this);
|
||||
}
|
||||
else {
|
||||
String s = conn.getResponseMessage();
|
||||
throw new HttpErrorException("HTTP Error code " + responseCode + " " + s);
|
||||
}
|
||||
|
||||
request.flush();
|
||||
|
||||
request.close();
|
||||
|
||||
conn.disconnect();
|
||||
}
|
||||
|
||||
return message;
|
||||
});
|
||||
}
|
||||
|
||||
public void showProgressFragment(){
|
||||
|
||||
public File file;
|
||||
public String href;
|
||||
public Button button;
|
||||
LinearLayout groot = fragment_progress.findViewById(R.id.groot);
|
||||
|
||||
public void downloadFile() throws IOException {
|
||||
URL url = null;
|
||||
HttpURLConnection conn = null;
|
||||
int maxBufferSize = 1 * 1024 * 1024;
|
||||
byte[] buffer = new byte[maxBufferSize];
|
||||
int bufferLength;
|
||||
loaded = 0;
|
||||
View progress = groot.findViewById(id);
|
||||
|
||||
Progress.PreProgress(this);
|
||||
|
||||
String[] parts = href.split("/");
|
||||
String path = "";
|
||||
for(int i=0; i< parts.length - 1; i++) {
|
||||
path = path + parts[i] + "/";
|
||||
}
|
||||
String query = URLEncoder.encode(parts[parts.length - 1], StandardCharsets.UTF_8.toString());
|
||||
url = new URL(protocol, host, port, path + query.replace("+", "%20"));
|
||||
conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setDoOutput(true);
|
||||
conn.setRequestMethod("GET");
|
||||
conn.setConnectTimeout(2000);
|
||||
|
||||
Log.d("URL", url.toString());
|
||||
|
||||
conn.connect();
|
||||
|
||||
int responseCode = conn.getResponseCode();
|
||||
|
||||
if (responseCode == HttpURLConnection.HTTP_OK) {
|
||||
|
||||
FileOutputStream fileOutput = new FileOutputStream(file);
|
||||
InputStream in = conn.getInputStream();
|
||||
|
||||
while ((bufferLength = in.read(buffer)) > 0) {
|
||||
fileOutput.write(buffer, 0, bufferLength);
|
||||
loaded+= (long) bufferLength;
|
||||
loadedHuman = Transfer.humanReadableByteCountBin(loaded);
|
||||
percent = ((loaded * 100) / fileSize);
|
||||
Progress.ProgressUpdateDelay(this);
|
||||
}
|
||||
fileOutput.close();
|
||||
|
||||
conn.disconnect();
|
||||
|
||||
message = "File " + fileName + " successful download";
|
||||
state = Transfer.STATE_SUCCESS;
|
||||
Progress.PostProgress(this);
|
||||
|
||||
}
|
||||
else {
|
||||
String s = conn.getResponseMessage();
|
||||
throw new HttpErrorException("HTTP Error code " + responseCode + " " + s);
|
||||
if (progress == null) {
|
||||
progress = inflater.inflate(R.layout.progress, null);
|
||||
progress.setId(id);
|
||||
final View final_progress = progress;
|
||||
activity.runOnUiThread(() -> {
|
||||
groot.addView(final_progress, 0);
|
||||
});
|
||||
}
|
||||
|
||||
conn.disconnect();
|
||||
((ProgressBar) progress.findViewById(R.id.progressBar)).setProgress((int) percent);
|
||||
((ImageView) progress.findViewById(R.id.transferType)).setImageResource(drawable);
|
||||
((TextView) progress.findViewById(R.id.progressText)).setText(percent + " %");
|
||||
((TextView) progress.findViewById(R.id.fileName)).setText(name);
|
||||
((TextView) progress.findViewById(R.id.fileSize)).setText(String.format("%s/%s", loadedSI, sizeSI));
|
||||
|
||||
if (state == Transfer.STATE_SUCCESS)
|
||||
((TextView) progress.findViewById(R.id.fileName)).setTextColor(Color.GREEN);
|
||||
else if (state == Transfer.STATE_FAILED)
|
||||
((TextView) progress.findViewById(R.id.fileName)).setTextColor(Color.RED);
|
||||
}
|
||||
|
||||
public static boolean setButton(String name, Button button) {
|
||||
|
||||
for (Object obj: instances) {
|
||||
Transfer tr = (Transfer) obj;
|
||||
if (name.equals(tr.fileName) && tr.state == STATE_RUNNING) {
|
||||
tr.button = button;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static String getFileList() throws IOException {
|
||||
URL url = null;
|
||||
HttpURLConnection conn = null;
|
||||
|
||||
String fileList = "";
|
||||
int buf;
|
||||
|
||||
url = new URL(protocol, host, port, root + "/list.php");
|
||||
conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setConnectTimeout(2000);
|
||||
|
||||
conn.connect();
|
||||
|
||||
int responseCode = conn.getResponseCode();
|
||||
|
||||
if (responseCode == HttpURLConnection.HTTP_OK) {
|
||||
InputStreamReader isw = new InputStreamReader(conn.getInputStream());
|
||||
|
||||
while ((buf = isw.read()) > 0) {
|
||||
fileList = fileList + (char) buf;
|
||||
}
|
||||
}
|
||||
else {
|
||||
String s = conn.getResponseMessage();
|
||||
throw new HttpErrorException("HTTP Error code " + responseCode + " " + s);
|
||||
}
|
||||
|
||||
conn.disconnect();
|
||||
|
||||
return fileList;
|
||||
}
|
||||
|
||||
public static String deleteFile(String file) throws IOException {
|
||||
|
||||
URL url = null;
|
||||
HttpURLConnection conn = null;
|
||||
|
||||
String message;
|
||||
|
||||
String query = URLEncoder.encode(file, StandardCharsets.UTF_8.toString());
|
||||
String serverUrl = root + "/delete.php?file=" + query;
|
||||
url = new URL(protocol, host, port, serverUrl);
|
||||
conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setRequestMethod("GET");
|
||||
conn.setConnectTimeout(2000);
|
||||
|
||||
conn.connect();
|
||||
|
||||
int responseCode = conn.getResponseCode();
|
||||
|
||||
if (responseCode == HttpURLConnection.HTTP_OK) {
|
||||
|
||||
message = "File " + file + " successful deleted";
|
||||
}
|
||||
else {
|
||||
String s = conn.getResponseMessage();
|
||||
throw new HttpErrorException("HTTP Error code " + responseCode + " " + s);
|
||||
}
|
||||
|
||||
conn.disconnect();
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
private static URL checkRedirection(URL url) throws IOException {
|
||||
static URL checkRedirection(URL url) throws IOException {
|
||||
String location = null;
|
||||
HttpURLConnection conn = null;
|
||||
int responseCode;
|
||||
@ -488,18 +317,47 @@ public class Transfer {
|
||||
return url;
|
||||
}
|
||||
|
||||
public static void error(final String message) {
|
||||
public static String getFileList() throws IOException {
|
||||
URL url = null;
|
||||
HttpURLConnection conn = null;
|
||||
|
||||
String fileList = "";
|
||||
int buf;
|
||||
|
||||
url = new URL(protocol, host, port, root + "/list.php");
|
||||
conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setConnectTimeout(2000);
|
||||
|
||||
conn.connect();
|
||||
|
||||
int responseCode = conn.getResponseCode();
|
||||
|
||||
if (responseCode == HttpURLConnection.HTTP_OK) {
|
||||
InputStreamReader isw = new InputStreamReader(conn.getInputStream());
|
||||
|
||||
while ((buf = isw.read()) > 0) {
|
||||
fileList = fileList + (char) buf;
|
||||
}
|
||||
}
|
||||
else {
|
||||
String s = conn.getResponseMessage();
|
||||
throw new HttpErrorException("error code: " + responseCode + " " + s);
|
||||
}
|
||||
|
||||
conn.disconnect();
|
||||
|
||||
return fileList;
|
||||
}
|
||||
|
||||
private static int timeout;
|
||||
|
||||
public static void errorSnackbar(final String message) {
|
||||
|
||||
System.out.println(message);
|
||||
|
||||
if (activity != null) {
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Snackbar.make(activity.findViewById(R.id.view_pager), message, Snackbar.LENGTH_LONG)
|
||||
.setAction("Action", null).show();
|
||||
}
|
||||
});
|
||||
activity.runOnUiThread(() -> Snackbar.make(activity.findViewById(R.id.view_pager), message, Snackbar.LENGTH_LONG)
|
||||
.setAction("Action", null).show());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@ public class TransferService extends Service {
|
||||
|
||||
Intent notificationIntent = new Intent(this, MainActivity.class);
|
||||
PendingIntent pendingIntent = PendingIntent.getActivity(this,
|
||||
0, notificationIntent, 0);
|
||||
0, notificationIntent, PendingIntent.FLAG_IMMUTABLE);
|
||||
|
||||
Notification notification = new NotificationCompat.Builder(this, "CHANNEL_ID")
|
||||
.setContentIntent(pendingIntent)
|
||||
|
201
app/src/main/java/com/localtransfer/UploadFile.java
Normal file
201
app/src/main/java/com/localtransfer/UploadFile.java
Normal file
@ -0,0 +1,201 @@
|
||||
package com.localtransfer;
|
||||
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.provider.OpenableColumns;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.core.content.FileProvider;
|
||||
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.sql.Timestamp;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ConcurrentModificationException;
|
||||
import java.util.Date;
|
||||
|
||||
public class UploadFile extends Transfer {
|
||||
|
||||
public Uri uri;
|
||||
|
||||
public String type;
|
||||
|
||||
public UploadFile() {
|
||||
this.id = View.generateViewId();
|
||||
instances.add(this);
|
||||
info = "Upload complete";
|
||||
state = STATE_NOT_REQUESTED;
|
||||
drawable = R.drawable.ic_upload_24;
|
||||
}
|
||||
|
||||
public static void handleSendFile(Uri uri) {
|
||||
if (uri != null) {
|
||||
UploadFile file = new UploadFile();
|
||||
file.uri = uri;
|
||||
|
||||
Cursor cursor = activity.getContentResolver().query(uri, null, null, null, null);
|
||||
cursor.moveToFirst();
|
||||
|
||||
file.type = activity.getContentResolver().getType(uri);
|
||||
|
||||
int col_name = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
|
||||
if (col_name != -1)
|
||||
file.name = cursor.getString(col_name);
|
||||
if(file.name == null)
|
||||
file.name = file.type.split("/")[0] + "_" + new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()) + "." + file.type.split("/")[1];
|
||||
|
||||
int col_size = cursor.getColumnIndex(OpenableColumns.SIZE);
|
||||
if (col_name != -1) {
|
||||
file.size = cursor.getLong(col_size);
|
||||
file.sizeSI = Transfer.humanReadableByteCountBin(file.size);
|
||||
}
|
||||
|
||||
file.AddTransfer();
|
||||
}
|
||||
}
|
||||
|
||||
public static void handleSendText(String sharedText) {
|
||||
if (sharedText != null) {
|
||||
SimpleDateFormat sdfDate = new SimpleDateFormat("yyyyMMdd_HHmmss");
|
||||
Date now = new Date();
|
||||
String strDate = sdfDate.format(now);
|
||||
Uri uri = null;
|
||||
|
||||
try {
|
||||
File outputFile = new File(activity.getCacheDir(), strDate + ".txt");
|
||||
FileOutputStream fileOut = new FileOutputStream(outputFile);
|
||||
OutputStreamWriter OutWriter = new OutputStreamWriter(fileOut);
|
||||
OutWriter.append(sharedText);
|
||||
OutWriter.close();
|
||||
|
||||
fileOut.flush();
|
||||
fileOut.close();
|
||||
|
||||
uri = FileProvider.getUriForFile(activity, activity.getPackageName(), outputFile);
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
handleSendFile(uri);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startTransfer() {
|
||||
super.startTransfer();
|
||||
|
||||
startedTime = new Timestamp(System.currentTimeMillis());
|
||||
|
||||
state = STATE_RUNNING;
|
||||
|
||||
try {
|
||||
uploadFile();
|
||||
} catch (IOException e) {
|
||||
final String ExceptionName = e.getClass().getSimpleName();
|
||||
final String ExceptionMess = e.getMessage();
|
||||
|
||||
state = Transfer.STATE_FAILED;
|
||||
progressEnd();
|
||||
|
||||
if(ExceptionName != null && ExceptionMess != null) {
|
||||
errorSnackbar(ExceptionMess);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private String uploadFile() throws IOException {
|
||||
String message = null;
|
||||
URL url = null;
|
||||
HttpURLConnection conn = null;
|
||||
DataOutputStream request = null;
|
||||
String boundary = "*****";
|
||||
final int maxBufferSize = 1 * 1024 * 1024;
|
||||
byte[] buffer = new byte[maxBufferSize];
|
||||
int bufferLength;
|
||||
loaded = 0;
|
||||
|
||||
Cursor cursor = activity.getContentResolver().query(uri, null, null, null, null);
|
||||
cursor.moveToFirst();
|
||||
|
||||
String fileNameUTF8 = new String(name.getBytes(), StandardCharsets.ISO_8859_1);
|
||||
|
||||
url = new URL(protocol, host, port, root + "/upload.php");
|
||||
|
||||
url = checkRedirection(url);
|
||||
|
||||
Log.d("URL", url.toString());
|
||||
|
||||
conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setDoInput(true); // Allow Inputs
|
||||
conn.setDoOutput(true); // Allow Outputs
|
||||
conn.setUseCaches(false); // Don't use a Cached Copy
|
||||
conn.setChunkedStreamingMode(maxBufferSize);
|
||||
conn.setRequestMethod("POST");
|
||||
conn.setRequestProperty("Connection", "keep-alive");
|
||||
conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
|
||||
|
||||
conn.connect();
|
||||
|
||||
request = new DataOutputStream(conn.getOutputStream());
|
||||
|
||||
request.writeBytes("--" + boundary + "\r\n");
|
||||
request.writeBytes("Content-Disposition: form-data; name=\"file\"; filename=\"" + fileNameUTF8 + "\"\r\n");
|
||||
request.writeBytes("Content-Type: " + type + "\r\n\r\n");
|
||||
|
||||
InputStream in = activity.getContentResolver().openInputStream(uri);
|
||||
|
||||
size = in.available();
|
||||
sizeSI = Transfer.humanReadableByteCountBin(size);
|
||||
|
||||
while ((bufferLength = in.read(buffer)) > 0) {
|
||||
request.write(buffer, 0, bufferLength);
|
||||
loaded+= bufferLength;
|
||||
percent = ((loaded * 100) / size);
|
||||
progressUpdateDelay();
|
||||
}
|
||||
|
||||
request.writeBytes("\r\n");
|
||||
request.writeBytes("--" + boundary + "--\r\n");
|
||||
|
||||
in.close();
|
||||
|
||||
int responseCode = conn.getResponseCode();
|
||||
|
||||
if (responseCode == HttpURLConnection.HTTP_OK) {
|
||||
message = "File " + name + " successful upload";
|
||||
state = Transfer.STATE_SUCCESS;
|
||||
progressEnd();
|
||||
}
|
||||
else {
|
||||
String s = conn.getResponseMessage();
|
||||
throw new HttpErrorException("error code: " + responseCode + " " + s);
|
||||
}
|
||||
|
||||
request.flush();
|
||||
|
||||
request.close();
|
||||
|
||||
conn.disconnect();
|
||||
|
||||
System.out.println(message);
|
||||
if (activity != null) {
|
||||
String finalMessage = message;
|
||||
activity.runOnUiThread(() ->
|
||||
Snackbar.make(activity.findViewById(R.id.view_pager), finalMessage, Snackbar.LENGTH_LONG)
|
||||
.setAction("Action", null).show());
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
}
|
@ -3,14 +3,10 @@ package com.localtransfer.fragment;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.core.content.FileProvider;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
|
||||
import android.os.Environment;
|
||||
import android.view.ContextMenu;
|
||||
import android.view.Gravity;
|
||||
@ -24,10 +20,14 @@ import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
import com.localtransfer.BuildConfig;
|
||||
import com.localtransfer.R;
|
||||
import com.localtransfer.DownloadFile;
|
||||
import com.localtransfer.Transfer;
|
||||
|
||||
import org.json.JSONArray;
|
||||
@ -35,8 +35,6 @@ import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
@ -52,6 +50,7 @@ public class DownloadFragment extends Fragment {
|
||||
}
|
||||
|
||||
private View root;
|
||||
private LayoutInflater inflater;
|
||||
|
||||
public static DownloadFragment newInstance() {
|
||||
DownloadFragment fragment = new DownloadFragment();
|
||||
@ -68,17 +67,20 @@ public class DownloadFragment extends Fragment {
|
||||
Bundle savedInstanceState) {
|
||||
root = inflater.inflate(R.layout.fragment_download, container, false);
|
||||
|
||||
this.inflater = inflater;
|
||||
|
||||
new Timer().schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
showFileList();
|
||||
listFile();
|
||||
}
|
||||
}, 100);
|
||||
|
||||
SwipeRefreshLayout refresh = root.findViewById(R.id.refresh);
|
||||
|
||||
|
||||
refresh.setOnRefreshListener(() -> {
|
||||
new Thread(() -> showFileList()).start();
|
||||
listFile();
|
||||
refresh.setRefreshing(false);
|
||||
});
|
||||
|
||||
@ -107,21 +109,21 @@ public class DownloadFragment extends Fragment {
|
||||
public boolean onContextItemSelected(MenuItem item) {
|
||||
if (item.getTitle() == "Delete") {
|
||||
LinearLayout fileDesc = (LinearLayout) root.findViewById(item.getItemId());
|
||||
final String file = String.valueOf(fileDesc.getTag(R.id.ID_FILE_NAME));
|
||||
DownloadFile file = (DownloadFile) DownloadFile.getFileById((Integer) fileDesc.getTag(R.id.ID_DOWNLOAD));
|
||||
new Thread(() -> {
|
||||
try {
|
||||
String message = Transfer.deleteFile(file);
|
||||
String message = file.deleteFile();
|
||||
System.out.println(message);
|
||||
Transfer.activity.runOnUiThread(() ->
|
||||
getActivity().runOnUiThread(() ->
|
||||
Snackbar.make(getActivity().findViewById(R.id.view_pager), message, Snackbar.LENGTH_LONG)
|
||||
.setAction("Action", null).show());
|
||||
showFileList();
|
||||
listFile();
|
||||
} catch (IOException e) {
|
||||
String ExceptionName = e.getClass().getSimpleName();
|
||||
String ExceptionMess = e.getMessage();
|
||||
|
||||
if(ExceptionName != null && ExceptionMess != null) {
|
||||
Transfer.error(ExceptionMess);
|
||||
Transfer.errorSnackbar(ExceptionMess);
|
||||
}
|
||||
|
||||
}
|
||||
@ -133,204 +135,175 @@ public class DownloadFragment extends Fragment {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void showFileList() {
|
||||
public void listFile() {
|
||||
new Thread(() -> {
|
||||
final TextView title = new TextView(Transfer.activity);
|
||||
final LinearLayout main_layout = root.findViewById(R.id.main_layout);
|
||||
try {
|
||||
String data = Transfer.getFileList();
|
||||
|
||||
final TextView title = new TextView(Transfer.activity);
|
||||
title.setTextSize(18);
|
||||
title.setGravity(Gravity.CENTER);
|
||||
final LinearLayout main_layout = root.findViewById(R.id.main_layout);
|
||||
final LayoutInflater inflater = (LayoutInflater) getActivity().getSystemService(getContext().LAYOUT_INFLATER_SERVICE);
|
||||
if (data.equals("[]")) {
|
||||
title.setTextSize(18);
|
||||
title.setGravity(Gravity.CENTER);
|
||||
main_layout.removeAllViews();
|
||||
main_layout.addView(title);
|
||||
title.setHeight(1000);
|
||||
title.setText("No file to download");
|
||||
}
|
||||
else {
|
||||
|
||||
String data = "";
|
||||
|
||||
try {
|
||||
data = Transfer.getFileList();
|
||||
} catch (IOException e) {
|
||||
final String ExceptionName = e.getClass().getSimpleName();
|
||||
final String ExceptionMess = e.getMessage();
|
||||
|
||||
if(ExceptionName != null && ExceptionMess != null) {
|
||||
Transfer.error(ExceptionMess);
|
||||
Transfer.activity.runOnUiThread(() -> {
|
||||
if(main_layout != null)
|
||||
getActivity().runOnUiThread(() -> {
|
||||
main_layout.removeAllViews();
|
||||
if(title != null) {
|
||||
main_layout.addView(title);
|
||||
title.setText(ExceptionMess);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
if (data.equals("[]")) {
|
||||
Transfer.activity.runOnUiThread(() -> {
|
||||
main_layout.removeAllViews();
|
||||
main_layout.addView(title);
|
||||
title.setHeight(1000);
|
||||
title.setText("No file to download");
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
JSONArray array;
|
||||
array = new JSONArray(data);
|
||||
|
||||
Transfer.activity.runOnUiThread(() -> {
|
||||
main_layout.removeAllViews();
|
||||
final View line = inflater.inflate(R.layout.horizontal_line, null);
|
||||
main_layout.addView(line);
|
||||
});
|
||||
for (int i = 0; i < array.length(); i++) {
|
||||
JSONObject row = array.getJSONObject(i);
|
||||
final String name = row.getString("name");
|
||||
final String href = row.getString("href");
|
||||
final long size = row.getLong("size");
|
||||
final String mime = row.getString("mime");
|
||||
final String type = row.getString("type");
|
||||
|
||||
Transfer.activity.runOnUiThread(() -> {
|
||||
title.setText("Choose file to download");
|
||||
View file_info = inflater.inflate(R.layout.file_info, null);
|
||||
main_layout.addView(file_info);
|
||||
ImageView image = file_info.findViewById(R.id.file_image);
|
||||
TextView viewName = file_info.findViewById(R.id.file_name);
|
||||
TextView viewType = file_info.findViewById(R.id.file_type);
|
||||
TextView viewSize = file_info.findViewById(R.id.file_size);
|
||||
LinearLayout fileDesc = file_info.findViewById(R.id.file_desc);
|
||||
LinearLayout file_buttons = file_info.findViewById(R.id.file_buttons);
|
||||
|
||||
fileDesc.setId(View.generateViewId());
|
||||
file_buttons.setId(View.generateViewId());
|
||||
file_buttons.setTag(R.id.ID_FILE_BUTTONS, "FOR VISIBILITY");
|
||||
|
||||
registerForContextMenu(fileDesc);
|
||||
fileDesc.setTag(R.id.ID_FILE_NAME, name);
|
||||
|
||||
viewName.setText(name);
|
||||
viewType.setText(mime);
|
||||
viewSize.setText(Transfer.humanReadableByteCountBin(size));
|
||||
|
||||
switch (type) {
|
||||
case "file-image":
|
||||
image.setImageResource(R.drawable.ic_icon_image);
|
||||
break;
|
||||
case "file-audio":
|
||||
image.setImageResource(R.drawable.ic_icon_music);
|
||||
break;
|
||||
case "file-video":
|
||||
image.setImageResource(R.drawable.ic_icon_video);
|
||||
break;
|
||||
default:
|
||||
image.setImageResource(R.drawable.ic_icon_file);
|
||||
}
|
||||
|
||||
fileDesc.setOnClickListener(view -> {
|
||||
String save_location;
|
||||
|
||||
if (mime.equals("text/plain"))
|
||||
save_location = getContext().getCacheDir().toString();
|
||||
else
|
||||
save_location = Environment.getExternalStorageDirectory() + "/" + Transfer.local_storage;
|
||||
|
||||
File file = new File(save_location, name);
|
||||
|
||||
file_buttons.setId(View.generateViewId());
|
||||
|
||||
Button Bview = file_buttons.findViewById(R.id.file_view);
|
||||
Button Bshare = file_buttons.findViewById(R.id.file_share);
|
||||
Button dl = file_buttons.findViewById(R.id.file_download);
|
||||
|
||||
dl.setOnClickListener(ListenerDL);
|
||||
Bview.setOnClickListener(ListenerView);
|
||||
Bshare.setOnClickListener(ListenerShare);
|
||||
|
||||
if (file.exists() && file.length() == size) {
|
||||
Bview.setVisibility(LinearLayout.VISIBLE);
|
||||
Bshare.setVisibility(LinearLayout.VISIBLE);
|
||||
dl.setVisibility(LinearLayout.GONE);
|
||||
}
|
||||
else {
|
||||
dl.setVisibility(LinearLayout.VISIBLE);
|
||||
Bview.setVisibility(LinearLayout.GONE);
|
||||
Bshare.setVisibility(LinearLayout.GONE);
|
||||
}
|
||||
|
||||
if (Transfer.setButton(name, dl)) {
|
||||
dl.setEnabled(false);
|
||||
final Drawable spinner = Transfer.activity.getDrawable(R.drawable.ic_spinner_rotate);
|
||||
int h = spinner.getIntrinsicHeight();
|
||||
int w = spinner.getIntrinsicWidth();
|
||||
spinner.setBounds(0, 0, w, h);
|
||||
dl.setCompoundDrawables(dl.getCompoundDrawables()[0], null, spinner, null);
|
||||
ObjectAnimator anim = ObjectAnimator.ofInt(spinner, "level", 0, 10000);
|
||||
anim.setDuration(1000);
|
||||
anim.setRepeatCount(Animation.INFINITE);
|
||||
anim.setInterpolator(new LinearInterpolator());
|
||||
anim.start();
|
||||
}
|
||||
|
||||
file_buttons.setTag(R.id.ID_FILE_NAME, name);
|
||||
file_buttons.setTag(R.id.ID_FILE_SIZE, size);
|
||||
file_buttons.setTag(R.id.ID_FILE_HREF, href);
|
||||
file_buttons.setTag(R.id.ID_FILE_MIME, mime);
|
||||
file_buttons.setTag(R.id.ID_SAVE_LOCATION, save_location);
|
||||
int state = file_buttons.getVisibility();
|
||||
if(state == LinearLayout.GONE) {
|
||||
for(View child : getAllChildren(main_layout)) {
|
||||
if(child.getTag(R.id.ID_FILE_BUTTONS) != null)
|
||||
child.setVisibility(LinearLayout.GONE);
|
||||
}
|
||||
file_buttons.setVisibility(LinearLayout.VISIBLE);
|
||||
}
|
||||
else if(state == LinearLayout.VISIBLE)
|
||||
file_buttons.setVisibility(LinearLayout.GONE);
|
||||
final View line = inflater.inflate(R.layout.horizontal_line, null);
|
||||
main_layout.addView(line);
|
||||
});
|
||||
|
||||
});
|
||||
try {
|
||||
JSONArray array = new JSONArray(data);
|
||||
for (int i = 0; i < array.length(); i++) {
|
||||
Integer id = View.generateViewId();
|
||||
DownloadFile trFile = new DownloadFile(id);
|
||||
|
||||
JSONObject row = array.getJSONObject(i);
|
||||
trFile.name = row.getString("name");
|
||||
trFile.size = row.getLong("size");
|
||||
trFile.href = row.getString("href");
|
||||
trFile.mime = row.getString("mime");
|
||||
trFile.type = row.getString("type");
|
||||
|
||||
getActivity().runOnUiThread(() -> showFileList(trFile));
|
||||
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
final String ExceptionName = e.getClass().getSimpleName();
|
||||
final String ExceptionMess = e.getMessage();
|
||||
|
||||
if(ExceptionName != null && ExceptionMess != null) {
|
||||
Transfer.errorSnackbar(ExceptionMess);
|
||||
}
|
||||
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}).start();
|
||||
}
|
||||
|
||||
private void setThumbnail(DownloadFile file, ImageView image) {
|
||||
new Thread(() -> {
|
||||
InputStream thumbnail = file.getThumbnail();
|
||||
Bitmap bitmap = BitmapFactory.decodeStream(thumbnail);
|
||||
getActivity().runOnUiThread(() -> {
|
||||
image.setImageBitmap(bitmap);
|
||||
});
|
||||
}).start();
|
||||
}
|
||||
|
||||
private void showFileList(DownloadFile trFile) {
|
||||
|
||||
final LinearLayout main_layout = root.findViewById(R.id.main_layout);
|
||||
|
||||
View file_info = inflater.inflate(R.layout.file_info, null);
|
||||
main_layout.addView(file_info);
|
||||
ImageView image = file_info.findViewById(R.id.file_image);
|
||||
TextView viewName = file_info.findViewById(R.id.file_name);
|
||||
TextView viewType = file_info.findViewById(R.id.file_type);
|
||||
TextView viewSize = file_info.findViewById(R.id.file_size);
|
||||
LinearLayout fileDesc = file_info.findViewById(R.id.file_desc);
|
||||
LinearLayout file_buttons = file_info.findViewById(R.id.file_buttons);
|
||||
|
||||
fileDesc.setId(View.generateViewId());
|
||||
|
||||
registerForContextMenu(fileDesc);
|
||||
|
||||
file_buttons.setId(trFile.getId());
|
||||
file_buttons.setTag(R.id.ID_DOWNLOAD, trFile.getId());
|
||||
fileDesc.setTag(R.id.ID_DOWNLOAD, trFile.getId());
|
||||
file_buttons.setTag(R.id.ID_FILE_BUTTONS, "FOR VISIBILITY");
|
||||
|
||||
|
||||
trFile.setButton(file_buttons.findViewById(R.id.file_download));
|
||||
|
||||
viewName.setText(trFile.name);
|
||||
viewType.setText(trFile.mime);
|
||||
viewSize.setText(Transfer.humanReadableByteCountBin(trFile.size));
|
||||
|
||||
switch (trFile.type) {
|
||||
case "file-image":
|
||||
image.setImageResource(R.drawable.ic_icon_image);
|
||||
setThumbnail(trFile, image);
|
||||
break;
|
||||
case "file-video":
|
||||
image.setImageResource(R.drawable.ic_icon_video);
|
||||
setThumbnail(trFile, image);
|
||||
break;
|
||||
case "file-audio":
|
||||
image.setImageResource(R.drawable.ic_icon_music);
|
||||
break;
|
||||
default:
|
||||
image.setImageResource(R.drawable.ic_icon_file);
|
||||
}
|
||||
|
||||
fileDesc.setOnClickListener(view -> {
|
||||
|
||||
Button Bview = file_buttons.findViewById(R.id.file_view);
|
||||
Button Bshare = file_buttons.findViewById(R.id.file_share);
|
||||
Button Bdownload = file_buttons.findViewById(R.id.file_download);
|
||||
|
||||
Bdownload.setOnClickListener(ListenerDL);
|
||||
Bview.setOnClickListener(ListenerView);
|
||||
Bshare.setOnClickListener(ListenerShare);
|
||||
|
||||
if (trFile.exist(getContext())) {
|
||||
Bview.setVisibility(LinearLayout.VISIBLE);
|
||||
Bshare.setVisibility(LinearLayout.VISIBLE);
|
||||
Bdownload.setVisibility(LinearLayout.GONE);
|
||||
}
|
||||
else {
|
||||
Bdownload.setVisibility(LinearLayout.VISIBLE);
|
||||
Bview.setVisibility(LinearLayout.GONE);
|
||||
Bshare.setVisibility(LinearLayout.GONE);
|
||||
}
|
||||
|
||||
trFile.setButton(Bdownload);
|
||||
|
||||
int state = file_buttons.getVisibility();
|
||||
if(state == LinearLayout.GONE) {
|
||||
for(View child : getAllChildren(main_layout)) {
|
||||
if(child.getTag(R.id.ID_FILE_BUTTONS) != null)
|
||||
child.setVisibility(LinearLayout.GONE);
|
||||
}
|
||||
file_buttons.setVisibility(LinearLayout.VISIBLE);
|
||||
}
|
||||
else if(state == LinearLayout.VISIBLE)
|
||||
file_buttons.setVisibility(LinearLayout.GONE);
|
||||
});
|
||||
}
|
||||
|
||||
private View.OnClickListener ListenerDL = v -> {
|
||||
v.setEnabled(false);
|
||||
final LinearLayout layout = (LinearLayout) v.getParent();
|
||||
final Button button = layout.findViewById(R.id.file_download);
|
||||
final Button button = (Button) v;
|
||||
button.setText(String.format("Download pending"));
|
||||
|
||||
final String name = (String) layout.getTag(R.id.ID_FILE_NAME);
|
||||
final String save_location = String.valueOf(layout.getTag(R.id.ID_SAVE_LOCATION));
|
||||
final long fileSize = (long) layout.getTag(R.id.ID_FILE_SIZE);
|
||||
final String href = (String) layout.getTag(R.id.ID_FILE_HREF);
|
||||
final Integer id = (Integer) layout.getTag(R.id.ID_DOWNLOAD);
|
||||
|
||||
new File(save_location).mkdirs();
|
||||
File file = new File(save_location, name);
|
||||
|
||||
Transfer tr = new Transfer(Transfer.TYPE_DOWNLOAD);
|
||||
tr.file = file;
|
||||
tr.fileName = name;
|
||||
tr.fileSize = fileSize;
|
||||
tr.fileSizeHuman = Transfer.humanReadableByteCountBin(fileSize);
|
||||
tr.href = href;
|
||||
tr.button = button;
|
||||
tr.AddTransfer();
|
||||
DownloadFile file = (DownloadFile) DownloadFile.getFileById(id);
|
||||
file.sizeSI = Transfer.humanReadableByteCountBin(file.size);
|
||||
file.AddTransfer();
|
||||
};
|
||||
|
||||
private View.OnClickListener ListenerShare = v -> {
|
||||
LinearLayout layout = (LinearLayout) v.getParent();
|
||||
final String name = (String) layout.getTag(R.id.ID_FILE_NAME);
|
||||
final String type = (String) layout.getTag(R.id.ID_FILE_MIME);
|
||||
final Integer id = (Integer) layout.getTag(R.id.ID_DOWNLOAD);
|
||||
|
||||
final String save_location = String.valueOf(layout.getTag(R.id.ID_SAVE_LOCATION));
|
||||
File file = new File(save_location, name);
|
||||
Uri uri = FileProvider.getUriForFile(getContext(), BuildConfig.APPLICATION_ID, file);
|
||||
DownloadFile dl = (DownloadFile) DownloadFile.getFileById(id);
|
||||
|
||||
if(type.equals("text/plain")) {
|
||||
if(dl.mime.equals("text/plain")) {
|
||||
String text = null;
|
||||
try {
|
||||
InputStream is = new FileInputStream(file);
|
||||
InputStream is = getActivity().getContentResolver().openInputStream(dl.uri);
|
||||
BufferedReader buf = new BufferedReader(new InputStreamReader(is));
|
||||
|
||||
String line;
|
||||
@ -348,47 +321,43 @@ public class DownloadFragment extends Fragment {
|
||||
|
||||
try {
|
||||
Intent intent = new Intent(Intent.ACTION_SEND);
|
||||
intent.setType(type);
|
||||
intent.setType(dl.mime);
|
||||
intent.putExtra(Intent.EXTRA_TEXT, text);
|
||||
startActivity(Intent.createChooser(intent, getString(R.string.share_title)));
|
||||
} catch (ActivityNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
Toast.makeText(getActivity(), "Can't share " + dl.mime, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
else {
|
||||
try {
|
||||
Intent intent = new Intent(Intent.ACTION_SEND);
|
||||
intent.putExtra(Intent.EXTRA_STREAM, uri);
|
||||
intent.setType(type);
|
||||
intent.putExtra(Intent.EXTRA_STREAM, dl.uri);
|
||||
intent.setType(dl.mime);
|
||||
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
startActivity(Intent.createChooser(intent, getString(R.string.share_title)));
|
||||
} catch (ActivityNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
Toast.makeText(getActivity(), "Can't share " + dl.mime, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
private View.OnClickListener ListenerView = v -> {
|
||||
LinearLayout layout = (LinearLayout) v.getParent();
|
||||
final String name = (String) layout.getTag(R.id.ID_FILE_NAME);
|
||||
final String type = (String) layout.getTag(R.id.ID_FILE_MIME);
|
||||
final Integer id = (Integer) layout.getTag(R.id.ID_DOWNLOAD);
|
||||
|
||||
final String save_location = String.valueOf(layout.getTag(R.id.ID_SAVE_LOCATION));
|
||||
File file = new File(save_location, name);
|
||||
Uri uri = FileProvider.getUriForFile(getContext(), BuildConfig.APPLICATION_ID, file);
|
||||
DownloadFile dl = (DownloadFile) DownloadFile.getFileById(id);
|
||||
|
||||
try {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setDataAndType(uri, type);
|
||||
intent.setDataAndType(dl.uri, dl.mime);
|
||||
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
startActivity(intent);
|
||||
} catch (ActivityNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
Toast.makeText(getActivity(), "No " + dl.mime + " viewer", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
private List<View> getAllChildren(View v) {
|
||||
|
@ -2,26 +2,16 @@ package com.localtransfer.fragment;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import androidx.core.app.NotificationManagerCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.localtransfer.Progress;
|
||||
import com.localtransfer.R;
|
||||
import com.localtransfer.Transfer;
|
||||
|
||||
import java.util.ConcurrentModificationException;
|
||||
import java.util.List;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
public class ProgressFragment extends Fragment {
|
||||
|
||||
@ -43,21 +33,20 @@ public class ProgressFragment extends Fragment {
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
// Inflate the layout for this fragment
|
||||
Progress.root = inflater.inflate(R.layout.fragment_progress, container, false);
|
||||
Transfer.fragment_progress = inflater.inflate(R.layout.fragment_progress, container, false);
|
||||
|
||||
return Progress.root;
|
||||
return Transfer.fragment_progress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume(){
|
||||
super.onResume();
|
||||
|
||||
Progress.fragment_on = true;
|
||||
Transfer.fragment_on = true;
|
||||
|
||||
List instances = Transfer.getInstances();
|
||||
for (Object obj: instances) {
|
||||
Transfer tr = (Transfer) obj;
|
||||
Progress.showProgressFragment(tr);
|
||||
List<Transfer> instances = Transfer.getInstances();
|
||||
for (Transfer file: instances) {
|
||||
file.showProgressFragment();
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,6 +54,6 @@ public class ProgressFragment extends Fragment {
|
||||
public void onPause(){
|
||||
super.onPause();
|
||||
|
||||
Progress.fragment_on = false;
|
||||
Transfer.fragment_on = false;
|
||||
}
|
||||
}
|
@ -1,9 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<item name="ID_FILE_NAME" type="id" />
|
||||
<item name="ID_FILE_SIZE" type="id" />
|
||||
<item name="ID_FILE_HREF" type="id" />
|
||||
<item name="ID_FILE_MIME" type="id" />
|
||||
<item name="ID_SAVE_LOCATION" type="id" />
|
||||
<item name="ID_DOWNLOAD" type="id" />
|
||||
<item name="ID_FILE_BUTTONS" type="id" />
|
||||
</resources>
|
@ -23,15 +23,16 @@
|
||||
<!-- Server Preferences -->
|
||||
<string name="server_host">Host</string>
|
||||
<string name="server_protocol">Use secure https</string>
|
||||
<string name="server_host_def">www.netdldata.net</string>
|
||||
<string name="server_host_def">transfer.netdldata.net</string>
|
||||
<string name="server_port">Port</string>
|
||||
<string name="server_port_def">80</string>
|
||||
<string name="server_port_def"></string>
|
||||
<string name="server_root">Root</string>
|
||||
<string name="server_root_def">/transfer</string>
|
||||
<string name="server_root_def">/php</string>
|
||||
|
||||
<!-- Local Preferences -->
|
||||
<string name="local_storage">Local Storage</string>
|
||||
<string name="local_storage_def">Download/TransferLocal</string>
|
||||
<string name="use_shared_storage">Use shared storage</string>
|
||||
<string name="shared_storage">Shared Storage</string>
|
||||
<string name="shared_storage_def">Download/TransferLocal</string>
|
||||
|
||||
<!-- File buttons -->
|
||||
<string name="file_share">Share</string>
|
||||
|
6
app/src/main/res/xml/network_security_config.xml
Normal file
6
app/src/main/res/xml/network_security_config.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<domain-config cleartextTrafficPermitted="true">
|
||||
<domain includeSubdomains="true">netdldata.net</domain>
|
||||
</domain-config>
|
||||
</network-security-config>
|
@ -31,11 +31,17 @@
|
||||
|
||||
<PreferenceCategory app:title="@string/local_header">
|
||||
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:key="use_shared_storage"
|
||||
android:title="@string/use_shared_storage" />
|
||||
|
||||
<Preference
|
||||
app:key="local_storage"
|
||||
app:title="@string/local_storage"
|
||||
app:defaultValue="@string/local_storage_def"
|
||||
app:useSimpleSummaryProvider="true" />
|
||||
app:key="shared_storage"
|
||||
app:title="@string/shared_storage"
|
||||
app:defaultValue="@string/shared_storage_def"
|
||||
app:useSimpleSummaryProvider="true"
|
||||
app:isPreferenceVisible="false"/>
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
|
@ -1,17 +0,0 @@
|
||||
package com.localtransfer;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
public class ExampleUnitTest {
|
||||
@Test
|
||||
public void addition_isCorrect() {
|
||||
assertEquals(4, 2 + 2);
|
||||
}
|
||||
}
|
14
build.gradle
14
build.gradle
@ -2,10 +2,10 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:4.1.2'
|
||||
classpath 'com.android.tools.build:gradle:8.9.3'
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
@ -15,15 +15,17 @@ buildscript {
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
}
|
||||
gradle.projectsEvaluated {
|
||||
tasks.withType(JavaCompile) {
|
||||
options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
|
||||
tasks.withType(JavaCompile).tap {
|
||||
configureEach {
|
||||
options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
tasks.register('clean', Delete) {
|
||||
delete rootProject.buildDir
|
||||
}
|
@ -16,4 +16,7 @@ org.gradle.jvmargs=-Xmx2048m
|
||||
# https://developer.android.com/topic/libraries/support-library/androidx-rn
|
||||
android.useAndroidX=true
|
||||
# Automatically convert third-party libraries to use AndroidX
|
||||
android.enableJetifier=true
|
||||
android.enableJetifier=true
|
||||
android.defaults.buildfeatures.buildconfig=true
|
||||
android.nonTransitiveRClass=false
|
||||
android.nonFinalResIds=false
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-all.zip
|
||||
|
Reference in New Issue
Block a user