package fr.neraud.padlistener.ui.fragment; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; import android.graphics.Color; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.webkit.WebView; import android.widget.Button; import android.widget.Switch; import android.widget.TextView; import java.io.PrintWriter; import java.io.StringWriter; import butterknife.ButterKnife; import butterknife.InjectView; import butterknife.OnCheckedChanged; import butterknife.OnClick; import fr.neraud.log.MyLog; import fr.neraud.padlistener.R; import fr.neraud.padlistener.constant.ProxyMode; import fr.neraud.padlistener.exception.MissingRequirementException; import fr.neraud.padlistener.helper.DefaultSharedPreferencesHelper; import fr.neraud.padlistener.helper.TechnicalSharedPreferencesHelper; import fr.neraud.padlistener.helper.WifiHelper; import fr.neraud.padlistener.service.task.model.SwitchListenerResult; /** * Main fragment for SwitchListener * * @author Neraud */ public class SwitchListenerFragment extends Fragment { private static final String TAG_TASK_FRAGMENT = "switch_listener_task_fragment"; private final SwitchListenerTaskFragment.CallBacks mCallbacks; private SwitchListenerTaskFragment mTaskFragment; private ProxyMode mProxyMode; private boolean mSwitchListenerEnabled = true; private SwitchListenerResult mResult; @InjectView(R.id.switch_listener_status) TextView mListenerStatus; @InjectView(R.id.switch_listener_switch) Switch mListenerSwitch; @InjectView(R.id.switch_listener_secondary_action_button) Button mSecondaryActionButton; @InjectView(R.id.switch_listener_proxy_started) TextView mProxyStartedTextView; @InjectView(R.id.switch_listener_show_logs_button) Button mShowLogsButton; @InjectView(R.id.switch_listener_error_text) TextView mErrorText; public SwitchListenerFragment() { mCallbacks = new SwitchListenerTaskFragment.CallBacks() { @Override public void updateState(SwitchListenerTaskFragment.ListenerState state, SwitchListenerResult result) { MyLog.entry("state = " + state); mResult = result; mProxyStartedTextView.setVisibility(View.GONE); resetState(); if (result != null && !result.isSuccess()) { if (result.getError() instanceof MissingRequirementException) { final int resId = ((MissingRequirementException) result.getError()).getRequirement().getErrorTextResId(); updateMissingRequirement(resId); } else { updateError(result.getError().getMessage(), result); } } if (state != null) { switch (state) { case STARTING: mListenerSwitch.setEnabled(false); forceToggledWithoutListener(true); break; case STARTED: mListenerSwitch.setEnabled(true); forceToggledWithoutListener(true); mListenerStatus.setText(generateStatusStartedText()); String proxyUrl = "127.0.0.1:8008"; final DefaultSharedPreferencesHelper prefHelper = new DefaultSharedPreferencesHelper(getActivity()); if (prefHelper.isListenerNonLocalEnabled()) { final WifiHelper wifiHelper = new WifiHelper(getActivity()); proxyUrl = wifiHelper.getWifiIpAddress() + ":8008"; } mProxyStartedTextView.setText(getString(R.string.switch_listener_proxy_started, proxyUrl)); mProxyStartedTextView.setVisibility(View.VISIBLE); break; case START_FAILED: mListenerSwitch.setEnabled(true); forceToggledWithoutListener(false); mListenerStatus.setText(R.string.switch_listener_status_start_failed); break; case STOPPING: mListenerSwitch.setEnabled(false); forceToggledWithoutListener(false); break; case STOPPED: mListenerSwitch.setEnabled(true); forceToggledWithoutListener(false); mListenerStatus.setText(R.string.switch_listener_status_stopped); break; case STOP_FAILED: mListenerSwitch.setEnabled(true); forceToggledWithoutListener(true); mListenerStatus.setText(R.string.switch_listener_status_stop_failed); break; default: } } else { // No state -> force to stopped mListenerSwitch.setEnabled(true); forceToggledWithoutListener(false); mListenerStatus.setText(R.string.switch_listener_status_stopped); } MyLog.exit(); } }; } private void resetState() { MyLog.entry(); final DefaultSharedPreferencesHelper prefHelper = new DefaultSharedPreferencesHelper(getActivity()); mProxyMode = prefHelper.getProxyMode(); if (mProxyMode == ProxyMode.MANUAL || mProxyMode == ProxyMode.AUTO_WIFI_PROXY) { mSecondaryActionButton.setText(R.string.switch_listener_launch_wifi_settings); } else if (mProxyMode == ProxyMode.AUTO_IPTABLES) { mSecondaryActionButton.setText(R.string.switch_listener_force_stop); } else { mSecondaryActionButton.setVisibility(View.INVISIBLE); } mProxyStartedTextView.setVisibility(View.GONE); mErrorText.setVisibility(View.GONE); mShowLogsButton.setVisibility(View.GONE); final boolean requireWifi = mProxyMode == ProxyMode.AUTO_WIFI_PROXY || prefHelper.isListenerNonLocalEnabled(); final WifiHelper wifiHelper = new WifiHelper(getActivity()); if (prefHelper.getAllListenerTargetHostnames().isEmpty()) { updateMissingRequirement(R.string.switch_listener_settings_no_target_hostname); } else if (requireWifi && !wifiHelper.isWifiConnected()) { updateMissingRequirement(R.string.switch_listener_settings_require_wifi); } else { mListenerSwitch.setClickable(true); mErrorText.setVisibility(View.GONE); } MyLog.exit(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { MyLog.entry(); final View view = inflater.inflate(R.layout.switch_listener_fragment, container, false); ButterKnife.inject(this, view); final FragmentManager fm = getFragmentManager(); mTaskFragment = (SwitchListenerTaskFragment) fm.findFragmentByTag(TAG_TASK_FRAGMENT); if (mTaskFragment == null) { mTaskFragment = new SwitchListenerTaskFragment(); fm.beginTransaction().add(mTaskFragment, TAG_TASK_FRAGMENT).commit(); } mTaskFragment.registerCallbacks(mCallbacks); MyLog.exit(); return view; } @Override public void onDestroyView() { super.onDestroyView(); ButterKnife.reset(this); } private void updateMissingRequirement(int textResId) { MyLog.entry(); mListenerSwitch.setClickable(false); mSecondaryActionButton.setClickable(false); mErrorText.setTextColor(Color.RED); mErrorText.setVisibility(View.VISIBLE); mErrorText.setText(textResId); MyLog.exit(); } private void updateError(String errorMessage, final SwitchListenerResult result) { MyLog.entry(); mResult = result; mListenerSwitch.setClickable(false); mSecondaryActionButton.setClickable(false); mErrorText.setTextColor(Color.RED); mErrorText.setVisibility(View.VISIBLE); mErrorText.setText(errorMessage); mShowLogsButton.setVisibility(View.VISIBLE); MyLog.exit(); } private String generateStatusStartedText() { final ProxyMode mode = new TechnicalSharedPreferencesHelper(getActivity()).getLastListenerStartProxyMode(); String status; switch (mode) { case AUTO_WIFI_PROXY: status = getString(R.string.switch_listener_status_started_proxy_wifi); break; case AUTO_IPTABLES: status = getString(R.string.switch_listener_status_started_iptables); break; case MANUAL: default: status = getString(R.string.switch_listener_status_started_manual); break; } return status; } private void forceToggledWithoutListener(boolean checked) { if (mListenerSwitch.isChecked() != checked) { mSwitchListenerEnabled = false; mListenerSwitch.setChecked(checked); mSwitchListenerEnabled = true; } } @OnCheckedChanged(R.id.switch_listener_switch) @SuppressWarnings("unused") void onListenerCheckChanged(boolean isChecked) { MyLog.entry("isChecked = " + isChecked); if(mSwitchListenerEnabled) { if (isChecked) { mTaskFragment.startListener(); } else { mTaskFragment.stopListener(false); } } MyLog.exit(); } @OnClick(R.id.switch_listener_show_logs_button) @SuppressWarnings("unused") void onShowLogsButtonClicked() { MyLog.entry(); final AlertDialog.Builder alert = new AlertDialog.Builder(getActivity()); alert.setTitle(R.string.switch_listener_show_logs_title); final WebView wv = new WebView(getActivity()); final StringBuilder dataBuilder = new StringBuilder(); dataBuilder.append("<html><body>"); if (mResult.getError() != null) { dataBuilder.append("<h2>").append(mResult.getError().getMessage()).append("</h2><br/>"); final StringWriter sw = new StringWriter(); final PrintWriter pw = new PrintWriter(sw); mResult.getError().printStackTrace(pw); final String stackTrace = sw.toString(); pw.close(); dataBuilder.append("<b>Stacktrace</b> : <br/>"); dataBuilder.append("<pre>").append(stackTrace).append("</pre>"); } if (mResult.getLogs() != null) { dataBuilder.append("<b>Logs</b> : <br/>"); dataBuilder.append("<pre>"); for (final String logLine : mResult.getLogs()) { dataBuilder.append(logLine).append("\n"); } dataBuilder.append("</pre>"); } dataBuilder.append("</body></html>"); wv.loadDataWithBaseURL("", dataBuilder.toString(), "text/html", "UTF-8", ""); alert.setView(wv); alert.setNegativeButton(R.string.switch_listener_show_logs_close, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int id) { dialog.dismiss(); } }); alert.show(); MyLog.exit(); } @OnClick(R.id.switch_listener_secondary_action_button) @SuppressWarnings("unused") void onSecondaryActionClicked() { MyLog.entry(); if (mProxyMode == ProxyMode.MANUAL || mProxyMode == ProxyMode.AUTO_WIFI_PROXY) { startActivity(new Intent(android.provider.Settings.ACTION_WIFI_SETTINGS)); } else if (mProxyMode == ProxyMode.AUTO_IPTABLES) { mTaskFragment.stopListener(true); } MyLog.exit(); } }