app/src/main/java/com/bedrock/padder/model/preset/store/Item.java
package com.bedrock.padder.model.preset.store;
import android.animation.Animator;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ShortcutManager;
import android.graphics.BitmapFactory;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.view.View;
import com.afollestad.materialdialogs.DialogAction;
import com.afollestad.materialdialogs.MaterialDialog;
import com.bedrock.padder.R;
import com.bedrock.padder.activity.PresetStoreActivity;
import com.bedrock.padder.adapter.PresetStoreAdapter;
import com.bedrock.padder.helper.ApiHelper;
import com.bedrock.padder.helper.FileHelper;
import com.bedrock.padder.helper.IntentHelper;
import com.bedrock.padder.helper.SoundHelper;
import com.bedrock.padder.model.preferences.Preferences;
import com.bedrock.padder.model.preset.Preset;
import com.bedrock.padder.model.preset.PresetSchema;
import com.daimajia.androidanimations.library.Techniques;
import com.daimajia.androidanimations.library.YoYo;
import com.squareup.picasso.Picasso;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.DecimalFormat;
import java.util.Arrays;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import static com.bedrock.padder.activity.MainActivity.isPresetChanged;
import static com.bedrock.padder.activity.MainActivity.isPresetDownloading;
import static com.bedrock.padder.helper.FileHelper.PRESET_LOCATION;
import static com.bedrock.padder.helper.FileHelper.PROJECT_LOCATION_PRESETS;
import static com.bedrock.padder.helper.WindowHelper.getStringFromId;
/*
* Wrapper class for saving download status
* */
public class Item {
private static final transient String TAG = "Store.Item";
private transient PresetStore presetStore = null;
private transient Activity activity = null;
private transient Preferences preferences = null;
private transient PresetStoreAdapter adapter = null;
private transient FileHelper file = new FileHelper();
private PresetSchema presetSchema;
private PresetStoreAdapter.PresetViewHolder holder;
private Download download = null;
private long bytesTransferred = -1;
private long totalByteCount = -1;
private int index = -1;
public Item(PresetSchema presetSchema, int index) {
this.presetSchema = presetSchema;
this.index = index;
}
public Item(PresetSchema presetSchema) {
// for selected
this.presetSchema = presetSchema;
}
public Preset getPreset() {
return presetSchema.getPreset();
}
public PresetSchema getPresetSchema() {
return presetSchema;
}
public boolean isDownloading() {
return bytesTransferred != -1 && totalByteCount != -1;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
@Override
public boolean equals(Object item) {
try {
return getPresetSchema().equals(((Item) item).getPresetSchema());
} catch (Exception e) {
Log.e(TAG, "equals(), cannot compare with another object");
return false;
}
}
public long getBytesTransferred() {
return bytesTransferred;
}
public void setBytesTransferred(long bytesTransferred) {
this.bytesTransferred = bytesTransferred;
}
public long getTotalByteCount() {
return totalByteCount;
}
public void setTotalByteCount(long totalByteCount) {
this.totalByteCount = totalByteCount;
}
public void clear() {
this.totalByteCount = -1;
this.bytesTransferred = -1;
}
public void load(Context context) {
isPresetChanged = true;
new Preferences(context).setLastPlayed(getPreset().getTag());
}
public void load(int color, int colorDef, Activity activity) {
SoundHelper sound = new SoundHelper();
sound.load(getPreset(), color, colorDef, activity);
}
public void largeLog(String log) {
Log.i(TAG, log.substring(0, 4000));
if (log.substring(4000).length() > 4000) {
largeLog(log.substring(4000));
} else {
Log.i(TAG, log.substring(4000));
}
}
public void download(final Runnable onFinish, final Activity activity) {
// download the preset from presetStore
final Item item = this;
if (isConnected(activity)) {
if (isWifiConnected(activity)) {
download = new Download(item, onFinish, activity);
download.execute();
} else {
// not connected with wifi, show dialog
new MaterialDialog.Builder(activity)
.title(R.string.preset_store_download_data_usage_title)
.content(R.string.preset_store_download_data_usage_text)
.contentColorRes(R.color.dark_secondary)
.positiveText(R.string.proceed_ac)
.positiveColorRes(R.color.colorAccent)
.onPositive(new MaterialDialog.SingleButtonCallback() {
@Override
public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
// download with cellular
download = new Download(item, onFinish, activity);
download.execute();
}
})
.negativeText(R.string.dialog_close)
.negativeColorRes(R.color.dark_secondary)
.onNegative(new MaterialDialog.SingleButtonCallback() {
@Override
public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
dialog.dismiss();
}
})
.neutralText(R.string.preset_store_download_data_usage_neutral)
.neutralColorRes(R.color.dark_secondary)
.onNeutral(new MaterialDialog.SingleButtonCallback() {
@Override
public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
// intent wifi
new IntentHelper().intentWiFiSettings(activity, 0);
}
})
.show();
}
} else {
// no connection dialog
new MaterialDialog.Builder(activity)
.title(R.string.preset_store_download_no_connection_dialog_title)
.content(R.string.preset_store_download_no_connection_dialog_text)
.contentColorRes(R.color.dark_primary)
.neutralText(R.string.dialog_close)
.show();
}
}
public void remove(Runnable onFinish, Activity activity) {
removeLocalPreset(getPreset().getTag(), onFinish, null);
if (isSelected()) {
// reset the savedPreset
isPresetChanged = true;
new Preferences(activity).setLastPlayed(null);
}
}
public void repair(final Runnable onFinish, final Activity activity) {
// remove and download the preset again
removeLocalPreset(getPreset().getTag(), new Runnable() {
@Override
public void run() {
download(onFinish, activity);
}
}, null);
if (isSelected()) {
// reset the savedPreset
isPresetChanged = true;
new Preferences(activity).setLastPlayed(null);
}
}
public void removeLocalPreset(String presetName, Runnable onSuccess, Runnable onFailure) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N_MR1) {
ShortcutManager shortcutManager = activity.getSystemService(ShortcutManager.class);
if (shortcutManager != null) {
shortcutManager.removeDynamicShortcuts(Arrays.asList(presetName));
}
}
if (new FileHelper().deleteRecursive(new File(PROJECT_LOCATION_PRESETS + "/" + presetName))) {
Log.d("remove()", "Successfully removed preset folder");
if (onSuccess != null) {
onSuccess.run();
}
} else {
Log.d("remove()", "Failed to remove preset folder");
if (onFailure != null) {
onFailure.run();
}
}
}
// UI elements
public void init(PresetStoreAdapter.PresetViewHolder vh,
PresetStoreAdapter ad,
PresetStore ps,
Preferences prefs,
Activity a) {
this.holder = vh;
this.adapter = ad;
this.presetStore = ps;
this.preferences = prefs;
this.activity = a;
draw();
}
private void draw() {
final PresetSchema presetSchema = getPresetSchema();
final Preset preset = presetSchema.getPreset();
// load preset image
String imageUrl = PRESET_LOCATION + "/" + preset.getTag() + "/album_art.jpg";
if (download != null && download.isCancelled()) {
Log.i(TAG, "Updated cancelled item");
// doesn't exist, download action
holder.select.setVisibility(View.GONE);
holder.select.setTextColor(preset.getAbout().getColor());
holder.remove.setVisibility(View.GONE);
holder.update.setVisibility(View.GONE);
holder.download.setVisibility(View.VISIBLE);
holder.download.setTextColor(preset.getAbout().getColor());
holder.download.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
download(new Runnable() {
@Override
public void run() {
if (isSelected()) {
presetStore.unselect();
}
adapter.notifyItemChanged(index);
}
}, activity);
}
});
// load url image
Picasso.with(activity)
.load(imageUrl)
.placeholder(R.drawable.ic_image_album_placeholder)
.error(R.drawable.ic_image_album_error)
.into(holder.image);
YoYo.with(Techniques.FadeOut)
.duration(200)
.onStart(new YoYo.AnimatorCallback() {
@Override
public void call(Animator animator) {
holder.actionLayout.setVisibility(View.GONE);
holder.downloadProgressBar.setProgress(0);
holder.downloadPercent.setText("0%");
holder.downloadSize.setText(R.string.preset_store_download_size_downloading);
}
})
.playOn(holder.downloadLayout);
YoYo.with(Techniques.FadeIn)
.delay(200)
.duration(200)
.onStart(new YoYo.AnimatorCallback() {
@Override
public void call(Animator animator) {
holder.actionLayout.setVisibility(View.VISIBLE);
}
})
.playOn(holder.actionLayout);
}
// set gesture
if (preset.isGesture()) {
// preset is gesture
holder.gesture.setVisibility(View.VISIBLE);
holder.gesture.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new MaterialDialog.Builder(activity)
.title(R.string.preset_store_gesture_help_dialog_title)
.content(R.string.preset_store_gesture_help_dialog_text)
.contentColorRes(R.color.dark_primary)
.positiveText(R.string.dialog_close)
.positiveColorRes(R.color.colorAccent)
.show();
}
});
} else {
holder.gesture.setVisibility(View.GONE);
}
// set title
holder.title.setText(preset.getAbout().getSongName());
// set artist name
holder.artist.setText(preset.getAbout().getSongArtist());
// set preset creator
holder.creator.setText(
getStringFromId(R.string.preset_store_preset_by, activity)
+ " "
+ preset.getAbout().getPresetArtist());
// actions
if (isPresetExists(preset.getTag())) {
if (file.isPresetAvailable(preset)) {
// exists, select | remove action
holder.select.setVisibility(View.VISIBLE);
holder.select.setTextColor(preset.getAbout().getColor());
holder.select.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// select and load preset
preset.loadPreset(activity);
presetStore.select(preset.getTag());
adapter.updatePresetStore(presetStore);
}
});
holder.warningLayout.setVisibility(View.GONE);
// load local image
Picasso.with(activity)
.load("file:" + PROJECT_LOCATION_PRESETS + "/" + preset.getTag() + "/about/album_art")
.placeholder(R.drawable.ic_image_album_placeholder)
.error(R.drawable.ic_image_album_error)
.into(holder.image);
// check preset update
onPresetUpdated(presetSchema.getLocalVersion(), preset.getTag(), new Runnable() {
@Override
public void run() {
// preset updated
holder.update.setVisibility(View.VISIBLE);
holder.update.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// re-download the preset
repair(new Runnable() {
@Override
public void run() {
adapter.notifyItemChanged(index);
}
}, activity);
}
});
// show warning
holder.warningLayout.setVisibility(View.VISIBLE);
holder.warning.setText(R.string.preset_store_action_update_available);
}
});
} else {
if (isPresetDownloading) {
int delay = 0;
if (holder.actionLayout.getVisibility() != View.GONE) {
YoYo.with(Techniques.FadeOut)
.duration(200)
.onEnd(new YoYo.AnimatorCallback() {
@Override
public void call(Animator animator) {
holder.actionLayout.setVisibility(View.GONE);
}
})
.playOn(holder.actionLayout);
delay = 200;
}
YoYo.with(Techniques.FadeIn)
.delay(delay)
.duration(200)
.onStart(new YoYo.AnimatorCallback() {
@Override
public void call(Animator animator) {
holder.downloadLayout.setVisibility(View.VISIBLE);
}
})
.playOn(holder.downloadLayout);
// load url image
Picasso.with(activity)
.load(imageUrl)
.placeholder(R.drawable.ic_image_album_placeholder)
.error(R.drawable.ic_image_album_error)
.into(holder.image);
} else {
// corrupted, show repair
holder.select.setVisibility(View.VISIBLE);
holder.select.setTextColor(activity.getResources().getColor(R.color.colorAccent));
holder.select.setText(R.string.preset_store_action_repair);
// show warning
holder.warningLayout.setVisibility(View.VISIBLE);
holder.warning.setText(R.string.preset_store_action_repair_needed);
holder.select.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// show repair dialog
new MaterialDialog.Builder(activity)
.title(R.string.preset_store_action_repair_dialog_title)
.content(R.string.preset_store_action_repair_dialog_text)
.contentColorRes(R.color.dark_primary)
.positiveText(R.string.preset_store_action_repair)
.positiveColorRes(R.color.colorAccent)
.onPositive(new MaterialDialog.SingleButtonCallback() {
@Override
public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
dialog.dismiss();
// repair the preset
repair(new Runnable() {
@Override
public void run() {
adapter.notifyItemChanged(index);
if (isSelected()) {
presetStore.unselect();
}
}
}, activity);
}
})
.negativeText(R.string.dialog_cancel)
.show();
}
});
// load url image
Picasso.with(activity)
.load(imageUrl)
.placeholder(R.drawable.ic_image_album_placeholder)
.error(R.drawable.ic_image_album_error)
.into(holder.image);
}
}
// selected
holder.remove.setVisibility(View.VISIBLE);
holder.remove.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// remove confirm dialog
new MaterialDialog.Builder(activity)
.content(R.string.preset_store_remove_warning_dialog_text)
.contentColorRes(R.color.dark_secondary)
.positiveText(R.string.remove_ac)
.positiveColorRes(R.color.red)
.onPositive(new MaterialDialog.SingleButtonCallback() {
@Override
public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
dialog.dismiss();
// repair the preset
remove(new Runnable() {
@Override
public void run() {
if (adapter.getCallingFragment().equals("installed")) {
adapter.updatePresetStore(presetStore);
}
}
}, activity);
}
})
.negativeText(R.string.dialog_cancel)
.show();
}
});
holder.update.setVisibility(View.GONE);
holder.download.setVisibility(View.GONE);
} else {
// doesn't exist, download action
holder.select.setVisibility(View.GONE);
holder.select.setTextColor(preset.getAbout().getColor());
holder.remove.setVisibility(View.GONE);
holder.update.setVisibility(View.GONE);
holder.download.setVisibility(View.VISIBLE);
holder.download.setTextColor(preset.getAbout().getColor());
holder.download.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
download(new Runnable() {
@Override
public void run() {
if (isSelected()) {
presetStore.unselect();
}
adapter.notifyItemChanged(index);
}
}, activity);
}
});
// load url image
Picasso.with(activity)
.load(imageUrl)
.placeholder(R.drawable.ic_image_album_placeholder)
.error(R.drawable.ic_image_album_error)
.into(holder.image);
}
if (isSelected()) {
// selected: current preset set, downloaded
holder.currentPreset.setVisibility(View.VISIBLE);
holder.select.setVisibility(View.GONE);
} else {
holder.currentPreset.setVisibility(View.GONE);
}
}
private void onPresetUpdated(final Integer version, final String tag, final Runnable onUpdated) {
ApiHelper api = new ApiHelper();
api.getPresetSchema(tag).enqueue(new Callback<PresetSchema>() {
@Override
public void onResponse(Call<PresetSchema> call, Response<PresetSchema> response) {
if (response != null && response.body() != null) {
Log.i(TAG, "Current version : " + response.body().getVersion() + " / Local version : " + version);
if (response.body().getVersion() > version) {
// the version is updated
onUpdated.run();
}
} else {
Log.i(TAG, "Cannot get online version");
}
}
@Override
public void onFailure(Call<PresetSchema> call, Throwable t) {
Log.e(TAG, "Failure getting version of the preset [" + tag + "]");
}
});
}
private boolean isPresetExists(String presetName) {
// preset exist
File folder = new File(PROJECT_LOCATION_PRESETS + "/" + presetName); // folder check
return folder.isDirectory() && folder.exists();
}
private boolean isSelected() {
if (presetStore != null && presetStore.getSelected() != null) {
return presetStore.getSelected().equals(this);
} else {
return false;
}
}
private boolean isConnected(Context context) {
// returns whether the device is connected to the internet
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
return activeNetwork != null && activeNetwork.isConnectedOrConnecting();
}
public boolean isWifiConnected(Context context) {
ConnectivityManager connManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo mWifi = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
return mWifi.isConnected();
}
class Download extends AsyncTask<Void, Boolean, Integer> {
private static final String TAG = "Download";
private Item item;
private Runnable onFinish;
private Activity activity;
private String tag;
private String fileLocation;
private boolean isSpaceDialogVisible = false;
private FileHelper fileHelper = new FileHelper();
private NotificationManager notificationManager;
private NotificationCompat.Builder mBuilder;
private int mNotificationId = 1;
private PendingIntent pendingIntent;
private InputStream input;
private OutputStream output;
private HttpURLConnection connection;
private int mProgress = 0;
private String mProgressText;
private int previousProgressCount = -1;
private String previousProgressText = "";
public Download(Item item, Runnable onFinish, Activity activity) {
this.item = item;
this.onFinish = onFinish;
this.activity = activity;
this.tag = item.getPreset().getTag();
this.fileLocation = PROJECT_LOCATION_PRESETS + "/" + tag + "/preset.zip";
notificationManager = (NotificationManager) activity.getSystemService(Context.NOTIFICATION_SERVICE);
// setup notifications
// from https://stackoverflow.com/questions/44443690/notificationcompat-with-api-26
if (Build.VERSION.SDK_INT >= 26) {
// Android O support notification
NotificationChannel channel = new NotificationChannel(
"tapad-preset-store",
"Preset download",
NotificationManager.IMPORTANCE_LOW
);
channel.setDescription("Show preset downloading progress");
notificationManager.createNotificationChannel(channel);
mBuilder = new NotificationCompat.Builder(activity, "tapad-preset-store");
} else {
mBuilder = new NotificationCompat.Builder(activity).setDefaults(0);
}
Intent presetStoreIntent = new Intent(this.activity, PresetStoreActivity.class);
presetStoreIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
pendingIntent = PendingIntent.getActivity(
this.activity, 0,
presetStoreIntent, PendingIntent.FLAG_UPDATE_CURRENT);
}
void cancel() {
isPresetDownloading = false;
if (item != null) {
item.setBytesTransferred(-1);
item.setTotalByteCount(-1);
// cancelled / failed notification
notificationManager.cancel(mNotificationId);
if (isCancelled()) {
mBuilder.setProgress(0, 0, false)
.setContentText(getStringFromId(R.string.preset_store_download_notification_text_cancelled, activity))
.setSmallIcon(android.R.drawable.stat_sys_download_done)
.setLargeIcon(BitmapFactory.decodeResource(activity.getResources(), android.R.drawable.stat_sys_download_done))
.setOngoing(false)
.setContentIntent(pendingIntent)
.setAutoCancel(true);
} else {
mBuilder.setProgress(0, 0, false)
.setContentText(getStringFromId(R.string.preset_store_download_notification_text_failed, activity))
.setSmallIcon(android.R.drawable.stat_sys_download_done)
.setLargeIcon(BitmapFactory.decodeResource(activity.getResources(), android.R.drawable.stat_sys_download_done))
.setOngoing(false)
.setContentIntent(pendingIntent)
.setAutoCancel(true);
}
notificationManager.notify(mNotificationId, mBuilder.build());
} else {
Log.e(TAG, "Download is not initialized");
}
// remove current preset
remove(new Runnable() {
@Override
public void run() {
// re-init the view
draw();
}
}, activity);
}
@Override
protected void onPreExecute() {
if (isConnected(activity)) {
// create preset project folder
new File(PROJECT_LOCATION_PRESETS + "/" + tag).mkdirs();
// storage available, start download
isPresetDownloading = true;
YoYo.with(Techniques.FadeOut)
.duration(200)
.playOn(holder.actionLayout);
YoYo.with(Techniques.FadeIn)
.delay(200)
.duration(200)
.onStart(new YoYo.AnimatorCallback() {
@Override
public void call(Animator animator) {
holder.downloadLayout.setVisibility(View.VISIBLE);
}
})
.playOn(holder.downloadLayout);
// progressbar initialize
holder.downloadProgressBar.setMax(100);
holder.downloadCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
cancel(true);
}
});
mBuilder.setContentTitle(item.getPreset().getAbout().getTitle())
.setContentText(getStringFromId(R.string.preset_store_download_notification_text_downloading, activity))
.setSmallIcon(android.R.drawable.stat_sys_download)
.setLargeIcon(BitmapFactory.decodeResource(activity.getResources(), android.R.drawable.stat_sys_download))
.setOngoing(true)
.setContentIntent(pendingIntent)
.setOnlyAlertOnce(true);
mBuilder.setDefaults(Notification.DEFAULT_ALL);
notificationManager.notify(mNotificationId, mBuilder.build());
} else {
// no internet connection, cancel the task
cancel(true);
// no connection dialog
new MaterialDialog.Builder(activity)
.title(R.string.preset_store_download_no_connection_dialog_title)
.content(R.string.preset_store_download_no_connection_dialog_text)
.contentColorRes(R.color.dark_primary)
.neutralText(R.string.dialog_close)
.show();
}
}
@Override
protected Integer doInBackground(Void... voids) {
// new http file download
input = null;
output = null;
connection = null;
int count;
try {
URL url = new URL(PRESET_LOCATION + "/" + tag + "/preset.zip");
connection = (HttpURLConnection) url.openConnection();
connection.connect();
Log.i(TAG, "Connecting to " + url.getPath());
// expect HTTP 200 OK, so we don't mistakenly save error report instead of the file
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
Log.e(TAG, "Server returned HTTP " + connection.getResponseCode()
+ " " + connection.getResponseMessage());
connection.disconnect();
// TODO add error dialog
return -1;
} else {
Log.i(TAG, "Server returned HTTP " + connection.getResponseCode()
+ " " + connection.getResponseMessage());
}
item.setTotalByteCount(connection.getContentLength());
String totalByteSize = getReadableFileSize(item.getTotalByteCount());
if (item.getTotalByteCount() > fileHelper.getAvailableExternalMemorySize()) {
// no space left dialog, cancel the task
if (isSpaceDialogVisible == false) {
isSpaceDialogVisible = true;
publishProgress(false);
cancel(true);
}
}
// InputStream with 8k buffer
input = new BufferedInputStream(url.openStream(), 8192);
output = new FileOutputStream(fileLocation);
byte data[] = new byte[1024];
item.setBytesTransferred(0);
while ((count = input.read(data)) != -1) {
if (isCancelled()) {
throw new Exception("cancel");
}
item.setBytesTransferred(item.getBytesTransferred() + count);
if (item.getTotalByteCount() > 0) {
// assign variables
mProgress = (int) (100 * item.getBytesTransferred() / item.getTotalByteCount());
if (item.getBytesTransferred() == 0) {
mProgressText = getStringFromId(R.string.preset_store_download_size_downloading, activity);
} else {
mProgressText = getReadableFileSize(item.getBytesTransferred())
+ "/" + totalByteSize;
}
publishProgress();
}
output.write(data, 0, count);
}
} catch (Exception e) {
Log.e(TAG, e.getMessage());
try {
if (output != null)
output.close();
if (input != null)
input.close();
} catch (IOException e1) {
Log.e(TAG, e1.getMessage());
}
if (connection != null) {
connection.disconnect();
Log.i(TAG, "HttpURLConnection disconnected");
}
if (e.getMessage().equals("cancel")) {
cancel(true);
}
} finally {
try {
if (output != null)
output.close();
if (input != null)
input.close();
} catch (IOException e) {
Log.e(TAG, e.getMessage());
}
}
return (int) (100 * (item.getBytesTransferred() / item.getTotalByteCount()));
}
@Override
protected void onProgressUpdate(Boolean... args) {
// update progress
if (mProgress > previousProgressCount) {
// less updates
previousProgressCount = mProgress;
holder.downloadPercent.setText(String.valueOf(mProgress) + "%");
if (holder.downloadProgressBar.isIndeterminate()) {
holder.downloadProgressBar.setIndeterminate(false);
}
holder.downloadProgressBar.setProgress(mProgress);
if (item.isDownloading()) {
// only notify when it is downloading
mBuilder.setProgress(1000, 10 * mProgress, false);
}
notificationManager.notify(mNotificationId, mBuilder.build());
}
if (!previousProgressText.equals(mProgressText)) {
// less updates
previousProgressText = mProgressText;
holder.downloadSize.setText(mProgressText);
}
if (args.length > 0 && args[0] == false) {
// cancel task
new MaterialDialog.Builder(activity)
.title(R.string.preset_store_download_no_space_dialog_title)
.content(R.string.preset_store_download_no_space_dialog_text)
.contentColorRes(R.color.dark_primary)
.neutralText(R.string.dialog_close)
.dismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
isSpaceDialogVisible = false;
cancel(true);
}
})
.show();
}
}
@Override
protected void onPostExecute(Integer integer) {
if (!isCancelled()) {
// Completed downloading
item.clear();
Log.d(TAG, "Successful download at " + fileLocation);
notificationManager.cancel(mNotificationId);
mBuilder.setContentTitle(item.getPreset().getAbout().getTitle())
.setContentText(getStringFromId(R.string.preset_store_download_notification_text_installing, activity))
.setProgress(0, 0, false)
.setOngoing(true)
.setContentIntent(pendingIntent)
.setOnlyAlertOnce(true);
// downloaded
YoYo.with(Techniques.FadeOut)
.duration(200)
.onEnd(new YoYo.AnimatorCallback() {
@Override
public void call(Animator animator) {
holder.downloadLayout.setVisibility(View.GONE);
}
})
.playOn(holder.downloadLayout);
YoYo.with(Techniques.FadeIn)
.delay(200)
.duration(200)
.onStart(new YoYo.AnimatorCallback() {
@Override
public void call(Animator animator) {
holder.installing.setVisibility(View.VISIBLE);
}
})
.playOn(holder.installing);
fileHelper.unzip(PROJECT_LOCATION_PRESETS + "/" + item.getPreset().getTag() + "/preset.zip",
PROJECT_LOCATION_PRESETS, tag, holder.root, activity,
new Runnable() {
@Override
public void run() {
notificationManager.cancel(mNotificationId);
mBuilder.setContentTitle(item.getPreset().getAbout().getTitle())
.setContentText(getStringFromId(R.string.preset_store_download_notification_text_complete, activity))
.setSmallIcon(android.R.drawable.stat_sys_download_done)
.setLargeIcon(BitmapFactory.decodeResource(activity.getResources(), android.R.drawable.stat_sys_download_done))
.setOngoing(false)
.setContentIntent(pendingIntent)
.setAutoCancel(true);
notificationManager.notify(mNotificationId, mBuilder.build());
onFinish.run();
}
}
);
}
}
@Override
protected void onCancelled(Integer integer) {
cancel();
}
@Override
protected void onCancelled() {
cancel();
}
private String getReadableFileSize(long size) {
if (size <= 0) {
return "0 B";
}
final String[] units = new String[]{"B", "KB", "MB", "GB", "TB"};
int digitGroups = (int) (Math.log10(size) / Math.log10(1024));
return new DecimalFormat("#,##0.0").format(size / Math.pow(1024, digitGroups)) + " " + units[digitGroups];
}
}
}