mirror of
https://github.com/KokaKiwi/BarInsta
synced 2024-11-18 12:47:30 +00:00
Remove IPTC from downloaded JPG files
This commit is contained in:
parent
09cf333cb0
commit
3ac2ee36aa
@ -31,5 +31,10 @@
|
|||||||
<option name="name" value="Google" />
|
<option name="name" value="Google" />
|
||||||
<option name="url" value="https://dl.google.com/dl/android/maven2/" />
|
<option name="url" value="https://dl.google.com/dl/android/maven2/" />
|
||||||
</remote-repository>
|
</remote-repository>
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="maven" />
|
||||||
|
<option name="name" value="maven" />
|
||||||
|
<option name="url" value="http://maven.geotoolkit.org/" />
|
||||||
|
</remote-repository>
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
@ -51,7 +51,9 @@ dependencies {
|
|||||||
def nav_version = '2.3.1'
|
def nav_version = '2.3.1'
|
||||||
|
|
||||||
implementation 'com.google.android.material:material:1.3.0-alpha03'
|
implementation 'com.google.android.material:material:1.3.0-alpha03'
|
||||||
implementation 'com.google.android.exoplayer:exoplayer:2.12.0'
|
|
||||||
|
implementation 'com.google.android.exoplayer:exoplayer-core:2.12.0'
|
||||||
|
implementation 'com.google.android.exoplayer:exoplayer-ui:2.12.0'
|
||||||
|
|
||||||
implementation "androidx.appcompat:appcompat:$appcompat_version"
|
implementation "androidx.appcompat:appcompat:$appcompat_version"
|
||||||
implementation "androidx.appcompat:appcompat-resources:$appcompat_version"
|
implementation "androidx.appcompat:appcompat-resources:$appcompat_version"
|
||||||
@ -68,7 +70,6 @@ dependencies {
|
|||||||
implementation 'com.google.guava:guava:27.0.1-android'
|
implementation 'com.google.guava:guava:27.0.1-android'
|
||||||
|
|
||||||
// implementation 'com.github.hendrawd:StorageUtil:1.1.0'
|
// implementation 'com.github.hendrawd:StorageUtil:1.1.0'
|
||||||
// implementation 'com.github.armcha:AutoLinkTextViewV2:2.1.1'
|
|
||||||
implementation 'com.github.ammargitham:AutoLinkTextViewV2:master-SNAPSHOT'
|
implementation 'com.github.ammargitham:AutoLinkTextViewV2:master-SNAPSHOT'
|
||||||
|
|
||||||
implementation 'org.jsoup:jsoup:1.13.1'
|
implementation 'org.jsoup:jsoup:1.13.1'
|
||||||
@ -79,6 +80,9 @@ dependencies {
|
|||||||
implementation 'com.squareup.retrofit2:converter-scalars:2.9.0'
|
implementation 'com.squareup.retrofit2:converter-scalars:2.9.0'
|
||||||
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
|
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
|
||||||
|
|
||||||
|
implementation 'com.github.dragon66:icafe:master-SNAPSHOT'
|
||||||
|
implementation 'javax.media:jai_imageio:1.1.1'
|
||||||
|
|
||||||
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.5'
|
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.5'
|
||||||
|
|
||||||
testImplementation 'org.junit.jupiter:junit-jupiter:5.7.0'
|
testImplementation 'org.junit.jupiter:junit-jupiter:5.7.0'
|
||||||
|
@ -5,7 +5,6 @@ import android.app.Activity;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.os.AsyncTask;
|
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
@ -37,13 +36,9 @@ import java.util.regex.Pattern;
|
|||||||
|
|
||||||
import awais.instagrabber.BuildConfig;
|
import awais.instagrabber.BuildConfig;
|
||||||
import awais.instagrabber.R;
|
import awais.instagrabber.R;
|
||||||
import awais.instagrabber.asyncs.DownloadAsync;
|
|
||||||
import awais.instagrabber.asyncs.PostFetcher;
|
|
||||||
import awais.instagrabber.models.BasePostModel;
|
import awais.instagrabber.models.BasePostModel;
|
||||||
import awais.instagrabber.models.FeedModel;
|
import awais.instagrabber.models.FeedModel;
|
||||||
import awais.instagrabber.models.PostChild;
|
import awais.instagrabber.models.PostChild;
|
||||||
import awais.instagrabber.models.enums.DownloadMethod;
|
|
||||||
import awais.instagrabber.models.enums.MediaItemType;
|
|
||||||
import awais.instagrabber.workers.DownloadWorker;
|
import awais.instagrabber.workers.DownloadWorker;
|
||||||
import awaisomereport.LogCollector;
|
import awaisomereport.LogCollector;
|
||||||
|
|
||||||
@ -63,96 +58,22 @@ public final class DownloadUtils {
|
|||||||
return lastNotificationId;
|
return lastNotificationId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void batchDownload(@NonNull final Context context,
|
@NonNull
|
||||||
@Nullable String username,
|
private static File getDownloadDir() {
|
||||||
final DownloadMethod method,
|
|
||||||
final List<? extends BasePostModel> itemsToDownload) {
|
|
||||||
if (Utils.settingsHelper == null) Utils.settingsHelper = new SettingsHelper(context);
|
|
||||||
|
|
||||||
if (itemsToDownload == null || itemsToDownload.size() < 1) return;
|
|
||||||
|
|
||||||
if (username != null && username.charAt(0) == '@') username = username.substring(1);
|
|
||||||
|
|
||||||
if (ContextCompat.checkSelfPermission(context, PERMS[0]) == PackageManager.PERMISSION_GRANTED)
|
|
||||||
batchDownloadImpl(context, username, method, itemsToDownload);
|
|
||||||
else if (context instanceof Activity)
|
|
||||||
ActivityCompat.requestPermissions((Activity) context, PERMS, 8020);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void batchDownloadImpl(@NonNull final Context context,
|
|
||||||
@Nullable final String username,
|
|
||||||
final DownloadMethod method,
|
|
||||||
final List<? extends BasePostModel> itemsToDownload) {
|
|
||||||
final File dir = getDownloadDir(context, username);
|
|
||||||
if (dir == null) return;
|
|
||||||
boolean checkEachPost = false;
|
|
||||||
switch (method) {
|
|
||||||
case DOWNLOAD_SAVED:
|
|
||||||
case DOWNLOAD_MAIN:
|
|
||||||
case DOWNLOAD_DISCOVER:
|
|
||||||
checkEachPost = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
final int itemsToDownloadSize = itemsToDownload.size();
|
|
||||||
for (int i = 0; i < itemsToDownloadSize; i++) {
|
|
||||||
final BasePostModel selectedItem = itemsToDownload.get(i);
|
|
||||||
if (!checkEachPost) {
|
|
||||||
final boolean isSlider = itemsToDownloadSize > 1;
|
|
||||||
final File saveFile = getDownloadSaveFile(dir,
|
|
||||||
selectedItem.getShortCode(),
|
|
||||||
isSlider ? "_slide_" + (i + 1) : "",
|
|
||||||
selectedItem.getDisplayUrl()
|
|
||||||
);
|
|
||||||
new DownloadAsync(context,
|
|
||||||
selectedItem.getDisplayUrl(),
|
|
||||||
saveFile,
|
|
||||||
file -> selectedItem.setDownloaded(true))
|
|
||||||
.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
|
||||||
} else {
|
|
||||||
final File finalDir = dir;
|
|
||||||
new PostFetcher(selectedItem.getShortCode(), result -> {
|
|
||||||
if (result == null) return;
|
|
||||||
final boolean isSlider = result.getItemType() == MediaItemType.MEDIA_TYPE_SLIDER;
|
|
||||||
if (isSlider) {
|
|
||||||
for (int j = 0; j < result.getSliderItems().size(); j++) {
|
|
||||||
final PostChild model = result.getSliderItems().get(j);
|
|
||||||
final File saveFile = getDownloadSaveFile(
|
|
||||||
finalDir,
|
|
||||||
model.getShortCode(),
|
|
||||||
"_slide_" + (j + 1),
|
|
||||||
model.getDisplayUrl()
|
|
||||||
);
|
|
||||||
new DownloadAsync(context,
|
|
||||||
model.getDisplayUrl(),
|
|
||||||
saveFile,
|
|
||||||
file -> {}/*model.setDownloaded(true)*/)
|
|
||||||
.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
final File saveFile = getDownloadSaveFile(
|
|
||||||
finalDir,
|
|
||||||
result.getPostId(),
|
|
||||||
result.getDisplayUrl()
|
|
||||||
);
|
|
||||||
new DownloadAsync(context,
|
|
||||||
result.getDisplayUrl(),
|
|
||||||
saveFile,
|
|
||||||
file -> result.setDownloaded(true))
|
|
||||||
.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
|
||||||
}
|
|
||||||
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private static File getDownloadDir(@NonNull final Context context, @Nullable final String username) {
|
|
||||||
File dir = new File(Environment.getExternalStorageDirectory(), "Download");
|
File dir = new File(Environment.getExternalStorageDirectory(), "Download");
|
||||||
|
|
||||||
if (Utils.settingsHelper.getBoolean(FOLDER_SAVE_TO)) {
|
if (Utils.settingsHelper.getBoolean(FOLDER_SAVE_TO)) {
|
||||||
final String customPath = Utils.settingsHelper.getString(FOLDER_PATH);
|
final String customPath = Utils.settingsHelper.getString(FOLDER_PATH);
|
||||||
if (!TextUtils.isEmpty(customPath)) dir = new File(customPath);
|
if (!TextUtils.isEmpty(customPath)) {
|
||||||
|
dir = new File(customPath);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private static File getDownloadDir(@NonNull final Context context, @Nullable final String username) {
|
||||||
|
File dir = getDownloadDir();
|
||||||
|
|
||||||
if (Utils.settingsHelper.getBoolean(Constants.DOWNLOAD_USER_FOLDER) && !TextUtils.isEmpty(username)) {
|
if (Utils.settingsHelper.getBoolean(Constants.DOWNLOAD_USER_FOLDER) && !TextUtils.isEmpty(username)) {
|
||||||
final String finaleUsername = username.startsWith("@") ? username : "@" + username;
|
final String finaleUsername = username.startsWith("@") ? username : "@" + username;
|
||||||
@ -216,6 +137,12 @@ public final class DownloadUtils {
|
|||||||
return new File(finalDir, fileName);
|
return new File(finalDir, fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public static File getTempFile() {
|
||||||
|
final File dir = getDownloadDir();
|
||||||
|
return new File(dir, UUID.randomUUID().toString());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copied from {@link MimeTypeMap#getFileExtensionFromUrl(String)})
|
* Copied from {@link MimeTypeMap#getFileExtensionFromUrl(String)})
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -26,9 +26,12 @@ import androidx.work.WorkerParameters;
|
|||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.JsonSyntaxException;
|
import com.google.gson.JsonSyntaxException;
|
||||||
|
import com.icafe4j.image.meta.Metadata;
|
||||||
|
import com.icafe4j.image.meta.MetadataType;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
@ -45,6 +48,7 @@ import awais.instagrabber.BuildConfig;
|
|||||||
import awais.instagrabber.R;
|
import awais.instagrabber.R;
|
||||||
import awais.instagrabber.services.DeleteImageIntentService;
|
import awais.instagrabber.services.DeleteImageIntentService;
|
||||||
import awais.instagrabber.utils.Constants;
|
import awais.instagrabber.utils.Constants;
|
||||||
|
import awais.instagrabber.utils.DownloadUtils;
|
||||||
import awais.instagrabber.utils.TextUtils;
|
import awais.instagrabber.utils.TextUtils;
|
||||||
import awais.instagrabber.utils.Utils;
|
import awais.instagrabber.utils.Utils;
|
||||||
import awaisomereport.LogCollector;
|
import awaisomereport.LogCollector;
|
||||||
@ -121,7 +125,9 @@ public class DownloadWorker extends Worker {
|
|||||||
final int total,
|
final int total,
|
||||||
final String url,
|
final String url,
|
||||||
final String filePath) {
|
final String filePath) {
|
||||||
final File outFile = new File(filePath);
|
final boolean isJpg = filePath.endsWith("jpg");
|
||||||
|
// using temp file approach to remove IPTC so that download progress can be reported
|
||||||
|
final File outFile = isJpg ? DownloadUtils.getTempFile() : new File(filePath);
|
||||||
try {
|
try {
|
||||||
final URLConnection urlConnection = new URL(url).openConnection();
|
final URLConnection urlConnection = new URL(url).openConnection();
|
||||||
final long fileSize = Build.VERSION.SDK_INT >= 24 ? urlConnection.getContentLengthLong() :
|
final long fileSize = Build.VERSION.SDK_INT >= 24 ? urlConnection.getContentLengthLong() :
|
||||||
@ -131,44 +137,32 @@ public class DownloadWorker extends Worker {
|
|||||||
final FileOutputStream fos = new FileOutputStream(outFile)) {
|
final FileOutputStream fos = new FileOutputStream(outFile)) {
|
||||||
final byte[] buffer = new byte[0x2000];
|
final byte[] buffer = new byte[0x2000];
|
||||||
int count;
|
int count;
|
||||||
boolean deletedIPTC = false;
|
|
||||||
while ((count = bis.read(buffer, 0, 0x2000)) != -1) {
|
while ((count = bis.read(buffer, 0, 0x2000)) != -1) {
|
||||||
totalRead = totalRead + count;
|
totalRead = totalRead + count;
|
||||||
// if (!deletedIPTC) {
|
|
||||||
// int iptcStart = -1;
|
|
||||||
// int fbmdStart = -1;
|
|
||||||
// int fbmdBytesLen = -1;
|
|
||||||
// for (int i = 0; i < buffer.length; ++i) {
|
|
||||||
// if (buffer[i] == (byte) 0xFF && buffer[i + 1] == (byte) 0xED)
|
|
||||||
// iptcStart = i;
|
|
||||||
// else if (buffer[i] == (byte) 'F' && buffer[i + 1] == (byte) 'B'
|
|
||||||
// && buffer[i + 2] == (byte) 'M' && buffer[i + 3] == (byte) 'D') {
|
|
||||||
// fbmdStart = i;
|
|
||||||
// fbmdBytesLen = buffer[i - 10] << 24 | (buffer[i - 9] & 0xFF) << 16 |
|
|
||||||
// (buffer[i - 8] & 0xFF) << 8 | (buffer[i - 7] & 0xFF) |
|
|
||||||
// (buffer[i - 6] & 0xFF);
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if (iptcStart != -1 && fbmdStart != -1 && fbmdBytesLen != -1) {
|
|
||||||
// final int fbmdDataLen = (iptcStart + (fbmdStart - iptcStart) + (fbmdBytesLen - iptcStart)) - 4;
|
|
||||||
// fos.write(buffer, 0, iptcStart);
|
|
||||||
// fos.write(buffer, fbmdDataLen + iptcStart, count - fbmdDataLen - iptcStart);
|
|
||||||
// // setProgressAsync(new Data.Builder().putString(URL, url)
|
|
||||||
// // .putFloat(PROGRESS, totalRead * 100f / fileSize)
|
|
||||||
// // .build());
|
|
||||||
// updateDownloadProgress(notificationId, position, total, totalRead * 100f / fileSize);
|
|
||||||
// deletedIPTC = true;
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
fos.write(buffer, 0, count);
|
fos.write(buffer, 0, count);
|
||||||
// setProgressAsync(new Data.Builder().putString(URL, url)
|
setProgressAsync(new Data.Builder().putString(URL, url)
|
||||||
// .putFloat(PROGRESS, totalRead * 100f / fileSize)
|
.putFloat(PROGRESS, totalRead * 100f / fileSize)
|
||||||
// .build());
|
.build());
|
||||||
updateDownloadProgress(notificationId, position, total, totalRead * 100f / fileSize);
|
updateDownloadProgress(notificationId, position, total, totalRead * 100f / fileSize);
|
||||||
}
|
}
|
||||||
fos.flush();
|
fos.flush();
|
||||||
|
} catch (final Exception e) {
|
||||||
|
Log.e(TAG, "Error while writing data from url: " + url + " to file: " + outFile.getAbsolutePath(), e);
|
||||||
|
}
|
||||||
|
if (isJpg) {
|
||||||
|
final File finalFile = new File(filePath);
|
||||||
|
try (FileInputStream bis = new FileInputStream(outFile);
|
||||||
|
FileOutputStream fos = new FileOutputStream(finalFile)) {
|
||||||
|
Metadata.removeMetadata(bis, fos, MetadataType.IPTC);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Error while removing iptc: url: " + url
|
||||||
|
+ ", tempFile: " + outFile.getAbsolutePath()
|
||||||
|
+ ", finalFile: " + finalFile.getAbsolutePath(), e);
|
||||||
|
}
|
||||||
|
final boolean deleted = outFile.delete();
|
||||||
|
if (!deleted) {
|
||||||
|
Log.w(TAG, "download: tempFile not deleted!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
Log.e(TAG, "Error while downloading: " + url, e);
|
Log.e(TAG, "Error while downloading: " + url, e);
|
||||||
@ -176,23 +170,6 @@ public class DownloadWorker extends Worker {
|
|||||||
updateDownloadProgress(notificationId, position, total, 100);
|
updateDownloadProgress(notificationId, position, total, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
// private void showCompleteNotification(final String url) {
|
|
||||||
// final Context context = getApplicationContext();
|
|
||||||
// final Notification notification = new NotificationCompat.Builder(context, Constants.DOWNLOAD_CHANNEL_ID)
|
|
||||||
// .setCategory(NotificationCompat.CATEGORY_STATUS)
|
|
||||||
// .setSmallIcon(R.drawable.ic_download)
|
|
||||||
// .setAutoCancel(false)
|
|
||||||
// .setOnlyAlertOnce(true)
|
|
||||||
// .setContentTitle(context.getString(R.string.downloader_complete))
|
|
||||||
// .setGroup(DOWNLOAD_GROUP)
|
|
||||||
// .build();
|
|
||||||
// final int id = Math.abs(url.hashCode());
|
|
||||||
// Log.d(TAG, "showCompleteNotification: cancelling: " + id);
|
|
||||||
// notificationManager.cancel(id);
|
|
||||||
// // WorkManager.getInstance(getApplicationContext()).
|
|
||||||
// notificationManager.notify(id + 1, notification);
|
|
||||||
// }
|
|
||||||
|
|
||||||
private void updateDownloadProgress(final int notificationId,
|
private void updateDownloadProgress(final int notificationId,
|
||||||
final int position,
|
final int position,
|
||||||
final int total,
|
final int total,
|
||||||
|
@ -16,6 +16,7 @@ allprojects {
|
|||||||
google()
|
google()
|
||||||
jcenter()
|
jcenter()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
maven { url 'http://maven.geotoolkit.org/' }
|
||||||
maven { url 'https://jitpack.io' }
|
maven { url 'https://jitpack.io' }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user