package com.github.andlyticsproject;
import android.support.v7.app.AppCompatActivity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.github.andlyticsproject.cache.AppIconInMemoryCache;
import com.github.andlyticsproject.io.ExportService;
import com.github.andlyticsproject.io.StatsCsvReaderWriter;
import com.github.andlyticsproject.model.AppInfo;
import com.github.andlyticsproject.util.DetachableAsyncTask;
import com.github.andlyticsproject.util.Utils;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class ExportActivity extends AppCompatActivity {
private static final String TAG = ExportActivity.class.getSimpleName();
public static final int TAG_IMAGE_REF = R.id.tag_mainlist_image_reference;
public static final String EXTRA_ACCOUNT_NAME = "accountName";
private static final String EXTRA_EXPORT_PACKAGE_NAMES = "exportPackageNames";
private LayoutInflater layoutInflater;
private AppIconInMemoryCache inMemoryCache;
private File cacheDir;
private Drawable spacerIcon;
private ExportListAdapter adapter;
private List<AppInfo> appInfos = new ArrayList<AppInfo>();
private ArrayList<String> exportPackageNames = new ArrayList<String>();
private String accountName;
private LoadExportTask loadTask;
@SuppressWarnings("unchecked")
@Override
public void onCreate(Bundle state) {
super.onCreate(state);
setContentView(R.layout.export_stats);
setProgressBarIndeterminateVisibility(false);
layoutInflater = getLayoutInflater();
accountName = getIntent().getExtras().getString(EXTRA_ACCOUNT_NAME);
getSupportActionBar().setSubtitle(accountName);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
adapter = new ExportListAdapter();
setAppInfos(appInfos);
if (state != null) {
exportPackageNames = (ArrayList<String>) state
.getSerializable(EXTRA_EXPORT_PACKAGE_NAMES);
}
setupView();
this.inMemoryCache = AppIconInMemoryCache.getInstance();
this.cacheDir = getCacheDir();
this.spacerIcon = ContextCompat.getDrawable(this, R.drawable.app_icon_spacer);
if (getLastNonConfigurationInstance() != null) {
loadTask = (LoadExportTask) getLastNonConfigurationInstance();
loadTask.attach(this);
setAppInfos(loadTask.getAppInfos());
} else {
loadTask = new LoadExportTask(this);
Utils.execute(loadTask);
}
}
private void setupView() {
View closeButton = (View) this.findViewById(R.id.export_dialog_close_button);
closeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
final Context context = this;
View exportButton = (View) this.findViewById(R.id.export_dialog_export_button);
exportButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!android.os.Environment.getExternalStorageState().equals(
android.os.Environment.MEDIA_MOUNTED)) {
Toast.makeText(context, context.getString(R.string.export_no_sdcard),
Toast.LENGTH_LONG).show();
return;
}
if (exportPackageNames.isEmpty()) {
Toast.makeText(context, context.getString(R.string.export_no_app),
Toast.LENGTH_LONG).show();
return;
}
String accountName = DeveloperAccountManager.getInstance(ExportActivity.this)
.getSelectedDeveloperAccount().getName();
File exportFile = StatsCsvReaderWriter.getExportFileForAccount(accountName);
if (exportFile.exists()) {
ConfirmExportDialogFragment.newInstance(exportFile.getName()).show(
getFragmentManager(), "confirmExportDialog");
} else {
startExport();
}
}
});
ListView lv = (ListView) this.findViewById(R.id.list_view_id);
lv.addHeaderView(layoutInflater.inflate(R.layout.export_list_header, null));
lv.setAdapter(adapter);
}
@Override
protected void onSaveInstanceState(Bundle state) {
super.onSaveInstanceState(state);
state.putSerializable(EXTRA_EXPORT_PACKAGE_NAMES, exportPackageNames);
}
@Override
public Object onRetainCustomNonConfigurationInstance() {
return loadTask == null ? null : loadTask.detach();
}
String getAccountName() {
return accountName;
}
public static class ConfirmExportDialogFragment extends DialogFragment {
public static final String ARG_FILENAME = "filename";
public static ConfirmExportDialogFragment newInstance(String filename) {
ConfirmExportDialogFragment frag = new ConfirmExportDialogFragment();
Bundle args = new Bundle();
args.putString(ARG_FILENAME, filename);
frag.setArguments(args);
return frag;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final String filename = getArguments().getString(ARG_FILENAME);
return new AlertDialog.Builder(getActivity())
.setIcon(android.R.drawable.ic_dialog_alert)
.setTitle(R.string.export_confirm_dialog_title)
.setMessage(
getResources().getString(R.string.export_confirm_dialog_message,
filename))
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
((ExportActivity) getActivity()).startExport();
}
})
.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dismiss();
}
}).create();
}
}
private static class LoadExportTask extends
DetachableAsyncTask<Void, Void, List<AppInfo>, ExportActivity> {
ContentAdapter db;
List<AppInfo> appInfos = new ArrayList<AppInfo>();
LoadExportTask(ExportActivity parent) {
super(parent);
db = ContentAdapter.getInstance(parent.getApplication());
}
@Override
protected void onPreExecute() {
activity.setProgressBarIndeterminateVisibility(true);
}
@Override
protected List<AppInfo> doInBackground(Void... params) {
if (activity == null) {
return null;
}
try {
appInfos = db.getAllAppsLatestStats(activity.getAccountName());
return appInfos;
} catch (Exception e) {
Log.e(TAG, "Failed to get app stats: " + e.getMessage(), e);
return null;
}
}
@Override
protected void onPostExecute(List<AppInfo> result) {
if (activity == null) {
return;
}
activity.setProgressBarIndeterminateVisibility(false);
if (!activity.isFinishing()) {
if (result != null) {
activity.setAppInfos(result);
} else {
Toast.makeText(activity, R.string.export_failed_to_load_stats,
Toast.LENGTH_LONG).show();
activity.finish();
}
}
}
List<AppInfo> getAppInfos() {
return appInfos;
}
}
class ExportListAdapter extends BaseAdapter {
@Override
public int getCount() {
return getAppInfos().size();
}
@Override
public AppInfo getItem(int position) {
return getAppInfos().get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.export_list_item, null);
holder = new ViewHolder();
holder.name = (TextView) convertView.findViewById(R.id.main_app_name);
holder.packageName = (TextView) convertView.findViewById(R.id.main_package_name);
holder.icon = (ImageView) convertView.findViewById(R.id.main_app_icon);
holder.row = (RelativeLayout) convertView.findViewById(R.id.main_app_row);
holder.checkbox = (CheckBox) convertView.findViewById(R.id.ghost_checkbox);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
final AppInfo appDownloadInfo = getItem(position);
holder.name.setText(appDownloadInfo.getName());
holder.packageName.setText(appDownloadInfo.getPackageName());
final String packageName = appDownloadInfo.getPackageName();
holder.checkbox.setChecked(exportPackageNames.contains(packageName));
final File iconFile = new File(cacheDir + "/" + appDownloadInfo.getIconName());
holder.icon.setTag(TAG_IMAGE_REF, packageName);
if (inMemoryCache.contains(packageName)) {
holder.icon.setImageBitmap(inMemoryCache.get(packageName));
holder.icon.clearAnimation();
} else {
holder.icon.setImageDrawable(null);
holder.icon.clearAnimation();
new GetCachedImageTask(holder.icon, appDownloadInfo.getPackageName())
.execute(new File[] { iconFile });
}
holder.row.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
CheckBox checkbox = ((CheckBox) (((ViewGroup) v)
.findViewById(R.id.ghost_checkbox)));
checkbox.setChecked(!checkbox.isChecked());
if (checkbox.isChecked()) {
exportPackageNames.add(appDownloadInfo.getPackageName());
} else {
exportPackageNames.remove(appDownloadInfo.getPackageName());
}
}
});
holder.checkbox.setTag(packageName);
holder.checkbox.setOnClickListener(new CheckBox.OnClickListener() {
@Override
public void onClick(View v) {
boolean checked = ((CheckBox) v).isChecked();
if (checked) {
exportPackageNames.add(appDownloadInfo.getPackageName());
} else {
exportPackageNames.remove(appDownloadInfo.getPackageName());
}
}
});
return convertView;
}
private class ViewHolder {
public RelativeLayout row;
public TextView name;
public TextView packageName;
public ImageView icon;
public CheckBox checkbox;
}
}
private class GetCachedImageTask extends AsyncTask<File, Void, Bitmap> {
private ImageView imageView;
private String reference;
public GetCachedImageTask(ImageView imageView, String reference) {
this.imageView = imageView;
this.reference = reference;
}
protected void onPostExecute(Bitmap result) {
// only update the image if tag==reference
// (view may have been reused as convertView)
if (imageView.getTag(TAG_IMAGE_REF).equals(reference)) {
if (result == null) {
imageView.setImageDrawable(spacerIcon);
} else {
inMemoryCache.put(reference, result);
updateMainImage(imageView, R.anim.fade_in_fast, result);
}
}
}
@Override
protected Bitmap doInBackground(File... params) {
File iconFile = params[0];
if (iconFile.exists()) {
Bitmap bm = BitmapFactory.decodeFile(iconFile.getAbsolutePath());
return bm;
}
return null;
}
}
public void updateMainImage(ImageView imageView, int animationId, Bitmap result) {
imageView.setImageBitmap(result);
imageView.clearAnimation();
Animation fadeInAnimation = AnimationUtils.loadAnimation(getApplicationContext(),
animationId);
imageView.startAnimation(fadeInAnimation);
}
public void setAppInfos(List<AppInfo> appInfos) {
this.appInfos = appInfos;
if (adapter != null) {
this.adapter.notifyDataSetChanged();
}
}
public List<AppInfo> getAppInfos() {
return appInfos;
}
private void startExport() {
Intent exportIntent = new Intent(this, ExportService.class);
exportIntent.putExtra(ExportService.EXTRA_PACKAGE_NAMES,
exportPackageNames.toArray(new String[exportPackageNames.size()]));
exportIntent.putExtra(ExportService.EXTRA_ACCOUNT_NAME, accountName);
startService(exportIntent);
finish();
}
}