Java tutorial
/* * Copyright (C) 2011 The Android Open Source Project * * 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 org.pquery; import android.app.NotificationManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.os.Parcelable; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; import android.widget.Toast; import com.actionbarsherlock.app.SherlockFragmentActivity; import com.actionbarsherlock.view.ActionMode; import com.actionbarsherlock.view.Menu; import com.actionbarsherlock.view.MenuItem; import com.actionbarsherlock.view.Window; import junit.framework.Assert; import net.htmlparser.jericho.Config; import org.pquery.dao.DownloadablePQ; import org.pquery.fragments.MyDialogFragment; import org.pquery.fragments.PQListFragment; import org.pquery.fragments.PQListFragment.PQClickedListener; import org.pquery.fragments.ProgressBoxFragment; import org.pquery.fragments.ProgressBoxFragment.ProgressBoxFragmentListener; import org.pquery.service.PQService; import org.pquery.service.PQServiceListener; import org.pquery.service.RetrievePQListResult; import org.pquery.util.Logger; import org.pquery.util.Prefs; import org.pquery.util.Util; import org.pquery.webdriver.ProgressInfo; import java.util.Date; public class Main extends SherlockFragmentActivity implements PQClickedListener, PQServiceListener, ProgressBoxFragmentListener { private boolean doDialog; private boolean onSaveInstanceStateCalled; private PQService service; private enum ServiceStatus { NotConnected, Connected, ServiceBusy } ; private ServiceStatus serviceStatus; //private long pqListTimestamp; @Override protected void onDestroy() { super.onDestroy(); Logger.d("enter"); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // We only want single instance of this activity at top // If launched via a notification and by normal icon android can try //to create another copy of activity down stack // Don't want that so pop superfluus activity // // http://stackoverflow.com/questions/4341600/how-to-prevent-multiple-instances-of-an-activity-when-it-is-launched-with-differ if (!isTaskRoot()) { final Intent intent = getIntent(); final String intentAction = intent.getAction(); if (intent.hasCategory(Intent.CATEGORY_LAUNCHER) && intentAction != null && intentAction.equals(Intent.ACTION_MAIN)) { Logger.w("Not root. Finishing Main Activity instead of launching"); finish(); return; } } // Make Jericho form parsing case sensitive Config.CurrentCompatibilityMode = Config.CompatibilityMode.MOZILLA; // Enable logging (if pref set) // If first time logging has been initialised a new log file will be created Logger.setEnable(Prefs.getDebug(this)); Logger.d("enter"); // Enable progress bar at top of window requestWindowFeature(Window.FEATURE_PROGRESS); setContentView(R.layout.main2); String title = getIntent().getStringExtra("title"); if (title != null) doDialog = true; } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); setIntent(intent); String title = intent.getStringExtra("title"); if (title != null) doDialog = true; } @Override protected void onResume() { super.onResume(); Logger.d("enter"); onSaveInstanceStateCalled = false; long time = Prefs.getPQListStateTimestamp(this); PQListFragment pqList = (PQListFragment) getSupportFragmentManager() .findFragmentById(R.id.pq_list_fragment); // First check if we have a DownloadablePQ list stored if (time != 0) { // OK we know we have a DownloadablePQ list // First check if it is too old // If so erase it and set list to be empty if (new Date().getTime() - time > 1000 * 60 * 15) { Prefs.erasePQListState(this); pqList.updateList(null, null); } else { pqList.updateList(Prefs.getDPQListState(this), Prefs.getRPQListState(this)); } //this.pqListTimestamp = time; //} } else { pqList.updateList(null, null); } if (doDialog) { String title = getIntent().getStringExtra("title"); String message = getIntent().getStringExtra("message"); int notificationId = getIntent().getIntExtra("notificationId", 0); if (title != null && message != null) { onServiceOperationResult(title, message, notificationId); } getIntent().removeExtra("title"); getIntent().removeExtra("message"); getIntent().removeExtra("notificationId"); } doDialog = false; doBindService(); } @Override protected void onPause() { super.onPause(); Logger.d("enter"); doUnbindService(); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); Logger.d("enter"); //outState.putLong("pqListTimestamp", pqListTimestamp); onSaveInstanceStateCalled = true; } @Override public boolean onCreateOptionsMenu(Menu menu) { if (serviceStatus == ServiceStatus.ServiceBusy) { setSupportProgressBarVisibility(true); setSupportProgressBarIndeterminateVisibility(true); } else { setSupportProgressBarVisibility(false); setSupportProgressBarIndeterminateVisibility(false); } if (serviceStatus == ServiceStatus.Connected) { menu.add(0, R.string.create, 0, R.string.create).setIcon(R.drawable.content_new) .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT); menu.add(0, R.string.get_pq_list, 0, R.string.get_pq_list).setIcon(R.drawable.navigation_refresh) .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); } else { menu.add(0, R.string.create, 0, R.string.create) .setIcon(Util.toGrey(getResources(), R.drawable.content_new)) .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT); menu.add(0, R.string.get_pq_list, 0, R.string.get_pq_list) .setIcon(Util.toGrey(getResources(), R.drawable.navigation_refresh)) .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); } menu.add(0, R.string.help, 0, R.string.help).setIcon(R.drawable.action_help) .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); menu.add(0, R.string.settings, 0, R.string.settings).setIcon(R.drawable.action_settings) .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); menu.add(0, R.string.about, 0, R.string.about).setIcon(R.drawable.action_about) .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.string.create: if (Prefs.getUsername(this).length() == 0 || Prefs.getPassword(this).length() == 0) { Toast.makeText(this, R.string.enter_gc_credentials, Toast.LENGTH_LONG).show(); return true; } if (serviceStatus != ServiceStatus.Connected) return true; startActivity(new Intent(this, CreateFiltersActivity.class)); break; case R.string.get_pq_list: if (Prefs.getUsername(this).length() == 0 || Prefs.getPassword(this).length() == 0) { Toast.makeText(this, R.string.enter_gc_credentials, Toast.LENGTH_LONG).show(); return true; } if (serviceStatus != ServiceStatus.Connected) return true; Intent intent = new Intent(this, PQService.class); intent.putExtra("operation", PQService.OPERATION_REFRESH); startService(intent); break; case R.string.settings: startActivity(new Intent(this, PreferencesFromXml.class)); break; case R.string.about: startActivity(new Intent(this, About.class)); break; case R.string.help: startActivity(new Intent(this, Help.class)); break; } return true; } private boolean isServiceBound; private ServiceConnection connection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder serviceBinder) { if (onSaveInstanceStateCalled) { Logger.w("Skipping service connected as onSaveInstanceState already called"); } else { Logger.d("connect"); service = ((PQService.LocalBinder) serviceBinder).getService(); service.registerClient(Main.this); checkActionBar(); } } public void onServiceDisconnected(ComponentName className) { Logger.d("disconnect"); service = null; checkActionBar(); } }; private void doBindService() { isServiceBound = bindService(new Intent(getApplicationContext(), PQService.class), connection, BIND_AUTO_CREATE); Logger.d("[isServiceBound=" + isServiceBound + "]"); } /** * Stop being interested in service If still connected to service, sent * unregister message to it */ private void doUnbindService() { Logger.d("[isServiceBound=" + isServiceBound + "]"); if (isServiceBound) { if (service != null) service.unRegisterClient(this); unbindService(connection); isServiceBound = false; } service = null; checkActionBar(); } private class PopupBar implements ActionMode.Callback { private DownloadablePQ pq; public PopupBar(DownloadablePQ pq) { this.pq = pq; } @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { menu.add("Download").setIcon(R.drawable.av_download) .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT); return true; } @Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) { return false; } @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { Intent intent = new Intent(getApplicationContext(), PQService.class); intent.putExtra("operation", PQService.OPERATION_DOWNLOAD); intent.putExtra("pq", (Parcelable) pq); startService(intent); mode.finish(); return true; } @Override public void onDestroyActionMode(ActionMode mode) { actionMode = null; } } ActionMode actionMode; /** * The fragment listing the DownloadablePQ has been clicked on * We open popup bar at top to allow DownloadablePQ to be downloaded */ @Override public void onPQClicked(DownloadablePQ pq) { if (actionMode != null) { // DownloadablePQ was clicked whilst bar was open for a previous DownloadablePQ click // Must manually close previous one // (Attempting to immediately open another bar on the new pq doesn't seem to work ?) actionMode.finish(); } else { // Open top bar to allow selection for DownloadablePQ download if (serviceStatus == ServiceStatus.Connected) actionMode = startActionMode(new PopupBar(pq)); } } /** * The fragment listing the RepeatablePQ has been clicked on * We open popup bar at top to allow RepeatablePQ to be downloaded */ @Override public void onSchedulePQ(String url) { Intent intent = new Intent(getApplicationContext(), PQService.class); intent.putExtra("operation", PQService.OPERATION_REFRESH); intent.putExtra("url", url); startService(intent); } @Override public void onServiceRetrievePQList(RetrievePQListResult pqListResult) { PQListFragment pqList = (PQListFragment) getSupportFragmentManager() .findFragmentById(R.id.pq_list_fragment); pqList.updateList(pqListResult.pqs, pqListResult.repeatables); if (pqListResult.failure != null) { MyDialogFragment dialog = MyDialogFragment.newInstance("Failed", pqListResult.failure.toString()); dialog.show(getSupportFragmentManager(), "dialog"); } checkActionBar(); } @Override public void onServiceProgressInfo(ProgressInfo progressInfo) { Assert.assertNotNull(progressInfo); ProgressBoxFragment box = getProgressBoxFragment(); setSupportProgressBarVisibility(true); int a = (Window.PROGRESS_END - Window.PROGRESS_START) / 100 * progressInfo.percent; setSupportProgress(a); checkActionBar(); box.setText(progressInfo.htmlMessage); } private void checkActionBar() { if (serviceStatus != calculateServiceStatus()) { serviceStatus = calculateServiceStatus(); supportInvalidateOptionsMenu(); if (serviceStatus != ServiceStatus.ServiceBusy) hideProgressBoxFragment(); } } private ServiceStatus calculateServiceStatus() { if (service == null) return ServiceStatus.NotConnected; if (service.isOperationInProgress()) return ServiceStatus.ServiceBusy; return ServiceStatus.Connected; } private ProgressBoxFragment getProgressBoxFragment() { ProgressBoxFragment box = (ProgressBoxFragment) getSupportFragmentManager().findFragmentByTag("robtag"); if (box != null) return box; // Fragment is not currently up. Add it FragmentManager fragmentManager = getSupportFragmentManager(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); box = new ProgressBoxFragment(); fragmentTransaction.add(R.id.fragment_content, box, "robtag"); fragmentTransaction.commit(); return box; } private void hideProgressBoxFragment() { ProgressBoxFragment box = (ProgressBoxFragment) getSupportFragmentManager().findFragmentByTag("robtag"); if (box == null) return; // Fragment is up, need to remove it FragmentManager fragmentManager = getSupportFragmentManager(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); fragmentTransaction.remove(box); fragmentTransaction.commit(); } /** * Fragment containing service progress text has been clicked. Means * user wants to cancel current service and abort; */ @Override public void onProgressBoxFragmentClicked() { if (serviceStatus == ServiceStatus.ServiceBusy) service.cancelInProgress(); } @Override public void onServiceStartingTask() { checkActionBar(); } @Override public void onServiceStoppedTask() { checkActionBar(); } @Override public void onServiceOperationResult(String title, String message, int notificationId) { MyDialogFragment dialog = MyDialogFragment.newInstance(title, message); dialog.show(getSupportFragmentManager(), "dialog"); checkActionBar(); ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).cancel(notificationId); } }