Java tutorial
// Copyright (c) 2014 Dan Nagle. All rights reserved. // // Licensed MIT: https://github.com/dannagle/PacketSender-Android package com.packetsender.android; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Locale; import android.app.Activity; import android.app.ActionBar; import android.app.Application; import android.app.Fragment; import android.app.FragmentManager; import android.app.FragmentTransaction; import android.app.SearchManager; import android.app.SearchableInfo; import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.os.Handler; import android.provider.Settings; import android.support.v13.app.FragmentPagerAdapter; import android.os.Bundle; import android.support.v4.view.ViewPager; import android.text.InputType; import android.util.Log; import android.view.Gravity; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.CheckBox; import android.widget.EditText; import android.widget.ListView; import android.widget.SearchView; import android.widget.TextView; import android.widget.Toast; import android.app.ActivityManager; import android.app.AlertDialog; import android.app.ActivityManager.RunningServiceInfo; public class MainActivity extends Activity implements ActionBar.TabListener, SearchView.OnQueryTextListener { /** * The {@link android.support.v4.view.PagerAdapter} that will provide * fragments for each of the sections. We use a * {@link FragmentPagerAdapter} derivative, which will keep every * loaded fragment in memory. If this becomes too memory intensive, it * may be best to switch to a * {@link android.support.v13.app.FragmentStatePagerAdapter}. */ SectionsPagerAdapter mSectionsPagerAdapter; private static Intent serviceIntent; private Context mContext; private DataStorage dataStore; private int activeMenu = R.menu.packetlistmenu; private SearchView mSearchView; private List<Packet> trafficLogPackets; public View trafficFragmentView; public View packetsFragmentView; //Runnable to self update the saved lists... private Runnable updateSavedLists; private String ipAddress; private boolean wifiActive; private Runnable updateWifi; private Runnable trafficLogPolling; private final Handler mHandler = new Handler(); /** * The {@link ViewPager} that will host the section contents. */ ViewPager mViewPager; @Override public void onResume() { super.onResume(); if (packetsFragmentView != null) { packetsFragmentView.invalidate(); } } @Override public void onPause() { super.onPause(); } public void onDestroy() { stopListenerService(); super.onDestroy(); } @Override public boolean onQueryTextSubmit(String s) { Log.d("main", DataStorage.FILE_LINE(s)); return false; } @Override public boolean onQueryTextChange(String s) { Log.d("main", DataStorage.FILE_LINE(s)); return false; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mContext = getApplicationContext(); serviceIntent = new Intent(mContext, PacketListenerService.class); activeMenu = R.menu.packetlistmenu; trafficLogPackets = new ArrayList<Packet>(); dataStore = new DataStorage(getSharedPreferences(DataStorage.PREFS_SETTINGS_NAME, 0), getSharedPreferences(DataStorage.PREFS_SAVEDPACKETS_NAME, 0), getSharedPreferences(DataStorage.PREFS_SERVICELOG_NAME, 0), getSharedPreferences(DataStorage.PREFS_MAINTRAFFICLOG_NAME, 0)); dataStore.clearServicePackets(); // Set up the action bar. final ActionBar actionBar = getActionBar(); actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); // Create the adapter that will return a fragment for each of the three // primary sections of the activity. mSectionsPagerAdapter = new SectionsPagerAdapter(getFragmentManager()); // Set up the ViewPager with the sections adapter. mViewPager = (ViewPager) findViewById(R.id.pager); mViewPager.setAdapter(mSectionsPagerAdapter); // When swiping between different sections, select the corresponding // tab. We can also use ActionBar.Tab#select() to do this if we have // a reference to the Tab. mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { @Override public void onPageSelected(int position) { actionBar.setSelectedNavigationItem(position); } }); // For each of the sections in the app, add a tab to the action bar. for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) { // Create a tab with text corresponding to the page title defined by // the adapter. Also specify this Activity object, which implements // the TabListener interface, as the callback (listener) for when // this tab is selected. actionBar .addTab(actionBar.newTab().setText(mSectionsPagerAdapter.getPageTitle(i)).setTabListener(this)); } startListenerService(); wifiActive = DataStorage.isWifiActive(mContext); ipAddress = ""; if (wifiActive) { ipAddress = DataStorage.getIP(mContext); Toast.makeText(mContext, "Your IP is " + ipAddress, Toast.LENGTH_LONG).show(); } else { Toast.makeText(mContext, "Send only. Wifi is inactive.", Toast.LENGTH_LONG).show(); } //periodically poll the traffic log trafficLogPolling = new Runnable() { public void run() { String msg = dataStore.getToast(); if (!msg.isEmpty()) { Toast.makeText(mContext, msg, Toast.LENGTH_LONG).show(); } Packet[] trafficPackets = dataStore.fetchAllTrafficLogPackets(); if (trafficPackets.length != trafficLogPackets.size()) { trafficLogPackets.clear(); trafficLogPackets.addAll(Arrays.asList(trafficPackets)); updateTrafficPacketsList(trafficFragmentView); //trafficFragmentView } //Log.d("main", DataStorage.FILE_LINE( "trafficLogPolling.")); mHandler.postDelayed(trafficLogPolling, 1100); } }; //periodically monitor Wi-Fi updateWifi = new Runnable() { public void run() { boolean checkWifi = DataStorage.isWifiActive(mContext); if (checkWifi != wifiActive) { if (checkWifi) { ipAddress = DataStorage.getIP(mContext); Toast.makeText(mContext, "Your IP is " + ipAddress, Toast.LENGTH_LONG).show(); } else { Toast.makeText(mContext, "Wifi is not active", Toast.LENGTH_LONG).show(); } wifiActive = checkWifi; } mHandler.postDelayed(updateWifi, 5000); } }; mHandler.postDelayed(updateWifi, 5000); mHandler.postDelayed(trafficLogPolling, 700); //setup saved List periodic check updateSavedLists = new Runnable() { public void run() { if (dataStore.isInvalidateLists()) { Log.d("main", DataStorage.FILE_LINE("Found invalid lists.")); updateSavedPacketsList(packetsFragmentView); dataStore.clearInvalidateLists(); } mHandler.postDelayed(updateSavedLists, 2000); } }; mHandler.postDelayed(updateSavedLists, 7000); } public AdapterView.OnItemClickListener getTrafficOnClick() { final MainActivity Main = this; return new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, final View view, int position, long id) { final int finalPosition = position; Log.d("main", DataStorage.FILE_LINE("Clicked " + position)); final Packet updatePacket = trafficLogPackets.get(position).duplicate(); updatePacket.name = "save"; AlertDialog.Builder alert = new AlertDialog.Builder(Main); alert.setTitle("Packet Name?"); // Set an EditText view to get user input final EditText input = new EditText(Main); input.setInputType(InputType.TYPE_CLASS_TEXT); //); alert.setView(input); alert.setPositiveButton("Ok", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { String value = input.getText().toString(); // Do something with value! updatePacket.name = value; Packet tempPacket = updatePacket; updatePacket.port = tempPacket.fromPort; updatePacket.toIP = tempPacket.fromIP; ////mDBHelper.updatePacket(packet); //mDBHelper.storemessage(packet); dataStore.savePacket(updatePacket); updateSavedPacketsList(packetsFragmentView); Toast.makeText(mContext, "Reversed addresses and saved.", Toast.LENGTH_SHORT).show(); } }); alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { // Canceled. } }); alert.show(); // see http://androidsnippets.com/prompt-user-input-with-an-alertdialog } }; } public void updateTrafficPacketsList(View rootView) { ListView trafficListView = (ListView) rootView.findViewById(R.id.trafficList); List<Packet> packetList = new ArrayList<Packet>(); packetList.addAll(Arrays.asList(trafficLogPackets.toArray(new Packet[trafficLogPackets.size()]))); Collections.sort(packetList); Collections.reverse(packetList); PacketAdapter packetAdapter = new PacketAdapter(this, packetList.toArray(new Packet[packetList.size()])); if (trafficListView != null) { trafficListView.setAdapter(packetAdapter); packetAdapter.notifyDataSetChanged(); trafficListView.setOnItemClickListener(getTrafficOnClick()); TextView trafficLogEmptyText = (TextView) rootView.findViewById(R.id.trafficLogEmptyText); Button clearLogButton = (Button) rootView.findViewById(R.id.clearTrafficLogButton); if (packetAdapter.isEmpty()) { trafficLogEmptyText.setVisibility(View.VISIBLE); clearLogButton.setVisibility(View.GONE); } else { clearLogButton.setVisibility(View.VISIBLE); trafficLogEmptyText.setVisibility(View.GONE); } } } public void updateSavedPacketsList(View rootView) { ListView packetListView = (ListView) rootView.findViewById(R.id.packetList); final Packet[] packetArray = dataStore.fetchAllSavedPackets(); PacketAdapter packetAdapter = new PacketAdapter(this, packetArray); if (packetListView != null) { packetListView.setAdapter(packetAdapter); packetAdapter.notifyDataSetChanged(); TextView noSavedPacketsText = (TextView) rootView.findViewById(R.id.noSavedPacketsText); if (packetAdapter.isEmpty()) { noSavedPacketsText.setVisibility(View.VISIBLE); } else { noSavedPacketsText.setVisibility(View.GONE); } packetListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, final View view, int position, long id) { Log.d("main", DataStorage.FILE_LINE("Clicked " + position)); Packet sendPacket = packetArray[position].duplicate(); if (activeMenu == R.menu.acceptchangemenu) { Log.d("main", DataStorage.FILE_LINE("Need to delete " + sendPacket.name)); dataStore.DeleteSavedPacket(sendPacket); updateSavedPacketsList(packetsFragmentView); } else { Log.d("main", DataStorage .FILE_LINE("Need to send " + sendPacket.name + " data " + sendPacket.toAscii())); dataStore.sendPacketToService(sendPacket); } } }); packetListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { Log.d("main", DataStorage.FILE_LINE("long click " + position)); Packet editPacket = packetArray[position].duplicate(); Intent newPacketActivity = DataStorage.getIntentFromPacket(editPacket); newPacketActivity.setClass(getApplicationContext(), NewPacketActivity.class); startActivity(newPacketActivity); return true; } }); } } public static boolean isMyServiceRunning(Context ctx) { ActivityManager manager = (ActivityManager) ctx.getSystemService(Context.ACTIVITY_SERVICE); for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) { if ("com.packetsender.android.PacketListenerService".equals(service.service.getClassName())) { return true; } } return false; } public RunningServiceInfo getServiceIntent() { ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) { if ("com.packetsender.android.PacketListenerService".equals(service.service.getClassName())) { return service; } } return null; } public void stopListenerService() { if (isMyServiceRunning(mContext)) { Log.i("main", DataStorage.FILE_LINE("Service is running. Stop it.")); if (serviceIntent != null) { Log.d("debug", DataStorage.FILE_LINE("serviceIntent is not null.")); } mContext.stopService(serviceIntent); } } public void startListenerService() { if (isMyServiceRunning(mContext)) { stopListenerService(); // do nothing } //this.needStop(); //clear out stop commands mContext.startService(serviceIntent); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(activeMenu, menu); if (activeMenu == R.menu.acceptchangemenu) return true; //MenuItem searchItem = menu.findItem(R.id.action_search); // mSearchView = (SearchView) searchItem.getActionView(); // setupSearchView(searchItem); return true; } private void setupSearchView(MenuItem searchItem) { //searchItem.setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW); SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE); if (searchManager != null) { List<SearchableInfo> searchables = searchManager.getSearchablesInGlobalSearch(); SearchableInfo info = searchManager.getSearchableInfo(getComponentName()); for (SearchableInfo inf : searchables) { if (inf.getSuggestAuthority() != null && inf.getSuggestAuthority().startsWith("applications")) { info = inf; } } mSearchView.setSearchableInfo(info); } mSearchView.setOnQueryTextListener(this); } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); activeMenu = R.menu.packetlistmenu; switch (id) { case R.id.action_new: Intent newPacketActivty = new Intent(this, NewPacketActivity.class); startActivity(newPacketActivty); break; case R.id.action_discard: Toast.makeText(this, "Tap to delete.", Toast.LENGTH_SHORT).show(); activeMenu = R.menu.acceptchangemenu; break; case R.id.action_search: break; case R.id.action_about: Intent newAboutActivity = new Intent(this, AboutActivity.class); startActivity(newAboutActivity); break; default: break; } invalidateOptionsMenu(); return super.onOptionsItemSelected(item); } @Override public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) { // When the given tab is selected, switch to the corresponding page in // the ViewPager. mViewPager.setCurrentItem(tab.getPosition()); } @Override public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) { } @Override public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) { } /** * A {@link FragmentPagerAdapter} that returns a fragment corresponding to * one of the sections/tabs/pages. */ public class SectionsPagerAdapter extends FragmentPagerAdapter { public SectionsPagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) { // getItem is called to instantiate the fragment for the given page. // Return a PlaceholderFragment (defined as a static inner class below). return PlaceholderFragment.newInstance(position + 1); } @Override public int getCount() { // Show 3 total pages. return 3; } @Override public CharSequence getPageTitle(int position) { Locale l = Locale.getDefault(); switch (position) { case 0: return getString(R.string.title_packets).toUpperCase(l); case 1: return getString(R.string.title_trafficlog).toUpperCase(l); case 2: return getString(R.string.title_settings).toUpperCase(l); } return null; } } /** * A placeholder fragment containing a simple view. */ public static class PlaceholderFragment extends Fragment { /** * The fragment argument representing the section number for this * fragment. */ private static final String ARG_SECTION_NUMBER = "section_number"; /** * Returns a new instance of this fragment for the given section * number. */ public static PlaceholderFragment newInstance(int sectionNumber) { PlaceholderFragment fragment = new PlaceholderFragment(); Bundle args = new Bundle(); args.putInt(ARG_SECTION_NUMBER, sectionNumber); fragment.setArguments(args); return fragment; } public PlaceholderFragment() { } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_main, container, false); TextView textView = (TextView) rootView.findViewById(R.id.section_label); textView.setText(Integer.toString(getArguments().getInt(ARG_SECTION_NUMBER))); MainActivity Main = (MainActivity) getActivity(); switch ((getArguments().getInt(ARG_SECTION_NUMBER))) { case 0: break; case 1: rootView = inflater.inflate(R.layout.packetlist, container, false); Main.packetsFragmentView = rootView; //load saved packets Main.updateSavedPacketsList(rootView); break; case 2: rootView = inflater.inflate(R.layout.trafficlist, container, false); Main.trafficFragmentView = rootView; //load traffic log packets Main.updateTrafficPacketsList(rootView); Button clearLogButton = (Button) rootView.findViewById(R.id.clearTrafficLogButton); clearLogButton.setOnClickListener(new Button.OnClickListener() { public void onClick(View v) { //perform action MainActivity Main = (MainActivity) getActivity(); Main.dataStore.clearTrafficPackets(); } }); break; case 3: rootView = inflater.inflate(R.layout.settingsform, container, false); //TODO actually implement the settings stuff Button wifiButton = (Button) rootView.findViewById(R.id.setupWifiButton); wifiButton.setOnClickListener(new Button.OnClickListener() { public void onClick(View v) { //perform action Log.d("main", DataStorage.FILE_LINE("Do wifiButton button")); MainActivity Main = (MainActivity) getActivity(); Main.startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS)); } }); Main.dataStore.prepSettings(rootView); Button applyButton = (Button) rootView.findViewById(R.id.applyButton); final View finalView = rootView; applyButton.setOnClickListener(new Button.OnClickListener() { public void onClick(View v) { //perform action Log.d("main", DataStorage.FILE_LINE("Do apply button")); MainActivity Main = (MainActivity) getActivity(); Main.dataStore.saveSettings(finalView); Main.startListenerService(); } }); default: break; } return rootView; } } }