Android Open Source - haveibeenpwned Main Activity






From Project

Back to project page haveibeenpwned.

License

The source code is released under:

Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCT...

If you think the Android project haveibeenpwned listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
* Copyright (C) 2014 Bj?rn Lund?n/*w w w .  java2 s  .  c  om*/
*
* 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 se.blunden.haveibeenpwned;

import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.content.DialogInterface.OnClickListener;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends ActionBarActivity {
  private static final String TAG = "HaveIBeenPwned";
  
  private static String aboutMessage = null;
  private AlertDialog mAboutDialog;
  private SharedPreferences mPreferences;
  
  private DBAdapter db;
  private static ArrayList<String> searchHistory = null;
  
  private HistoryCardView historyCard;
  private EditText searchInputField;
  private ImageButton searchButton;
  
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    
    // Explicitly specify the preference file to load instead of the default to actually make it read it properly
    mPreferences = getApplicationContext().getSharedPreferences("preferences", Context.MODE_PRIVATE);
    
    db = new DBAdapter(this);
    
    if(isFirstLaunch()) {
      displayHelpCard();      
      storeFirstLaunch();
    }
    
    prepareAboutDialog();
    
    // Check if this is the first start and if so, fetch the history from the db
    if(savedInstanceState == null) {
      searchHistory = new ArrayList<String>();
      // Fetch the search history from the database and display the history card
      new FetchHistoryTask().execute();
    } else {
      // Since we are restoring from a configuration change (probably a rotation), searchHistory is populated already
      if(!searchHistory.isEmpty()) {
        displayHistoryCard();
      }
    }
    
        searchInputField = (EditText) findViewById(R.id.input_search);
        
        searchInputField.setOnEditorActionListener(new EditText.OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                if (actionId == EditorInfo.IME_ACTION_SEARCH) {
                  performSearch();
                    return true;
                }
                return false;
            }
        });

        searchButton = (ImageButton) findViewById(R.id.button_search);
        searchButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {
              performSearch();
            }
        });
  }
  
  private void performSearch() {
    if(!isConnected()) {
      Log.e(TAG, "No internet connection detected");
      Toast.makeText(getBaseContext(), getString(R.string.error_no_connection), Toast.LENGTH_SHORT).show();
      return;
    }
    
    String account = searchInputField.getText().toString().trim();
      
      // Add to search history unless it matches the most recently searched account
      if(!account.equals("") && account != null && !matchesLatestSearch(account)) {
        searchHistory.add(account);
        Log.d(TAG, "performSearch searchHistory: " + searchHistory);
        db.setOutdated(true);
      }
      Log.d(TAG, "Searching for account: " + account);
      
      // Clear the search field
      searchInputField.setText("");
      
      showSpinner();
      
      // Perform the search using the AsyncTask
      new PerformSearchTask().execute(account);
  }

  private void displayOutput(Breach breach) {
    // Get a reference to the layout where the card will be displayed
    final LinearLayout layout = (LinearLayout) findViewById(R.id.now_layout);
    
    // Create the View for the card and pass along the breach data used to populate it
    final BreachCardView card = new BreachCardView(this, breach);
    
    // Specify layout parameters to be applied
    LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
    lp.setMargins(0, 20, 0, 0);
    
    card.setLayoutParams(lp);
    
        // Create the swipe-to-dismiss touch listener.
        card.setOnTouchListener(new SwipeDismissTouchListener(
            card,
            null,
            new SwipeDismissTouchListener.DismissCallbacks() {
                @Override
                public boolean canDismiss(Object token) {
                    return true;
                }

                @Override
                public void onDismiss(View view, Object token) {
                  layout.removeView(card);
                }
            }));
        
        layout.addView(card);
  }
  
  private void displayHelpCard() {
    // Get a reference to the layout where the card will be displayed
    final LinearLayout layout = (LinearLayout) findViewById(R.id.now_layout);
    
    // Create the View for the card 
    final HelpCardView card = new HelpCardView(this);
    
    // Specify layout parameters to be applied
    LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
    lp.setMargins(0, 20, 0, 0);
    
    card.setHeaderText(getString(R.string.card_title_help));
    card.setDescriptionText(getString(R.string.card_description_help));
    card.setDismissText(getString(R.string.card_swipe_dismiss));
    card.setLayoutParams(lp);
    
        // Create the swipe-to-dismiss touch listener.
        card.setOnTouchListener(new SwipeDismissTouchListener(
            card,
            null,
            new SwipeDismissTouchListener.DismissCallbacks() {
                @Override
                public boolean canDismiss(Object token) {
                    return true;
                }

                @Override
                public void onDismiss(View view, Object token) {
                  layout.removeView(card);
                }
            }));
        
        layout.addView(card);
  }
  
  private void displayHistoryCard() {
    // Get a reference to the layout where the card will be displayed
    final LinearLayout layout = (LinearLayout) findViewById(R.id.now_layout);
    
    // Create the View for the card and save the reference
    if(historyCard == null) {
      historyCard = new HistoryCardView(this);
    }
    
    // Specify layout parameters to be applied
    LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
    lp.setMargins(0, 20, 0, 0);
    
    updateHistoryCard(historyCard);
    historyCard.setLayoutParams(lp);
    
        // Create the swipe-to-dismiss touch listener.
    historyCard.setOnTouchListener(new SwipeDismissTouchListener(
      historyCard,
            null,
            new SwipeDismissTouchListener.DismissCallbacks() {
                @Override
                public boolean canDismiss(Object token) {
                    return true;
                }

                @Override
                public void onDismiss(View view, Object token) {
                  layout.removeView(historyCard);
                }
            }));

        layout.addView(historyCard);
        
        // Register listeners for the buttons (must be done after adding the view)
    ImageButton historyButton1 = (ImageButton) findViewById(R.id.button_history_search_1);
    historyButton1.setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {
              searchInputField.setText(historyCard.getHistory1().getText());
              performSearch();
            }
        });
    
    final TextView historyText1 = (TextView) findViewById(R.id.card_history_1);
    historyText1.setOnLongClickListener(new View.OnLongClickListener() {
            public boolean onLongClick(View view) {
              confirmDelete(historyCard.getHistory1().getText().toString(), 1);
              return true;
            }
        });
    
    ImageButton historyButton2 = (ImageButton) findViewById(R.id.button_history_search_2);
    historyButton2.setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {
              searchInputField.setText(historyCard.getHistory2().getText());
              performSearch();
            }
        });
    
    final TextView historyText2 = (TextView) findViewById(R.id.card_history_2);
    historyText2.setOnLongClickListener(new View.OnLongClickListener() {
            public boolean onLongClick(View view) {
              confirmDelete(historyCard.getHistory2().getText().toString(), 2);
              return true;
            }
        });
    
    ImageButton historyButton3 = (ImageButton) findViewById(R.id.button_history_search_3);
    historyButton3.setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {
              searchInputField.setText(historyCard.getHistory3().getText());
              performSearch();
            }
        });
    
    final TextView historyText3 = (TextView) findViewById(R.id.card_history_3);
    historyText3.setOnLongClickListener(new View.OnLongClickListener() {
            public boolean onLongClick(View view) {
              confirmDelete(historyCard.getHistory3().getText().toString(), 3);
              return true;
            }
        });
  }
  
  private void updateHistoryCard(HistoryCardView card) {
    // card should never end up null here but check just in case
    if(searchHistory != null && card != null) {
      int last = searchHistory.size() - 1;
      switch(last) {
        case -1:
          Log.d(TAG, "last index: " + last);
          card.setHistory1(null);
          card.setHistory2(null);
          card.setHistory3(null);
          // Removes the history card view
          final LinearLayout layout = (LinearLayout) findViewById(R.id.now_layout);
          layout.removeView(historyCard);
          break;
        case 0:
          card.setHistory1(searchHistory.get(last));
          card.setHistory2(null);
          card.setHistory3(null);
          break;
        
        case 1:
          card.setHistory1(searchHistory.get(last));
          card.setHistory2(searchHistory.get(last - 1));
          card.setHistory3(null);
          break;
          
        default: // Enough search history to fill all 3 slots
          card.setHistory1(searchHistory.get(last));
          card.setHistory2(searchHistory.get(last - 1));
          card.setHistory3(searchHistory.get(last - 2));
          break;
      }
    }
  }
  
  private void confirmDelete(String account, int id) {
    AlertDialog confirmDialog = new AlertDialog.Builder(this)
    .setTitle(account)
    .setMessage(R.string.confirm_delete)
    .setPositiveButton(R.string.yes, new DeleteOnClickListener(id))
    .setNegativeButton(R.string.no, new OnClickListener() {
      @Override
      public void onClick(DialogInterface dialog, int which) {
        dialog.dismiss();
      }
    })
    .create();
    confirmDialog.show();
  }
  
  private final class DeleteOnClickListener implements DialogInterface.OnClickListener {
      private int id;
      
      public DeleteOnClickListener(int id) {
        this.id = id;
      }
    
    public void onClick(DialogInterface dialog, int which) {
      if(searchHistory.size() > 0) {
        searchHistory.remove(searchHistory.size() - id);
      }
      updateHistoryCard(historyCard);
      }
    }
  
  private void showSpinner() {
    searchInputField.setVisibility(View.INVISIBLE);
    
    View spinner = findViewById(R.id.search_spinner);
    spinner.setVisibility(View.VISIBLE);
  }
  
  private void hideSpinner() {
    View spinner = findViewById(R.id.search_spinner);
    spinner.setVisibility(View.GONE);
    
    searchInputField.setVisibility(View.VISIBLE);
  }
  
  private void prepareAboutDialog() {
    if (aboutMessage == null) {
      aboutMessage = getString(R.string.about_message);
    }
    
    mAboutDialog = new AlertDialog.Builder(this)
    .setTitle(R.string.menu_about)
    .setMessage(aboutMessage)
    .setNeutralButton(R.string.ok, new OnClickListener() {
      @Override
      public void onClick(DialogInterface dialog, int which) {
        dialog.dismiss();
      }
    })
    .create();
  }
  
  private void clearAllCards() {
    boolean finished = false;
    while(!finished) {
      ViewGroup group = (ViewGroup) findViewById(R.id.now_layout);
      int count = group.getChildCount();
      int i;
      for (i = 0; i < count; i++) {
        View view = group.getChildAt(i);
            if (view instanceof BreachCardView || view instanceof HelpCardView) {
              group.removeView(view);
              break;
            }
        }
      if(i == count) {
        finished = true;
      }
    }
  }
  
  public boolean isConnected() {
      ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
      NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
      
      return (activeNetwork != null && activeNetwork.isConnected());
    }
  
  private boolean isFirstLaunch() {
      return mPreferences.getBoolean("firstLaunch", true);
    }
  
  private void storeFirstLaunch(){
      SharedPreferences.Editor editor = mPreferences.edit();
      
      editor.putBoolean("firstLaunch", false);
      editor.apply();
    }
  
  private boolean matchesLatestSearch(String account) {
    if(!searchHistory.isEmpty()) {
      String latestSearch = searchHistory.get(searchHistory.size() - 1);
      if(latestSearch != null) {
        return latestSearch.equals(account);
      }
    }
    return false;
  }
  
  @Override
  protected void onSaveInstanceState(Bundle outState) {
      super.onSaveInstanceState(outState);
      // Store all breaches to be able to restore on configuration change
      ArrayList<Breach> savedBreaches = new ArrayList<Breach>();
      boolean firstLaunch = false;
      
      ViewGroup group = (ViewGroup) findViewById(R.id.now_layout);
      for (int i = 0, count = group.getChildCount(); i < count; ++i) {
          View view = group.getChildAt(i);
          if (view instanceof BreachCardView) {
            savedBreaches.add(((BreachCardView) view).getBreach());
          }
          if (view instanceof HelpCardView) {
            firstLaunch = true;
          }
      }

      outState.putParcelableArrayList("savedBreaches", savedBreaches);
      outState.putString("savedSearchInput", searchInputField.getText().toString());
      outState.putBoolean("firstLaunch", firstLaunch);
      outState.putStringArrayList("searchHistory", searchHistory);
  }
  
  @Override
  protected void onRestoreInstanceState(Bundle savedInstanceState) {
    // Retrieve saved breaches
    ArrayList<Breach> savedBreaches = savedInstanceState.getParcelableArrayList("savedBreaches");
    searchHistory = savedInstanceState.getStringArrayList("searchHistory");
    
    boolean firstLaunch = savedInstanceState.getBoolean("firstLaunch");
    
    // Restore saved user search field input
    searchInputField.setText(savedInstanceState.getString("savedSearchInput"));
    
    // Add the help card back
    if(firstLaunch) {
      displayHelpCard();
    }
    
    // Add the cards back
    if(savedBreaches != null) {
      for(Breach breach : savedBreaches) {
        displayOutput(breach);
      }
    }
    
    super.onRestoreInstanceState(savedInstanceState);
  }
  
  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu items for use in the action bar
      MenuInflater inflater = getMenuInflater();
      inflater.inflate(R.menu.main_activity_actions, menu);
      
      return super.onCreateOptionsMenu(menu);
  }

  @Override
  public boolean onOptionsItemSelected(MenuItem item) {
    switch(item.getItemId()) {
    case R.id.action_about:
      mAboutDialog.show();
      return true;
    
    case R.id.action_clear_all:
      // Clear the search field
          searchInputField.setText("");
      // Remove all the cards
          clearAllCards();
      return true;
    }

    return super.onOptionsItemSelected(item);
  }
  
  @Override
  public void onStop() {
    super.onStop();
    if(db.isOutdated()) {
      db.updateHistoryDB(searchHistory);
    }
    db.close();
  }
  
  @Override
  public void onPause() {
    super.onPause();
    Log.d(TAG, "onPause searchHistory: " + searchHistory);
    if(db.isOutdated()) {
      db.updateHistoryDB(searchHistory);
    }
    db.close();
  }
  
  @Override
  public void onDestroy() {
    super.onDestroy();
    if(db.isOutdated()) {
      db.updateHistoryDB(searchHistory);
    }
    db.close();
  }
  
  private class PerformSearchTask extends AsyncTask<String, Void, ArrayList<Breach>> {
      protected ArrayList<Breach> doInBackground(String... accounts) {
        HaveIBeenPwnedAPI api = new HaveIBeenPwnedAPI();
        ArrayList<Breach> result = new ArrayList<Breach>();
        try {
        result = api.query(accounts[0]);
      } catch (URISyntaxException e) {
        Toast.makeText(getBaseContext(), getString(R.string.error_invalid_uri_syntax), Toast.LENGTH_SHORT).show();
        e.printStackTrace();
      } catch (IOException e) {
        Toast.makeText(getBaseContext(), getString(R.string.error_invalid_response), Toast.LENGTH_SHORT).show();
        e.printStackTrace();
      }
        return result;
        }

        protected void onPostExecute(ArrayList<Breach> result) {
          hideSpinner();
          
          // Create the history card if not already created by FetchHistoryTask
        if(historyCard == null) {
          displayHistoryCard();
        } else {
          updateHistoryCard(historyCard);
        }
        
          if(result == null) {
            Toast.makeText(getBaseContext(), getString(R.string.error_result_null), Toast.LENGTH_SHORT).show();
            return;
          } else if(!result.isEmpty()) {
            for(Breach breach : result) {
              displayOutput(breach);
            }
          }
        }
    }
  
  private class FetchHistoryTask extends AsyncTask<Void, Void, ArrayList<String>> {
      protected ArrayList<String> doInBackground(Void... params) {
      return db.getHistory();
        }

        protected void onPostExecute(ArrayList<String> result) {
          if(result == null) {
            Log.d(TAG, "onPostExecute: Empty history returned!");
            return;
          } else if(!result.isEmpty()) {
            searchHistory = result;
            db.setOutdated(false);
            displayHistoryCard();
          }
        }
    }
}




Java Source Code List

se.blunden.haveibeenpwned.BreachCardView.java
se.blunden.haveibeenpwned.Breach.java
se.blunden.haveibeenpwned.DBAdapter.java
se.blunden.haveibeenpwned.HaveIBeenPwnedAPI.java
se.blunden.haveibeenpwned.HelpCardView.java
se.blunden.haveibeenpwned.HistoryCardView.java
se.blunden.haveibeenpwned.MainActivity.java
se.blunden.haveibeenpwned.SwipeDismissTouchListener.java