/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
*
* This file is part of FileExplorer.
*
* FileExplorer is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FileExplorer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with SwiFTP. If not, see <http://www.gnu.org/licenses/>.
*/
package net.micode.fileexplorer;
import net.micode.fileexplorer.FileExplorerTabActivity.IBackPressedListener;
import org.swiftp.Defaults;
import org.swiftp.Globals;
import org.swiftp.MyLog;
import org.swiftp.UiUpdater;
import android.app.Activity;
import android.app.Fragment;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.net.ConnectivityManager;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import java.io.File;
import java.net.InetAddress;
public class ServerControlActivity extends Fragment implements IBackPressedListener {
private TextView ipText;
protected MyLog myLog = new MyLog(this.getClass().getName());
public Handler handler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case 0: // We are being told to do a UI update
// If more than one UI update is queued up, we only need to
// do one.
removeMessages(0);
updateUi();
break;
case 1: // We are being told to display an error message
removeMessages(1);
}
}
};
private TextView instructionText;
private TextView instructionTextPre;
private View startStopButton;
private Activity mActivity;
private View mRootView;
public ServerControlActivity() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mActivity = getActivity();
mRootView = inflater.inflate(R.layout.server_control_activity, container, false);
// Set the application-wide context global, if not already set
Context myContext = Globals.getContext();
if (myContext == null) {
myContext = mActivity.getApplicationContext();
if (myContext == null) {
throw new NullPointerException("Null context!?!?!?");
}
Globals.setContext(myContext);
}
ipText = (TextView) mRootView.findViewById(R.id.ip_address);
instructionText = (TextView) mRootView.findViewById(R.id.instruction);
instructionTextPre = (TextView) mRootView.findViewById(R.id.instruction_pre);
startStopButton = mRootView.findViewById(R.id.start_stop_button);
startStopButton.setOnClickListener(startStopListener);
updateUi();
UiUpdater.registerClient(handler);
// quickly turn on or off wifi.
mRootView.findViewById(R.id.wifi_state_image).setOnClickListener(
new OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent(
android.provider.Settings.ACTION_WIFI_SETTINGS);
startActivity(intent);
}
});
return mRootView;
}
@Override
public boolean onBack() {
return false;
}
/**
* Whenever we regain focus, we should update the button text depending on
* the state of the server service.
*/
public void onStart() {
super.onStart();
UiUpdater.registerClient(handler);
updateUi();
}
public void onResume() {
super.onResume();
UiUpdater.registerClient(handler);
updateUi();
// Register to receive wifi status broadcasts
myLog.l(Log.DEBUG, "Registered for wifi updates");
IntentFilter filter = new IntentFilter();
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
mActivity.registerReceiver(wifiReceiver, filter);
}
/*
* Whenever we lose focus, we must unregister from UI update messages from
* the FTPServerService, because we may be deallocated.
*/
public void onPause() {
super.onPause();
UiUpdater.unregisterClient(handler);
myLog.l(Log.DEBUG, "Unregistered for wifi updates");
mActivity.unregisterReceiver(wifiReceiver);
}
public void onStop() {
super.onStop();
UiUpdater.unregisterClient(handler);
}
public void onDestroy() {
super.onDestroy();
UiUpdater.unregisterClient(handler);
}
/**
* This will be called by the static UiUpdater whenever the service has
* changed state in a way that requires us to update our UI. We can't use
* any myLog.l() calls in this function, because that will trigger an
* endless loop of UI updates.
*/
public void updateUi() {
myLog.l(Log.DEBUG, "Updating UI", true);
WifiManager wifiMgr = (WifiManager) mActivity.getSystemService(Context.WIFI_SERVICE);
int wifiState = wifiMgr.getWifiState();
WifiInfo info = wifiMgr.getConnectionInfo();
String wifiId = info != null ? info.getSSID() : null;
boolean isWifiReady = FTPServerService.isWifiEnabled();
setText(R.id.wifi_state, isWifiReady ? wifiId : getString(R.string.no_wifi_hint));
ImageView wifiImg = (ImageView) mRootView.findViewById(R.id.wifi_state_image);
wifiImg.setImageResource(isWifiReady ? R.drawable.wifi_state4 : R.drawable.wifi_state0);
boolean running = FTPServerService.isRunning();
if (running) {
myLog.l(Log.DEBUG, "updateUi: server is running", true);
// Put correct text in start/stop button
// Fill in wifi status and address
InetAddress address = FTPServerService.getWifiIp();
if (address != null) {
String port = ":" + FTPServerService.getPort();
ipText.setText("ftp://" + address.getHostAddress() + (FTPServerService.getPort() == 21 ? "" : port));
} else {
// could not get IP address, stop the service
Context context = mActivity.getApplicationContext();
Intent intent = new Intent(context, FTPServerService.class);
context.stopService(intent);
ipText.setText("");
}
}
startStopButton.setEnabled(isWifiReady);
TextView startStopButtonText = (TextView) mRootView.findViewById(R.id.start_stop_button_text);
if (isWifiReady) {
startStopButtonText.setText(running ? R.string.stop_server : R.string.start_server);
startStopButtonText.setCompoundDrawablesWithIntrinsicBounds(running ? R.drawable.disconnect
: R.drawable.connect, 0, 0, 0);
startStopButtonText.setTextColor(running ? getResources().getColor(R.color.remote_disconnect_text)
: getResources().getColor(R.color.remote_connect_text));
} else {
if (FTPServerService.isRunning()) {
Context context = mActivity.getApplicationContext();
Intent intent = new Intent(context, FTPServerService.class);
context.stopService(intent);
}
startStopButtonText.setText(R.string.no_wifi);
startStopButtonText.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
startStopButtonText.setTextColor(Color.GRAY);
}
ipText.setVisibility(running ? View.VISIBLE : View.INVISIBLE);
instructionText.setVisibility(running ? View.VISIBLE : View.GONE);
instructionTextPre.setVisibility(running ? View.GONE : View.VISIBLE);
}
private void setText(int id, String text) {
TextView tv = (TextView) mRootView.findViewById(id);
tv.setText(text);
}
OnClickListener startStopListener = new OnClickListener() {
public void onClick(View v) {
Globals.setLastError(null);
File chrootDir = new File(Defaults.chrootDir);
if (!chrootDir.isDirectory())
return;
Context context = mActivity.getApplicationContext();
Intent intent = new Intent(context, FTPServerService.class);
Globals.setChrootDir(chrootDir);
if (!FTPServerService.isRunning()) {
warnIfNoExternalStorage();
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
context.startService(intent);
}
} else {
context.stopService(intent);
}
}
};
private void warnIfNoExternalStorage() {
String storageState = Environment.getExternalStorageState();
if (!storageState.equals(Environment.MEDIA_MOUNTED)) {
myLog.i("Warning due to storage state " + storageState);
Toast toast = Toast.makeText(mActivity, R.string.storage_warning, Toast.LENGTH_LONG);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
}
}
BroadcastReceiver wifiReceiver = new BroadcastReceiver() {
public void onReceive(Context ctx, Intent intent) {
myLog.l(Log.DEBUG, "Wifi status broadcast received");
updateUi();
}
};
boolean requiredSettingsDefined() {
SharedPreferences settings = mActivity.getSharedPreferences(Defaults.getSettingsName(), Defaults.getSettingsMode());
String username = settings.getString("username", null);
String password = settings.getString("password", null);
if (username == null || password == null) {
return false;
} else {
return true;
}
}
/**
* Get the settings from the FTPServerService if it's running, otherwise
* load the settings directly from persistent storage.
*/
SharedPreferences getSettings() {
SharedPreferences settings = FTPServerService.getSettings();
if (settings != null) {
return settings;
} else {
return mActivity.getPreferences(Activity.MODE_PRIVATE);
}
}
}