Java tutorial
/* Copyright 2014-2016 Alan G. Downie Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package uk.org.downiesoft.slideshow; import android.Manifest; import android.app.Activity; import android.app.AlertDialog; import android.app.FragmentManager; import android.app.FragmentTransaction; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.preference.PreferenceManager; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; import android.util.Log; import android.view.GestureDetector; import android.view.GestureDetector.SimpleOnGestureListener; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.RelativeLayout; import android.widget.Toast; import java.util.ArrayList; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import android.view.Window; import android.view.WindowManager; public class SlideShowActivity extends Activity { public static final String TAG = SlideShowActivity.class.getName(); public static final String ACTION_STOP_WALLPAPER = TAG + ".stopWallpaper"; public static final int REQUEST_BROWSER = 1024; public static final int REQUEST_FAVOURITES = 1025; public static final int REQUEST_SLIDESHOW = 1026; private static final int PERMISSION_ACCESS_EXTERNAL_STORAGE = 1; public static final Executor THREAD_POOL_EXECUTOR = Executors.newCachedThreadPool(); public static int sDebug; private SharedPreferences mSlideshowSettings; private ThumbnailCacheManager mCacheManager; private GridViewFragment mGridViewFragment; private PreviewFragment mPreviewFragment; private ImageView mPreviewButton; private GestureDetector mGestureDetector; private FrameLayout mPreviewView; private boolean mPreviewVisible; /** UIHider to manage immersive view changes. */ private UiHider mUiHider; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Window win = getWindow(); win.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); win.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); win.requestFeature(Window.FEATURE_ACTION_BAR_OVERLAY); mUiHider = new UiHider(this); getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(mUiHider); mCacheManager = ThumbnailCacheManager.getInstance(this); SlideShowActivity.debug(1, TAG, "onCreate: %s", savedInstanceState == null ? "null" : savedInstanceState.toString()); setContentView(R.layout.activity_slide_show); PreferenceManager.setDefaultValues(this, R.xml.view_preferences, false); PreferenceManager.setDefaultValues(this, R.xml.slideshow_preferences, false); PreferenceManager.setDefaultValues(this, R.xml.cache_preferences, false); PreferenceManager.setDefaultValues(this, R.xml.wallpaper_preferences, false); PreferenceManager.setDefaultValues(this, R.xml.other_preferences, false); mSlideshowSettings = PreferenceManager.getDefaultSharedPreferences(this); int thumbSize = Integer.parseInt(mSlideshowSettings.getString(getString(R.string.PREFS_THUMBSIZE), "1")); // Hack to convert old hard-coded thumbsize settings to platform dependent sizes if (thumbSize > 2) { thumbSize = thumbSize / 90; SharedPreferences.Editor editor = mSlideshowSettings.edit(); editor.putString(getString(R.string.PREFS_THUMBSIZE), Integer.toString(thumbSize)); editor.apply(); } FragmentManager fm = getFragmentManager(); int cacheLimit = Integer .parseInt(mSlideshowSettings.getString(getString(R.string.PREFS_CACHE_LIMIT), "10")); mPreviewButton = (ImageView) findViewById(R.id.slideShowImageButton); mPreviewView = (FrameLayout) findViewById(R.id.previewContainer); RelativeLayout divider = (RelativeLayout) findViewById(R.id.frameDivider); if (divider != null) { divider.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View view, MotionEvent event) { return mGestureDetector.onTouchEvent(event) || view.onTouchEvent(event); } }); } mPreviewFragment = (PreviewFragment) fm.findFragmentByTag(PreviewFragment.TAG); if (mPreviewView != null && mPreviewFragment == null) { mPreviewFragment = new PreviewFragment(); fm.beginTransaction().replace(R.id.previewContainer, mPreviewFragment, PreviewFragment.TAG).commit(); } mGridViewFragment = (GridViewFragment) fm.findFragmentByTag(GridViewFragment.TAG); if (mGridViewFragment == null) { mGridViewFragment = new GridViewFragment(); FragmentTransaction ft = fm.beginTransaction(); ft.replace(R.id.fragmentContainer, mGridViewFragment, GridViewFragment.TAG); ft.commit(); } mGestureDetector = new GestureDetector(this, new DividerGestureListener()); // restart/stop service as required Intent intent = getIntent(); if (intent != null && intent.getAction() != null && intent.getAction().equals(ACTION_STOP_WALLPAPER) && isServiceRunning()) { stopWallpaperService(); finish(); } else { if (!mSlideshowSettings.getBoolean(getString(R.string.PREFS_WALLPAPER_ENABLE), false)) { if (isServiceRunning()) { stopWallpaperService(); } } else { if (!isServiceRunning()) { Intent startIntent = new Intent(SlideShowActivity.this, WallpaperService.class); startService(startIntent); invalidateOptionsMenu(); } } } mCacheManager.tidyCache(cacheLimit); BitmapManager.setDisplayMetrics(getResources().getDisplayMetrics()); } @Override public void onNewIntent(Intent intent) { if (intent != null && intent.getAction() != null && intent.getAction().equals(ACTION_STOP_WALLPAPER) && isServiceRunning()) { BitmapManager.setWallpaper(this, null); stopWallpaperService(); } } @Override public void onStart() { SlideShowActivity.debug(1, TAG, "onStart"); super.onStart(); } @Override protected void onResume() { super.onResume(); mPreviewVisible = mSlideshowSettings.getBoolean(getString(R.string.PREFS_SHOW_PREVIEW), true); sDebug = Integer.parseInt(mSlideshowSettings.getString(getString(R.string.PREFS_DEBUG_LEVEL), "0")); showPreview(mPreviewVisible); mUiHider.showUi(true); } @Override protected void onPostResume() { super.onPostResume(); String[] permissions = new String[] { Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE }; ArrayList<String> notGranted = new ArrayList<>(2); for (String p : permissions) { if (ContextCompat.checkSelfPermission(this, p) != PackageManager.PERMISSION_GRANTED) { notGranted.add(p); } } if (notGranted.size() > 0) { final String[] required = notGranted.toArray(permissions); boolean explain = false; for (String r : required) { explain |= ActivityCompat.shouldShowRequestPermissionRationale(this, r); } if (explain) { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("Access External Storage"); builder.setMessage("Needed to access photo albums and favourite lists on SD card"); builder.setPositiveButton(R.string.text_ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { ActivityCompat.requestPermissions(SlideShowActivity.this, required, PERMISSION_ACCESS_EXTERNAL_STORAGE); } }); } else { ActivityCompat.requestPermissions(SlideShowActivity.this, required, PERMISSION_ACCESS_EXTERNAL_STORAGE); } } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) { switch (requestCode) { case PERMISSION_ACCESS_EXTERNAL_STORAGE: { if (grantResults.length < 0) { boolean granted = true; for (int result : grantResults) { granted &= result != PackageManager.PERMISSION_GRANTED; } if (!granted) { Toast.makeText(this, R.string.text_exit_app, Toast.LENGTH_LONG).show(); finish(); } } } } } @Override public void onStop() { SlideShowActivity.debug(1, TAG, "onStop"); super.onStop(); } @Override public void onDestroy() { SlideShowActivity.debug(1, TAG, "onDestroy"); super.onDestroy(); if (mCacheManager != null) { mCacheManager.close(); } } @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); getMenuInflater().inflate(R.menu.slideshow_menu, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.action_settings: { Intent intent = new Intent(this, SettingsActivity.class); this.startActivity(intent); return true; } case R.id.action_clear_wallpaper: BitmapManager.setWallpaper(this, null); Toast.makeText(this, R.string.text_wallpaper_cleared, Toast.LENGTH_SHORT).show(); if (isServiceRunning()) { stopWallpaperService(); } return true; } return super.onOptionsItemSelected(item); } @Override public void onBackPressed() { debug(1, TAG, "onBackPressed"); mUiHider.showUi(true); if (mGridViewFragment != null) { if (mGridViewFragment.offerBackKeyEvent()) { return; } } invalidateOptionsMenu(); if (mSlideshowSettings.getBoolean(getString(R.string.PREFS_WALLPAPER_CLEAR_ON_EXIT), true)) { if (isServiceRunning()) { stopWallpaperService(); } } super.onBackPressed(); } public void showPreview(boolean aIsVisible) { if (mPreviewFragment != null) { mPreviewFragment.addGlobalLayoutListener(); Drawable button; if (aIsVisible) { mPreviewView.setVisibility(View.VISIBLE); button = ContextCompat.getDrawable(this, R.drawable.ic_action_collapse); } else { mPreviewView.setVisibility(View.GONE); button = ContextCompat.getDrawable(this, R.drawable.ic_action_expand); } if (button != null && mPreviewButton != null) { mPreviewButton.setImageDrawable(button); } mPreviewView.requestLayout(); if (mGridViewFragment != null) { mGridViewFragment.setGridChoiceMode(); } SharedPreferences.Editor editor = mSlideshowSettings.edit(); editor.putBoolean(getString(R.string.PREFS_SHOW_PREVIEW), aIsVisible); editor.apply(); } } public boolean isServiceRunning() { return WallpaperService.isServiceRunning(this); } public void stopWallpaperService() { if (isServiceRunning()) { WallpaperService.stopWallpaperService(this); invalidateOptionsMenu(); Toast.makeText(this, R.string.text_service_stopped, Toast.LENGTH_SHORT).show(); } finish(); } /** * Gesture listener to handle fling and tap gestures on the divider bar between preview and grid views */ private class DividerGestureListener extends SimpleOnGestureListener { @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { float dx = e2.getX() - e1.getX(); float dy = e2.getY() - e1.getY(); int orientation = getResources().getConfiguration().orientation; switch (orientation) { case Configuration.ORIENTATION_LANDSCAPE: if (Math.abs(dx) > 2 * Math.abs(dy)) { if (mPreviewVisible && dx < 0 || !mPreviewVisible && dx > 0) { showPreview(mPreviewVisible = !mPreviewVisible); } return true; } return false; case Configuration.ORIENTATION_PORTRAIT: if (Math.abs(dy) > 2 * Math.abs(dx)) { if (mPreviewVisible && dy < 0 || !mPreviewVisible && dy > 0) { showPreview(mPreviewVisible = !mPreviewVisible); } return true; } return false; default: return false; } } @Override public boolean onSingleTapConfirmed(MotionEvent e) { showPreview(mPreviewVisible = !mPreviewVisible); return true; } } public static void debug(int aLevel, String tag, String format, Object... params) { if (aLevel <= sDebug) { Log.d(tag, String.format(format, params)); } } }