package de.robv.android.xposed.installer.widget;
import android.Manifest;
import android.app.DownloadManager;
import android.app.Fragment;
import android.content.Context;
import android.content.pm.PackageManager;
import android.support.v13.app.FragmentCompat;
import android.support.v4.app.ActivityCompat;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import de.robv.android.xposed.installer.R;
import de.robv.android.xposed.installer.util.DownloadsUtil;
import de.robv.android.xposed.installer.util.DownloadsUtil.DownloadFinishedCallback;
import de.robv.android.xposed.installer.util.DownloadsUtil.DownloadInfo;
import static de.robv.android.xposed.installer.XposedApp.WRITE_EXTERNAL_PERMISSION;
public class DownloadView extends LinearLayout {
public static String mClickedUrl;
private final Button btnDownload;
private final Button btnDownloadCancel;
private final Button btnInstall;
private final Button btnSave;
private final ProgressBar progressBar;
private final TextView txtInfo;
public Fragment fragment;
private DownloadInfo mInfo = null;
private String mUrl = null;
private final Runnable refreshViewRunnable = new Runnable() {
@Override
public void run() {
if (mUrl == null) {
btnDownload.setVisibility(View.GONE);
btnSave.setVisibility(View.GONE);
btnDownloadCancel.setVisibility(View.GONE);
btnInstall.setVisibility(View.GONE);
progressBar.setVisibility(View.GONE);
txtInfo.setVisibility(View.VISIBLE);
txtInfo.setText(R.string.download_view_no_url);
} else if (mInfo == null) {
btnDownload.setVisibility(View.VISIBLE);
btnSave.setVisibility(View.VISIBLE);
btnDownloadCancel.setVisibility(View.GONE);
btnInstall.setVisibility(View.GONE);
progressBar.setVisibility(View.GONE);
txtInfo.setVisibility(View.GONE);
} else {
switch (mInfo.status) {
case DownloadManager.STATUS_PENDING:
case DownloadManager.STATUS_PAUSED:
case DownloadManager.STATUS_RUNNING:
btnDownload.setVisibility(View.GONE);
btnSave.setVisibility(View.GONE);
btnDownloadCancel.setVisibility(View.VISIBLE);
btnInstall.setVisibility(View.GONE);
progressBar.setVisibility(View.VISIBLE);
txtInfo.setVisibility(View.VISIBLE);
if (mInfo.totalSize <= 0 || mInfo.status != DownloadManager.STATUS_RUNNING) {
progressBar.setIndeterminate(true);
txtInfo.setText(R.string.download_view_waiting);
} else {
progressBar.setIndeterminate(false);
progressBar.setMax(mInfo.totalSize);
progressBar.setProgress(mInfo.bytesDownloaded);
txtInfo.setText(getContext().getString(
R.string.download_view_running,
mInfo.bytesDownloaded / 1024,
mInfo.totalSize / 1024));
}
break;
case DownloadManager.STATUS_FAILED:
btnDownload.setVisibility(View.VISIBLE);
btnSave.setVisibility(View.VISIBLE);
btnDownloadCancel.setVisibility(View.GONE);
btnInstall.setVisibility(View.GONE);
progressBar.setVisibility(View.GONE);
txtInfo.setVisibility(View.VISIBLE);
txtInfo.setText(getContext().getString(
R.string.download_view_failed, mInfo.reason));
break;
case DownloadManager.STATUS_SUCCESSFUL:
btnDownload.setVisibility(View.GONE);
btnSave.setVisibility(View.GONE);
btnDownloadCancel.setVisibility(View.GONE);
btnInstall.setVisibility(View.VISIBLE);
progressBar.setVisibility(View.GONE);
txtInfo.setVisibility(View.VISIBLE);
txtInfo.setText(R.string.download_view_successful);
break;
}
}
// TODO maybe enable again after checking the implementation
btnSave.setVisibility(View.GONE);
}
};
private String mTitle = null;
private DownloadFinishedCallback mCallback = null;
public DownloadView(Context context, final AttributeSet attrs) {
super(context, attrs);
setFocusable(false);
setOrientation(LinearLayout.VERTICAL);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.download_view, this, true);
btnDownload = (Button) findViewById(R.id.btnDownload);
btnDownloadCancel = (Button) findViewById(R.id.btnDownloadCancel);
btnInstall = (Button) findViewById(R.id.btnInstall);
btnSave = (Button) findViewById(R.id.save);
btnDownload.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mInfo = DownloadsUtil.add(getContext(), mTitle, mUrl, mCallback, DownloadsUtil.MIME_TYPES.APK);
refreshViewFromUiThread();
if (mInfo != null)
new DownloadMonitor().start();
}
});
btnSave.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mClickedUrl = mUrl;
if (checkPermissions()) return;
DownloadsUtil.add(getContext(), mTitle, mUrl,
new DownloadFinishedCallback() {
@Override
public void onDownloadFinished(Context context, DownloadInfo info) {
Toast.makeText(context, context.getString(R.string.module_saved,
info.localFilename), Toast.LENGTH_SHORT).show();
}
}, DownloadsUtil.MIME_TYPES.APK, true, true);
}
});
btnDownloadCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mInfo == null)
return;
DownloadsUtil.removeById(getContext(), mInfo.id);
// UI update will happen automatically by the DownloadMonitor
}
});
btnInstall.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mCallback == null)
return;
mCallback.onDownloadFinished(getContext(), mInfo);
}
});
progressBar = (ProgressBar) findViewById(R.id.progress);
txtInfo = (TextView) findViewById(R.id.txtInfo);
refreshViewFromUiThread();
}
private boolean checkPermissions() {
if (ActivityCompat.checkSelfPermission(this.getContext(),
Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
FragmentCompat.requestPermissions(fragment, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, WRITE_EXTERNAL_PERMISSION);
return true;
}
return false;
}
private void refreshViewFromUiThread() {
refreshViewRunnable.run();
}
private void refreshView() {
post(refreshViewRunnable);
}
public String getUrl() {
return mUrl;
}
public void setUrl(String url) {
mUrl = url;
if (mUrl != null)
mInfo = DownloadsUtil.getLatestForUrl(getContext(), mUrl);
else
mInfo = null;
refreshView();
}
public String getTitle() {
return mTitle;
}
public void setTitle(String title) {
this.mTitle = title;
}
public DownloadFinishedCallback getDownloadFinishedCallback() {
return mCallback;
}
public void setDownloadFinishedCallback(DownloadFinishedCallback downloadFinishedCallback) {
this.mCallback = downloadFinishedCallback;
}
private class DownloadMonitor extends Thread {
public DownloadMonitor() {
super("DownloadMonitor");
}
@Override
public void run() {
while (true) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
return;
}
try {
mInfo = DownloadsUtil.getById(getContext(), mInfo.id);
} catch (NullPointerException ignored) {
}
refreshView();
if (mInfo == null)
return;
if (mInfo.status != DownloadManager.STATUS_PENDING
&& mInfo.status != DownloadManager.STATUS_PAUSED
&& mInfo.status != DownloadManager.STATUS_RUNNING)
return;
}
}
}
}