Java tutorial
/* Copyright (c) 2013 Richard G. Todd. * Licensed under the terms of the GNU General Public License (GPL) Version 3.0. */ package com.richtodd.android.quiltdesign.app; import java.io.BufferedInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.text.DateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import org.json.JSONException; import org.json.JSONObject; import android.app.ActionBar; import android.app.ActionBar.Tab; import android.app.ActionBar.TabListener; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.app.FragmentManager; import android.app.FragmentTransaction; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.preference.PreferenceManager; import android.support.v4.view.ViewPager; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.ProgressBar; import android.widget.Toast; import com.richtodd.android.quiltdesign.block.JSONRepository; import com.richtodd.android.quiltdesign.block.QuiltDesignThumbnailProvider; import com.richtodd.android.quiltdesign.block.Repository; import com.richtodd.android.quiltdesign.block.Repository.MergeModes; import com.richtodd.android.repository.JSONUtility; import com.richtodd.android.repository.RepositoryException; public class MainActivity extends Activity implements RefreshListSource, AsyncTaskListener { // // Fields // private static final DateFormat s_dateFormat = DateFormat.getDateTimeInstance(); private static AsyncTask<?, ?, ?> s_sampleLoaderTask; private ActionBar m_actionBar; private HomeCollectionPagerAdapter m_pagerAdapter; private ViewPager m_viewPager; private List<RefreshListListener> m_refreshListListeners = new ArrayList<RefreshListListener>(); // // Overrides // @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); PreferenceManager.setDefaultValues(this, R.xml.application_preferences, false); PreferenceManager.setDefaultValues(this, R.xml.block_preferences, false); PreferenceManager.setDefaultValues(this, R.xml.quilt_preferences, false); setContentView(R.layout.activity_main); FragmentManager fm = getFragmentManager(); m_pagerAdapter = new HomeCollectionPagerAdapter(fm); m_viewPager = (ViewPager) findViewById(R.id.viewPager); m_viewPager.setAdapter(m_pagerAdapter); m_viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageSelected(int position) { getActionBar().setSelectedNavigationItem(position); } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageScrollStateChanged(int state) { } }); m_actionBar = getActionBar(); m_actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); ActionBar.TabListener actionBarTabListener = new TabListener() { @Override public void onTabReselected(Tab tab, FragmentTransaction ft) { } @Override public void onTabSelected(Tab tab, FragmentTransaction ft) { m_viewPager.setCurrentItem(tab.getPosition()); } @Override public void onTabUnselected(Tab tab, FragmentTransaction ft) { } }; m_actionBar.addTab(m_actionBar.newTab().setText("Blocks").setTabListener(actionBarTabListener)); m_actionBar.addTab(m_actionBar.newTab().setText("Quilts").setTabListener(actionBarTabListener)); m_actionBar.addTab(m_actionBar.newTab().setText("Themes").setTabListener(actionBarTabListener)); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.options_activity_main, menu); return true; } @Override protected void onStart() { super.onStart(); try { if (Repository.getDefaultRepository(this).isEmpty() && !hasSampleLoaderTask()) { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage("Would you like to add some sample blocks and quilts?") .setPositiveButton("Yes", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int id) { SampleLoaderTask task = new SampleLoaderTask(); setSampleLoaderTask(task); task.execute(MainActivity.this); } }).setNegativeButton("No", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int id) { // No action required. } }); Dialog dialog = builder.create(); dialog.show(); } } catch (RepositoryException e) { Handle.asRuntimeError(e); } } @Override protected void onResume() { super.onResume(); SampleLoaderTask.registerListener(this); verifySampleLoaderTask(); } @Override protected void onPause() { super.onPause(); SampleLoaderTask.unregisterListener(this); } @Override public boolean onOptionsItemSelected(MenuItem item) { int itemId = item.getItemId(); switch (itemId) { case R.id.menu_settings: { Intent intent = new Intent(this, MainPreferenceActivity.class); startActivity(intent); return true; } case R.id.menu_about: { TextDialogFragment dialog = TextDialogFragment.create("About Quilt Design", getString(R.string.about), "Close"); dialog.show(getFragmentManager(), null); return true; } case R.id.menu_help: { // Intent intent = new Intent(this, BrowserActivity.class); // intent.putExtra(BrowserActivity.ARG_URL, // "http://quiltdesign.richtodd.com"); Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://quiltdesign.richtodd.com")); startActivity(intent); return true; } case R.id.menu_backup: { Uri uriFile; try { uriFile = saveRepository(); Intent intent = new Intent(Intent.ACTION_SEND); intent.putExtra(Intent.EXTRA_STREAM, uriFile); intent.setType("application/vnd.richtodd.quiltdesign"); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); startActivity(Intent.createChooser(intent, "Backup")); } catch (RepositoryException e) { Handle.asRuntimeError(e); } return true; } case R.id.menu_loadSamples: { SampleLoaderTask task = new SampleLoaderTask(); setSampleLoaderTask(task); task.execute(this); return true; } } return super.onOptionsItemSelected(item); } @Override public void addListener(RefreshListListener listener) { m_refreshListListeners.add(listener); } @Override public void removeListener(RefreshListListener listener) { m_refreshListListeners.remove(listener); } @Override public void onPostExecute(AsyncTask<?, ?, ?> task, String result) { clearSampleLoaderTask(task); try { refreshLists(); } catch (RepositoryException e) { Handle.asRuntimeError(e); } Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT).show(); } @Override public void onCancelled(AsyncTask<?, ?, ?> task, String result) { clearSampleLoaderTask(task); } synchronized void setSampleLoaderTask(AsyncTask<?, ?, ?> task) { if (s_sampleLoaderTask != null) { throw new IllegalStateException("Sample loader task already in progress."); } s_sampleLoaderTask = task; ProgressBar progressBar = (ProgressBar) findViewById(R.id.progressBar); progressBar.setVisibility(View.VISIBLE); } synchronized void clearSampleLoaderTask(AsyncTask<?, ?, ?> task) { if (s_sampleLoaderTask != task) { throw new IllegalStateException("Sample loader task not in progress."); } s_sampleLoaderTask = null; ProgressBar progressBar = (ProgressBar) findViewById(R.id.progressBar); progressBar.setVisibility(View.GONE); } synchronized boolean hasSampleLoaderTask() { return s_sampleLoaderTask != null; } synchronized void verifySampleLoaderTask() { ProgressBar progressBar = (ProgressBar) findViewById(R.id.progressBar); if (s_sampleLoaderTask == null) { progressBar.setVisibility(View.GONE); } else { progressBar.setVisibility(View.VISIBLE); } } // // Private Methods // private Uri saveRepository() throws RepositoryException { Repository repository = Repository.getDefaultRepository(this); JSONObject targetJsonRepository = new JSONObject(); JSONRepository targetRepository = new JSONRepository(targetJsonRepository, null); targetRepository.merge(repository, MergeModes.New); String name = "Quilt Design Backup - " + s_dateFormat.format(new Date()) + ".quiltdesign"; File file; try { file = new File(StorageUtility.getPublicFolder(), name); } catch (IOException e) { throw new RepositoryException(e); } JSONUtility.saveJSONObject(file, targetJsonRepository); Uri uri = Uri.fromFile(file); return uri; } private void refreshLists() throws RepositoryException { for (RefreshListListener listener : m_refreshListListeners) { listener.refreshList(); } } private static class SampleLoaderTask extends AsyncTask<Context, Void, String> { private static Object s_syncRoot = new Object(); private static List<AsyncTaskListener> s_listeners = new ArrayList<AsyncTaskListener>(); synchronized static void registerListener(AsyncTaskListener listener) { s_listeners.add(listener); } synchronized static void unregisterListener(AsyncTaskListener listener) { s_listeners.remove(listener); } synchronized static void raiseOnPostExecute(AsyncTask<?, ?, ?> task, String result) { for (AsyncTaskListener listener : s_listeners) { listener.onPostExecute(task, result); } } synchronized static void raiseOnCancelled(AsyncTask<?, ?, ?> task, String result) { for (AsyncTaskListener listener : s_listeners) { listener.onCancelled(task, result); } } @Override protected String doInBackground(Context... params) { Context context = params[0]; try { String json = loadSampleJSON(context); if (json != null) { synchronized (s_syncRoot) { Repository sampleRepository = new JSONRepository(new JSONObject(json), new QuiltDesignThumbnailProvider()); Repository repository = Repository.getDefaultRepository(context); repository.merge(sampleRepository, MergeModes.New); repository.getThemes().createStandardThemes( context.getResources().getInteger(R.integer.theme_swatch_count)); } return context.getString(R.string.toast_samplesLoaded_success); } } catch (IOException e) { } catch (RepositoryException e) { } catch (JSONException e) { } return context.getString(R.string.toast_samplesLoaded_failure); } @Override protected void onPostExecute(String result) { super.onPostExecute(result); raiseOnPostExecute(this, result); } @Override protected void onCancelled(String result) { super.onCancelled(result); raiseOnCancelled(this, result); } private String loadSampleJSON(Context context) throws IOException { final int BUFFER_SIZE = 10000; final char[] buffer = new char[BUFFER_SIZE]; InputStream resourceStream = context.getResources().openRawResource(R.raw.samples); ZipInputStream zipStream = new ZipInputStream(new BufferedInputStream(resourceStream)); try { ZipEntry ze = zipStream.getNextEntry(); if (ze != null) { InputStreamReader reader = new InputStreamReader(zipStream); try { StringBuilder sb = new StringBuilder(); int count = reader.read(buffer); while (count >= 0) { sb.append(buffer, 0, count); count = reader.read(buffer); } return sb.toString(); } finally { reader.close(); } } else { return null; } } finally { zipStream.close(); } } } }