Java tutorial
package com.mikhaellopez.saveinsta.activity; import android.Manifest; import android.animation.ArgbEvaluator; import android.animation.ValueAnimator; import android.content.ActivityNotFoundException; import android.content.ClipData; import android.content.ClipDescription; import android.content.ClipboardManager; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.Color; import android.graphics.drawable.BitmapDrawable; import android.media.MediaPlayer; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.support.design.widget.Snackbar; import android.support.v4.content.ContextCompat; import android.support.v7.app.AlertDialog; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; import android.widget.ImageView; import android.widget.TextView; import android.widget.VideoView; import com.google.gson.Gson; import com.mikhaellopez.saveinsta.BuildConfig; import com.mikhaellopez.saveinsta.R; import com.mikhaellopez.saveinsta.activity.generic.ABaseActivity; import com.mikhaellopez.saveinsta.model.EventChangeDominantColor; import com.mikhaellopez.saveinsta.model.EventInstaPictureLoad; import com.mikhaellopez.saveinsta.model.InstaData; import com.mikhaellopez.saveinsta.model.InstaMedia; import com.mikhaellopez.saveinsta.model.InstaOwner; import com.mikhaellopez.saveinsta.utils.DominantImageColor; import com.mikhaellopez.saveinsta.utils.PermissionsUtils; import com.squareup.picasso.Callback; import com.squareup.picasso.Picasso; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URL; import javax.net.ssl.HttpsURLConnection; import butterknife.Bind; import butterknife.OnClick; import de.greenrobot.event.EventBus; /** * Copyright (C) 2016 Mikhael LOPEZ * Licensed under the Apache License Version 2.0 */ public class MainActivity extends ABaseActivity { @Bind(R.id.toolbar_title) protected TextView mToolbarTitle; @Bind(R.id.coordinator_layout) protected View mCoordinatorLayout; @Bind(R.id.progressBar) protected View mProgressBar; @Bind(R.id.card_view) protected View mCardView; @Bind(R.id.image_to_download) protected ImageView mImageToDownload; @Bind(R.id.icon_profile) protected ImageView mIconProfil; @Bind(R.id.text_user_name) protected TextView mTextUserName; @Bind(R.id.video_to_download) protected VideoView mVideoToDownload; @Bind(R.id.image_action_play) protected View mImageActionPlay; @Bind(R.id.layout_input) protected View mLayoutInput; @Bind(R.id.edit_insta_url) protected EditText editInstaUrl; private MenuItem mMenuItem; private String mUserName; private String mIdInstaContent; private boolean mIsVideo; private String mUrlVideo; private String mCurrentUrlRemove = null; private int mCurrentDominantColor; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mCurrentDominantColor = ContextCompat.getColor(MainActivity.this, R.color.colorPrimary); } @Override protected void onResume() { super.onResume(); // Init View initView(pastClipboard()); } private void initView(String instaUrl) { // Init View mCardView.setVisibility(View.GONE); mLayoutInput.setVisibility(View.GONE); mProgressBar.setVisibility(View.VISIBLE); // Check Insta URL if (instaUrl != null && instaUrl.contains("https://www.instagram.com/p/") && !instaUrl.equals(mCurrentUrlRemove)) { // Load Image loadImageData(instaUrl); } else { // Show Input mProgressBar.setVisibility(View.GONE); mLayoutInput.setVisibility(View.VISIBLE); // Clear Theme Color setThemeColor(mCurrentDominantColor, ContextCompat.getColor(this, R.color.colorPrimary)); } } //region Action Click @OnClick({ R.id.text_user_name, R.id.icon_profile }) protected void onClickUserName() { Uri uri = Uri.parse("http://instagram.com/_u/" + mUserName); Intent likeIng = new Intent(Intent.ACTION_VIEW, uri); likeIng.setPackage("com.instagram.android"); try { startActivity(likeIng); } catch (ActivityNotFoundException e) { startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://instagram.com/" + mUserName))); } } @OnClick(R.id.image_action_close) protected void onClickClose() { // Save URL to remove mCurrentUrlRemove = pastClipboard(); // Init View initView(null); } @OnClick(R.id.image_action_download) protected void onClickDownload() { if (PermissionsUtils.checkAndRequest(this, Manifest.permission.WRITE_EXTERNAL_STORAGE, PermissionsUtils.PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE, getString(R.string.dialog_message_why_permission), null)) { saveInstaContent(); } } @OnClick(R.id.btn_open_insta) protected void onClickOpenInstagram() { // Close Keyboard closeKeyboard(); // Start Instagram App or Open Market String packageName = "com.instagram.android"; Intent intent = getPackageManager().getLaunchIntentForPackage(packageName); if (intent == null) { // Bring user to the market or let them choose an app? intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse("market://details?id=" + packageName)); } intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); try { startActivity(intent); } catch (ActivityNotFoundException e) { Snackbar.make(mCoordinatorLayout, R.string.snackbar_no_instagram, Snackbar.LENGTH_SHORT).show(); } } @OnClick(R.id.btn_load_it) protected void onClickLoadIt() { String editVal = editInstaUrl.getText().toString(); if (editVal != null) { if (editVal.contains("https://www.instagram.com/p/")) { // Clear current Url Remove mCurrentUrlRemove = null; // Clear editText editInstaUrl.setText(null); // Close Keyboard closeKeyboard(); // Init View initView(editVal); } else { // Is Not Insta URL Snackbar.make(mCoordinatorLayout, R.string.snackbar_no_insta_url, Snackbar.LENGTH_SHORT).show(); } } else { // Empty Snackbar.make(mCoordinatorLayout, R.string.snackbar_input_empty, Snackbar.LENGTH_SHORT).show(); } } @OnClick({ R.id.image_action_play, R.id.video_to_download }) protected void onClickPlayVideo() { if (!mVideoToDownload.isPlaying()) { Uri uri = Uri.parse(mUrlVideo); mVideoToDownload.setVideoURI(uri); mVideoToDownload.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { mp.setLooping(true); } }); mVideoToDownload.start(); mVideoToDownload.setVisibility(View.VISIBLE); } else { mVideoToDownload.setVisibility(View.GONE); mVideoToDownload.stopPlayback(); } } //endregion //region Load Image & User information private void loadImageData(final String instaUrl) { new Thread(new Runnable() { @Override public void run() { // Get User and Profil Picture try { URL url = new URL(instaUrl); InputStream is = url.openStream(); int ptr; StringBuffer buffer = new StringBuffer(); while ((ptr = is.read()) != -1) { buffer.append((char) ptr); } String html = buffer.toString(); String startJson = "<script type=\"text/javascript\">window._sharedData = "; String endJson = ";</script>"; String json = html.substring(html.indexOf(startJson) + startJson.length(), html.indexOf(endJson)); InstaData instaData = new Gson().fromJson(json, InstaData.class); InstaMedia instaMedia = instaData.getEntryData().getPostPage().get(0).getMedia(); InstaOwner instaOwner = instaMedia.getOwner(); String userName = instaOwner.getUsername(); String fullName = instaOwner.getFullname(); String urlProfile = instaOwner.getProfilePicUrl(); EventBus.getDefault() .post(new EventInstaPictureLoad(userName, fullName, instaUrl + "media/?size=l", urlProfile, instaMedia.getId(), instaMedia.isVideo(), instaMedia.getVideoUrl())); } catch (Exception ex) { // Send Fail EventBus.getDefault().post(new EventInstaPictureLoad(false)); } } }).start(); } public void onEventMainThread(final EventInstaPictureLoad eventInstaPictureLoad) { if (eventInstaPictureLoad != null && eventInstaPictureLoad.isLoadWell()) { // Save userName and id image mUserName = eventInstaPictureLoad.getUserName(); mIdInstaContent = eventInstaPictureLoad.getIdContent(); // Load User Name to View mTextUserName.setText(eventInstaPictureLoad.getUserFullName()); // If is video, Save URL mVideoToDownload.setVisibility(View.GONE); if (eventInstaPictureLoad.isVideo()) { mIsVideo = true; mUrlVideo = eventInstaPictureLoad.getUrlVideo(); mImageActionPlay.setVisibility(View.VISIBLE); } else { mIsVideo = false; mImageActionPlay.setVisibility(View.GONE); } final Handler handler = new Handler(); new Thread(new Runnable() { @Override public void run() { handler.post(new Runnable() { @Override public void run() { // Load Image to View Picasso.with(MainActivity.this).load(eventInstaPictureLoad.getUrlImage()) .into(mImageToDownload, new Callback() { @Override public void onSuccess() { EventBus.getDefault().post(new EventChangeDominantColor()); // Show Result mProgressBar.setVisibility(View.GONE); mCardView.setVisibility(View.VISIBLE); } @Override public void onError() { } }); // Load Profil Icon to View Picasso.with(MainActivity.this).load(eventInstaPictureLoad.getUrlIconProfil()) .into(mIconProfil); } }); } }).start(); } else { initView(null); // Show erreur Snackbar.make(mCoordinatorLayout, R.string.snackbar_load_photo_failed, Snackbar.LENGTH_SHORT).show(); } } //endregion //region Private Method private String pastClipboard() { String textToPaste = null; ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE); if (clipboard.hasPrimaryClip()) { ClipData clip = clipboard.getPrimaryClip(); if (clip.getDescription().hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)) { textToPaste = clip.getItemAt(0).getText().toString(); } } return textToPaste; } private void saveInstaContent() { if (!mIsVideo) { // Save Picture Bitmap bitmap = ((BitmapDrawable) mImageToDownload.getDrawable()).getBitmap(); if (downloadPicture(bitmap, mIdInstaContent + ".jpg")) { Snackbar.make(mCoordinatorLayout, R.string.snackbar_photo_saved, Snackbar.LENGTH_SHORT).show(); } else { Snackbar.make(mCoordinatorLayout, R.string.snackbar_save_photo_failed, Snackbar.LENGTH_SHORT) .show(); } } else { // Save Video if (mVideoToDownload != null && mVideoToDownload.isPlaying()) { mVideoToDownload.stopPlayback(); mVideoToDownload.setVisibility(View.GONE); } startDownloadVideo(mUrlVideo, mIdInstaContent + ".mp4"); } } private boolean downloadPicture(Bitmap bitmap, String fileName) { boolean result = false; OutputStream output = null; try { File root = new File(Environment.getExternalStorageDirectory() + File.separator + getResources().getString(R.string.app_name) + File.separator); root.mkdirs(); File sdImageMainDirectory = new File(root, fileName); output = new FileOutputStream(sdImageMainDirectory); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, output); output.flush(); result = true; } catch (Exception e) { e.printStackTrace(); } finally { if (null != output) { try { output.close(); } catch (IOException e) { e.printStackTrace(); } } } return result; } private void startDownloadVideo(final String urlVideo, final String fileName) { final Handler handler = new Handler(); new Thread(new Runnable() { @Override public void run() { final boolean isDownload = downloadVideo(urlVideo, fileName); handler.post(new Runnable() { @Override public void run() { if (isDownload) { Snackbar.make(mCoordinatorLayout, R.string.snackbar_video_saved, Snackbar.LENGTH_SHORT) .show(); } else { Snackbar.make(mCoordinatorLayout, R.string.snackbar_save_video_failed, Snackbar.LENGTH_SHORT).show(); } } }); } }).start(); } private boolean downloadVideo(String urlVideo, String fileName) { boolean result = false; OutputStream output = null; InputStream input = null; try { File root = new File(Environment.getExternalStorageDirectory() + File.separator + getResources().getString(R.string.app_name) + File.separator); root.mkdirs(); File sdImageMainDirectory = new File(root, fileName); // Download Video URL url = new URL(urlVideo); HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection(); urlConnection.connect(); input = urlConnection.getInputStream(); output = new FileOutputStream(sdImageMainDirectory); byte[] data = new byte[input.available()]; input.read(data); output.write(data); byte[] buffer = new byte[1024]; int len1; while ((len1 = input.read(buffer)) > 0) { output.write(buffer, 0, len1); } result = true; } catch (Exception e) { e.printStackTrace(); } finally { if (null != output) { try { output.close(); } catch (IOException e) { e.printStackTrace(); } } if (null != input) { try { input.close(); } catch (IOException e) { e.printStackTrace(); } } } return result; } private void closeKeyboard() { // Check if no view has focus: View view = getCurrentFocus(); if (view != null) { InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(view.getWindowToken(), 0); } } //endregion //region Theme & Color public void onEventMainThread(EventChangeDominantColor eventChangeDominantColor) { final Handler handler = new Handler(); new Thread(new Runnable() { @Override public void run() { // Get Dominant Color final int color = getDominantColor(mImageToDownload); if (color != 0) { handler.post(new Runnable() { @Override public void run() { if (mCardView.getVisibility() == View.VISIBLE) { // Set Theme color with Dominant color of Image setThemeColor(mCurrentDominantColor, color); } } }); } else if (BuildConfig.DEBUG) { Log.e(getClass().getName(), "Color Unknown"); } } }).start(); } private int getDominantColor(ImageView imageView) { int color = 0; try { Bitmap bitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap(); String dominantColor = DominantImageColor.getDominantColorOfImage(bitmap); color = Color.parseColor(dominantColor); } catch (Exception ex) { ex.printStackTrace(); } return color; } private void setThemeColor(int colorFrom, final int colorTo) { // Set Toolbar and NavigationBar color ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo); colorAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animator) { mToolbar.setBackgroundColor((int) animator.getAnimatedValue()); } }); colorAnimation.start(); // Set Status Bar color ValueAnimator colorAnimationDark = ValueAnimator.ofObject(new ArgbEvaluator(), darkerColor(colorFrom), darkerColor(colorTo)); colorAnimationDark.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animator) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { getWindow().setStatusBarColor((int) animator.getAnimatedValue()); getWindow().setNavigationBarColor((int) animator.getAnimatedValue()); } } }); colorAnimationDark.start(); // Set Text and icon color int textColorFrom = getTextColorByBackground(colorFrom); int textColorTo = getTextColorByBackground(colorTo); if (textColorFrom != colorTo) { ValueAnimator colorAnimationText = ValueAnimator.ofObject(new ArgbEvaluator(), textColorFrom, textColorTo); colorAnimationText.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animator) { mToolbarTitle.setTextColor((int) animator.getAnimatedValue()); if (mMenuItem != null) { mMenuItem.setIcon(isColorDark(colorTo) ? ContextCompat.getDrawable(MainActivity.this, R.drawable.ic_info) : ContextCompat.getDrawable(MainActivity.this, R.drawable.ic_info_dark)); } } }); colorAnimationText.start(); } mCurrentDominantColor = colorTo; } private int getTextColorByBackground(int backgroundColor) { int textColor; if (isColorDark(backgroundColor)) { textColor = ContextCompat.getColor(this, android.R.color.white); } else { textColor = ContextCompat.getColor(this, R.color.colorAccent); } return textColor; } private int darkerColor(int color) { float[] hsv = new float[3]; Color.colorToHSV(color, hsv); hsv[2] *= 0.8f; // value component return Color.HSVToColor(hsv); } public boolean isColorDark(int color) { double darkness = 1 - (0.299 * Color.red(color) + 0.587 * Color.green(color) + 0.114 * Color.blue(color)) / 255; if (darkness < 0.5) { return false; // It's a light color } else { return true; // It's a dark color } } //endregion //region Menu Implememtatiom @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_main, menu); mMenuItem = menu.getItem(0); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.action_info: // Show Dialog Information final AlertDialog dialog = new AlertDialog.Builder(this) .setIcon(ContextCompat.getDrawable(this, R.mipmap.ic_launcher)) .setTitle(getResources().getString(R.string.app_name)) .setMessage(getResources().getString(R.string.info_message)).setCancelable(false) .setNeutralButton(getString(R.string.dialog_button_rate_app), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { try { startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + getPackageName()))); } catch (ActivityNotFoundException e) { Snackbar.make(mCoordinatorLayout, R.string.snackbar_no_market, Snackbar.LENGTH_SHORT).show(); } } }) .setPositiveButton(getResources().getString(android.R.string.ok), null).create(); dialog.setOnShowListener(new DialogInterface.OnShowListener() { @Override public void onShow(DialogInterface arg0) { dialog.getButton(AlertDialog.BUTTON_NEUTRAL) .setTextColor(ContextCompat.getColor(MainActivity.this, R.color.colorAccent)); dialog.getButton(AlertDialog.BUTTON_POSITIVE) .setTextColor(ContextCompat.getColor(MainActivity.this, R.color.colorAccent)); } }); dialog.show(); break; } return super.onOptionsItemSelected(item); } //endregion //region Permission @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); switch (requestCode) { case PermissionsUtils.PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE: // If request is cancelled, the result arrays are empty. if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // permission was granted saveInstaContent(); } break; } } //endregion }