package com.zulip.android.activities; import android.Manifest; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.ClipData; import android.content.ClipboardManager; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.os.Environment; import android.provider.Settings; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.support.v7.app.NotificationCompat; import android.support.v7.widget.Toolbar; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.Toast; import com.bumptech.glide.Glide; import com.bumptech.glide.load.resource.drawable.GlideDrawable; import com.bumptech.glide.request.RequestListener; import com.bumptech.glide.request.target.GlideDrawableImageViewTarget; import com.bumptech.glide.request.target.Target; import com.zulip.android.R; import com.zulip.android.util.ZLog; 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.MalformedURLException; import java.net.URL; import java.net.URLConnection; public class PhotoViewActivity extends AppCompatActivity implements ActivityCompat.OnRequestPermissionsResultCallback { private static final int EXTERNAL_STORAGE_PERMISSION_CONSTANT = 100; private static final int REQUEST_PERMISSION_SETTING = 101; int id = 1; private ImageView linkImage; private ProgressBar progressBar; private NotificationManager mNotifyManager; private NotificationCompat.Builder mBuilder; private boolean openSettings = false; private SharedPreferences permissionStatus; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_photo_view); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setHomeButtonEnabled(true); permissionStatus = getSharedPreferences("permissionStatus", MODE_PRIVATE); final Intent intent = getIntent(); String url = intent.getStringExtra(Intent.EXTRA_TEXT); getSupportActionBar().setTitle(url); linkImage = (ImageView) findViewById(R.id.linkImageView); progressBar = (ProgressBar) findViewById(R.id.progress); GlideDrawableImageViewTarget imageViewPreview = new GlideDrawableImageViewTarget(linkImage); Glide .with(this) .load(url) .listener(new RequestListener<String, GlideDrawable>() { @Override public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) { progressBar.setVisibility(View.GONE); if (!isNetworkAvailable()) { Toast.makeText(getApplicationContext(), R.string.toast_no_internet_connection, Toast.LENGTH_SHORT).show(); } else { Toast.makeText(getApplicationContext(), R.string.toast_unable_to_load_image, Toast.LENGTH_SHORT).show(); } return false; } @Override public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) { progressBar.setVisibility(View.GONE); return false; } }) .into(imageViewPreview); } private boolean isNetworkAvailable() { ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo(); return activeNetworkInfo != null && activeNetworkInfo.isConnected(); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.photoview_options, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { final Intent intent = getIntent(); final String url = intent.getStringExtra(Intent.EXTRA_TEXT); switch (item.getItemId()) { case R.id.open: Intent i = new Intent(Intent.ACTION_VIEW); i.setData(Uri.parse(url)); startActivity(i); break; case R.id.copy_link: copyLink(url); break; case R.id.download: if (ActivityCompat.checkSelfPermission(PhotoViewActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { allowPermission(); } else { downloadImage(url); } break; default: return super.onOptionsItemSelected(item); } return true; } private void allowPermission() { if (ActivityCompat.shouldShowRequestPermissionRationale(PhotoViewActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { //Information about the permission AlertDialog.Builder builder = new AlertDialog.Builder(PhotoViewActivity.this); builder.setTitle(R.string.permission_title); builder.setMessage(R.string.permission_message); builder.setPositiveButton("Grant", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.cancel(); ActivityCompat.requestPermissions(PhotoViewActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, EXTERNAL_STORAGE_PERMISSION_CONSTANT); } }); builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.cancel(); } }); builder.show(); } else if (permissionStatus.getBoolean(Manifest.permission.WRITE_EXTERNAL_STORAGE, false)) { //Previously Permission Request was cancelled with 'Dont Ask Again', // Now Redirect to Settings after showing Information about permission AlertDialog.Builder builder = new AlertDialog.Builder(PhotoViewActivity.this); builder.setTitle(R.string.permission_title); builder.setMessage(R.string.permission_message); builder.setPositiveButton("Grant", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.cancel(); openSettings = true; Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); Uri uri = Uri.fromParts("package", getPackageName(), null); intent.setData(uri); startActivityForResult(intent, REQUEST_PERMISSION_SETTING); } }); builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.cancel(); } }); builder.show(); } else { ActivityCompat.requestPermissions(PhotoViewActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, EXTERNAL_STORAGE_PERMISSION_CONSTANT); } SharedPreferences.Editor editor = permissionStatus.edit(); editor.putBoolean(Manifest.permission.WRITE_EXTERNAL_STORAGE, true); editor.apply(); } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if (requestCode == EXTERNAL_STORAGE_PERMISSION_CONSTANT) { if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { final Intent intent = getIntent(); final String url = intent.getStringExtra(Intent.EXTRA_TEXT); downloadImage(url); } } else { super.onRequestPermissionsResult(requestCode, permissions, grantResults); } } private void downloadImage(String url) { Toast.makeText(PhotoViewActivity.this, R.string.downloading, Toast.LENGTH_SHORT).show(); mNotifyManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); mBuilder = new NotificationCompat.Builder(PhotoViewActivity.this); mBuilder.setContentTitle(url) .setSmallIcon(android.R.drawable.stat_sys_download); DownloadImage download = new DownloadImage(); download.execute(url); } private void copyLink(String url) { ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); ClipData clip = ClipData.newPlainText("link", url); clipboard.setPrimaryClip(clip); Toast.makeText(PhotoViewActivity.this, R.string.link_copied, Toast.LENGTH_SHORT).show(); } class DownloadImage extends AsyncTask<String, Integer, String> { int calculatedProgress = 0; int imageLength = 0; @Override protected void onPreExecute() { mBuilder.setProgress(100, 0, false); mNotifyManager.notify(id, mBuilder.build()); } @Override protected String doInBackground(String... params) { String path = params[0]; File downloadedImages = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath() + "/" + Uri.parse(path).getLastPathSegment()); int total = 0; int count = 0; try { URL url = new URL(path); URLConnection urlConnection = url.openConnection(); urlConnection.connect(); imageLength = urlConnection.getContentLength(); boolean isFileCreated = downloadedImages.exists(); InputStream inputStream = new BufferedInputStream(url.openStream(), 8192); byte[] data = new byte[1024]; OutputStream outputStream = new FileOutputStream(downloadedImages); if (!isFileCreated) { isFileCreated = downloadedImages.createNewFile(); } while ((count = inputStream.read(data)) != -1) { total = total + count; outputStream.write(data, 0, count); calculatedProgress = (int) total * 100 / imageLength; publishProgress(total); } inputStream.close(); outputStream.close(); } catch (MalformedURLException e) { ZLog.logException(e); } catch (IOException e) { ZLog.logException(e); } return String.valueOf(downloadedImages); } @Override protected void onProgressUpdate(Integer... values) { mBuilder.setProgress(100, values[0], true); mNotifyManager.notify(id, mBuilder.build()); super.onProgressUpdate(values); } @Override protected void onPostExecute(String result) { mBuilder.setContentText("Download complete"); mBuilder.setSmallIcon(android.R.drawable.stat_sys_download_done); mBuilder.setProgress(0, 0, false); Toast.makeText(PhotoViewActivity.this, "Saved at " + result, Toast.LENGTH_LONG).show(); File file = new File(result); Uri uri = Uri.fromFile(file); Intent intent = new Intent(); intent.setAction(android.content.Intent.ACTION_VIEW); intent.setDataAndType(uri, "image/*"); PendingIntent pIntent = PendingIntent.getActivity(PhotoViewActivity.this, 0, intent, 0); mBuilder.setContentIntent(pIntent).build(); mBuilder.setAutoCancel(true); mNotifyManager.notify(id, mBuilder.build()); } } }