Java tutorial
package com.paranoid.gerrit; /* * Copyright (C) 2013 Android Open Kang Project (AOKP) * Author: Jon Stanford (JBirdVegas), 2013 * * 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. */ import android.app.AlertDialog.Builder; import android.app.DialogFragment; import android.app.SearchManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.content.SharedPreferences; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.preference.PreferenceManager; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; import android.support.v4.content.LocalBroadcastManager; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.Window; import android.widget.SearchView; import android.widget.Toast; import com.google.analytics.tracking.android.EasyTracker; import com.google.analytics.tracking.android.GoogleAnalytics; import com.google.analytics.tracking.android.Logger; import com.google.analytics.tracking.android.MapBuilder; import com.google.analytics.tracking.android.Tracker; import com.paranoid.gerrit.database.SelectedChange; import com.paranoid.gerrit.helpers.ROMHelper; import com.paranoid.gerrit.listeners.DefaultGerritReceivers; import com.paranoid.gerrit.message.ConnectionEstablished; import com.paranoid.gerrit.message.ErrorDuringConnection; import com.paranoid.gerrit.message.EstablishingConnection; import com.paranoid.gerrit.message.Finished; import com.paranoid.gerrit.message.HandshakeError; import com.paranoid.gerrit.message.InitializingDataTransfer; import com.paranoid.gerrit.message.ProgressUpdate; import com.paranoid.gerrit.objects.GerritURL; import com.paranoid.gerrit.search.OwnerSearch; import com.paranoid.gerrit.search.ProjectSearch; import com.paranoid.gerrit.search.SearchKeyword; import com.paranoid.gerrit.tasks.GerritTask; import java.util.HashSet; import java.util.Iterator; import java.util.Set; public class GerritControllerActivity extends FragmentActivity { private static final String TAG = GerritControllerActivity.class.getSimpleName(); private static final String GERRIT_INSTANCE = "gerrit"; private String mGerritWebsite; private GooFileObject mChangeLogStart; private GooFileObject mChangeLogStop; /** * Keep track of all the GerritTask instances so the dialog can be dismissed * when this activity is paused. */ private Set<GerritTask> mGerritTasks; // Listener for changes to which commit is selected private BroadcastReceiver mChangeListener; private DefaultGerritReceivers receivers; // This is maintained for checking if the project has changed without looking private String mCurrentProject; private Menu mMenu; // Indicates if we are running this in tablet mode. private boolean mTwoPane = false; private ChangeListFragment mChangeList; // This will be null if mTwoPane is false (i.e. not tablet mode) private PatchSetViewerFragment mChangeDetail; private SearchView searchView; // Wrapper around searchView for modifying searchView before it is initialised private SearchViewProperties mSearchViewProperties = new SearchViewProperties(); private int mTheme; @Override protected void onStart() { super.onStart(); EasyTracker.getInstance(this).activityStart(this); registerReceivers(); } @Override protected void onStop() { super.onStop(); EasyTracker.getInstance(this).activityStop(this); receivers.unregisterReceivers(); LocalBroadcastManager.getInstance(this).unregisterReceiver(mChangeListener); } @Override public void onCreate(Bundle savedInstanceState) { mTheme = Prefs.getCurrentThemeID(this); setTheme(mTheme); super.onCreate(savedInstanceState); // check if caller has a gerrit instance start screen preference String suppliedGerritInstance = getIntent().getStringExtra(GERRIT_INSTANCE); if (suppliedGerritInstance != null && !suppliedGerritInstance.isEmpty() && suppliedGerritInstance.contains("http")) { // just set the prefs and allow normal loading Prefs.setCurrentGerrit(this, suppliedGerritInstance); } GoogleAnalytics googleAnalytics = GoogleAnalytics.getInstance(this); String trackingId = getString(R.string.ga_trackingId); Tracker tracker = googleAnalytics.getTracker(trackingId); googleAnalytics.getLogger().setLogLevel(Logger.LogLevel.VERBOSE); tracker.send(MapBuilder.createAppView().build()); // keep a log of what ROM our users run EasyTracker easyTracker = EasyTracker.getInstance(this); easyTracker.send(MapBuilder.createEvent(AnalyticsConstants.GA_APP_OPEN, // Event category (required) AnalyticsConstants.GA_ROM_VERSION, // Event action (required) ROMHelper.determineRom(this), // Event label null) // Event value (long) .build()); // note this screen as viewed easyTracker.send(MapBuilder.createAppView().build()); // Keep track of what theme is being used easyTracker.send(MapBuilder.createEvent(AnalyticsConstants.GA_APP_OPEN, AnalyticsConstants.GA_THEME_SET_ON_OPEN, Prefs.getCurrentTheme(this), null).build()); // note this screen as viewed easyTracker.send(MapBuilder.createAppView().build()); requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); setContentView(R.layout.main); FragmentManager fm = getSupportFragmentManager(); if (findViewById(R.id.change_detail_fragment) != null) { // The detail container view will be present only in the // large-screen layouts (res/values-large and // res/values-sw600dp). If this view is present, then the // activity should be in two-pane mode. mTwoPane = true; mChangeDetail = (PatchSetViewerFragment) fm.findFragmentById(R.id.change_detail_fragment); } Prefs.setTabletMode(this, mTwoPane); mChangeList = (ChangeListFragment) fm.findFragmentById(R.id.change_list_fragment); mGerritWebsite = Prefs.getCurrentGerrit(this); /* Initially set the current Gerrit globally here. * We can rely on callbacks to know when they change */ GerritURL.setGerrit(Prefs.getCurrentGerrit(this)); GerritURL.setProject(Prefs.getCurrentProject(this)); // Don't register listeners here. It is registered in onResume instead. mChangeListener = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String changeid = intent.getStringExtra(PatchSetViewerFragment.CHANGE_ID); String status = intent.getStringExtra(PatchSetViewerFragment.STATUS); boolean expand = intent.getBooleanExtra(PatchSetViewerFragment.EXPAND_TAG, false); onChangeSelected(changeid, status, expand); } }; handleIntent(this.getIntent()); } private void init() { // ensure we are not tracking a project unintentionally if (Prefs.getCurrentProject(this).isEmpty()) { Prefs.setCurrentProject(this, null); } mCurrentProject = Prefs.getCurrentProject(this); mGerritTasks = new HashSet<>(); receivers = new DefaultGerritReceivers(this); } // Register to receive messages. private void registerReceivers() { if (receivers == null) { receivers = new DefaultGerritReceivers(this); } receivers.registerReceivers(EstablishingConnection.TYPE, ConnectionEstablished.TYPE, InitializingDataTransfer.TYPE, ProgressUpdate.TYPE, Finished.TYPE, HandshakeError.TYPE, ErrorDuringConnection.TYPE); LocalBroadcastManager.getInstance(this).registerReceiver(mChangeListener, new IntentFilter(PatchSetViewerFragment.NEW_CHANGE_SELECTED)); } @Override public boolean onPrepareOptionsMenu(Menu menu) { hideChangelogOption(Prefs.getCurrentGerrit(this)); return super.onPrepareOptionsMenu(menu); } @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.gerrit_instances_menu, menu); this.mMenu = menu; // Get the SearchView and set the searchable configuration SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE); searchView = (SearchView) menu.findItem(R.id.menu_search).getActionView(); // Assumes current activity is the searchable activity searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName())); searchView.setIconifiedByDefault(true); // Let the change list fragment handle queries directly. searchView.setOnQueryTextListener(mChangeList); searchView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { @Override public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { SearchView view = (SearchView) v; if (view.isIconified()) { mMenu.findItem(R.id.menu_team_instance).setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); mMenu.findItem(R.id.menu_projects).setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); } else { mMenu.findItem(R.id.menu_team_instance).setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); mMenu.findItem(R.id.menu_projects).setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); } } }); setupSearchQuery(); return true; } @Override protected void onNewIntent(Intent intent) { setIntent(intent); handleIntent(intent); } private void handleIntent(Intent intent) { String action = intent.getAction(); if (TheApplication.PREF_CHANGE_TYPE.equals(action)) { onPreferenceChanged(intent.getStringExtra(TheApplication.PREF_CHANGE_KEY)); } else if (!Intent.ACTION_SEARCH.equals(action)) { // Searching is already handled when the query text changes. init(); } } @Override public boolean onOptionsItemSelected(MenuItem item) { Intent intent; switch (item.getItemId()) { case R.id.menu_save: intent = new Intent(this, PrefsActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); startActivity(intent); return true; case R.id.menu_help: showHelpDialog(); return true; case R.id.menu_refresh: refreshTabs(); return true; case R.id.menu_team_instance: DialogFragment newFragment = new GerritSwitcher(); String tag = getResources().getString(R.string.choose_gerrit_instance); // Must use getFragmentManager not getSupportFragmentManager here newFragment.show(getFragmentManager(), tag); return true; case R.id.menu_projects: intent = new Intent(this, ProjectsList.class); intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); startActivity(intent); return true; default: return super.onOptionsItemSelected(item); } } private void onGerritChanged(String newGerrit) { mGerritWebsite = newGerrit; Toast.makeText(this, getString(R.string.using_gerrit_toast) + ' ' + newGerrit, Toast.LENGTH_LONG).show(); hideChangelogOption(newGerrit); // Unset the project - we don't track these across Gerrit instances Prefs.setCurrentProject(this, null); Prefs.clearTrackingUser(this); refreshTabs(); } private void onProjectChanged(String newProject) { String query = getSearchQuery(); query = SearchKeyword.replaceKeyword(query, new ProjectSearch(newProject)); mSearchViewProperties.setQuery(query, true); mCurrentProject = newProject; } private void onUserTrackingChanged(Integer userTracking) { String query = getSearchQuery(); String user = userTracking == null ? "" : userTracking.toString(); query = SearchKeyword.replaceKeyword(query, new OwnerSearch(user)); mSearchViewProperties.setQuery(query, true); } /* Mark all of the tabs as dirty to trigger a refresh when they are next * resumed. refresh must be called on the current fragment as it is already * resumed. */ public void refreshTabs() { mChangeList.refreshTabs(); } @Override protected void onPause() { super.onPause(); if (mGerritTasks != null) { Iterator<GerritTask> it = mGerritTasks.iterator(); while (it.hasNext()) { GerritTask gerritTask = it.next(); if (gerritTask.getStatus() == AsyncTask.Status.FINISHED) { it.remove(); } } } } @Override protected void onResume() { super.onResume(); // Manually check if the Gerrit source changed (from the Preferences) String s = Prefs.getCurrentGerrit(this); if (!s.equals(mGerritWebsite)) onGerritChanged(s); // Manually check if the project changed (e.g. we are resuming from the Projects List) s = Prefs.getCurrentProject(this); if (!s.equals(mCurrentProject)) onProjectChanged(s); // Apply the theme if it has changed int themeId = Prefs.getCurrentThemeID(this); if (themeId != mTheme) { mTheme = themeId; setTheme(themeId); this.recreate(); } } @Override protected void onDestroy() { super.onDestroy(); // if screen gets disposed of before mGerritTasks is initialized if (mGerritTasks != null) { for (GerritTask gerritTask : mGerritTasks) { gerritTask.cancel(true); } mGerritTasks.clear(); mGerritTasks = null; } } /** * Handler for when a change is selected in the list. * @param changeID The currently selected change ID * @param expand Whether to expand the change and view the change details. * Relevant only to the tablet layout. */ public void onChangeSelected(String changeID, String status, boolean expand) { Bundle arguments = new Bundle(); arguments.putString(PatchSetViewerFragment.CHANGE_ID, changeID); arguments.putString(PatchSetViewerFragment.STATUS, status); SelectedChange.setSelectedChange(this, changeID); if (mChangeList.getCurrentFragment() != null) { mChangeList.getCurrentFragment().markChangeAsSelected(changeID); } if (mTwoPane) { mChangeDetail.setSelectedChange(changeID); } else if (expand) { // In single-pane mode, simply start the detail activity // for the selected item ID. Intent detailIntent = new Intent(this, PatchSetViewerActivity.class); detailIntent.putExtras(arguments); startActivity(detailIntent); } } private void onPreferenceChanged(String key) { switch (key) { case Prefs.GERRIT_KEY: onGerritChanged(Prefs.getCurrentGerrit(this)); break; case Prefs.CURRENT_PROJECT: onProjectChanged(Prefs.getCurrentProject(this)); break; case Prefs.TRACKING_USER: onUserTrackingChanged(Prefs.getTrackingUser(this)); break; case Prefs.ANIMATION_KEY: mChangeList.getCurrentFragment().toggleAnimations(Prefs.getAnimationPreference(this)); break; } } public String getSearchQuery() { return mSearchViewProperties.getQuery(); } public ChangeListFragment getChangeList() { return mChangeList; } /** * @return The change detail fragment, may be null. */ public PatchSetViewerFragment getChangeDetail() { return mChangeDetail; } private void showHelpDialog() { Builder builder = new Builder(this); builder.setTitle(R.string.menu_help); LayoutInflater layoutInflater = this.getLayoutInflater(); View dialog = layoutInflater.inflate(R.layout.dialog_help, null); builder.setView(dialog); builder.setNeutralButton(getString(R.string.gerrit_help), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(mGerritWebsite + "Documentation/index.html")); startActivity(browserIntent); } }); builder.create(); builder.show(); } // Call this ONLY after the searchView has been initialised private void setupSearchQuery() { String oldQuery = ""; if (searchView != null && searchView.getQuery() != null) { oldQuery = searchView.getQuery().toString(); } String query = ""; if (mSearchViewProperties != null) query = mSearchViewProperties.mQuery; if (!mCurrentProject.isEmpty()) { query = SearchKeyword.replaceKeyword(query, new ProjectSearch(mCurrentProject)); } Integer user = Prefs.getTrackingUser(this); if (user != null) { query = SearchKeyword.replaceKeyword(query, new OwnerSearch(user.toString())); } if (!oldQuery.equals(query)) { mSearchViewProperties.setQuery(query, false); // Don't submit (it will be submitted initially) } searchView.setIconified(query.isEmpty()); } // SearchView properties to be set and can be used by setupSearchQuery when the search // view is visible class SearchViewProperties { String mQuery = ""; void setQuery(String query, boolean submit) { if (query == null) query = ""; mQuery = query; if (searchView != null) { searchView.setQuery(mQuery, submit); searchView.setIconified(query.isEmpty()); } } String getQuery() { if (searchView != null) { return searchView.getQuery().toString(); } else { return mQuery; } } } }