Add project
19
src/Assets/AboutAssets.txt
Executable file
@ -0,0 +1,19 @@
|
|||||||
|
Any raw assets you want to be deployed with your application can be placed in
|
||||||
|
this directory (and child directories) and given a Build Action of "AndroidAsset".
|
||||||
|
|
||||||
|
These files will be deployed with your package and will be accessible using Android's
|
||||||
|
AssetManager, like this:
|
||||||
|
|
||||||
|
public class ReadAsset : Activity
|
||||||
|
{
|
||||||
|
protected override void OnCreate (Bundle bundle)
|
||||||
|
{
|
||||||
|
base.OnCreate (bundle);
|
||||||
|
|
||||||
|
InputStream input = Assets.Open ("my_asset.txt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Additionally, some Android functions will automatically load asset files:
|
||||||
|
|
||||||
|
Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf");
|
43
src/Connection.cs
Executable file
@ -0,0 +1,43 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
//using Android.App;
|
||||||
|
//using Android.Content;
|
||||||
|
//using Android.OS;
|
||||||
|
//using Android.Runtime;
|
||||||
|
//using Android.Views;
|
||||||
|
//using Android.Widget;
|
||||||
|
|
||||||
|
namespace TCPCommanderAndroid
|
||||||
|
{
|
||||||
|
public class TCP_Connection
|
||||||
|
{
|
||||||
|
private static TCP_Connection _TCP_instance;
|
||||||
|
public static TCP_Connection TCP_Instance
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_TCP_instance == null) _TCP_instance = new TCP_Connection();
|
||||||
|
return _TCP_instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public TcpClient client { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class UDP_Connection
|
||||||
|
{
|
||||||
|
private static UDP_Connection _UDP_instance;
|
||||||
|
public static UDP_Connection UDP_Instance
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_UDP_instance == null) _UDP_instance = new UDP_Connection();
|
||||||
|
return _UDP_instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public UdpClient client { get; set; }
|
||||||
|
}
|
||||||
|
}
|
442
src/FunctionsPage.cs
Executable file
@ -0,0 +1,442 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.NetworkInformation;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
using Android.App;
|
||||||
|
using Android.Content;
|
||||||
|
using Android.OS;
|
||||||
|
using Android.Runtime;
|
||||||
|
using Android.Views;
|
||||||
|
using Android.Widget;
|
||||||
|
|
||||||
|
namespace TCPCommanderAndroid
|
||||||
|
{
|
||||||
|
[Activity(Label = "FunctionsPage", ScreenOrientation = Android.Content.PM.ScreenOrientation.Portrait)]
|
||||||
|
public class FunctionsPage : Activity
|
||||||
|
{
|
||||||
|
public static string storedprivIP;
|
||||||
|
Show_Dialog dialog;
|
||||||
|
Button testButton;
|
||||||
|
Button pingButton;
|
||||||
|
Button shutdownButton;
|
||||||
|
Button monitorONButton;
|
||||||
|
Button monitorOFFButton;
|
||||||
|
Button screenshotButton;
|
||||||
|
Button PCLockButton;
|
||||||
|
//ImageView screenshotView;
|
||||||
|
Vibrator vibrator;
|
||||||
|
byte[] buffer = new byte[1];
|
||||||
|
System.Timers.Timer connectionTimer;
|
||||||
|
protected override void OnCreate(Bundle savedInstanceState)
|
||||||
|
{
|
||||||
|
base.OnCreate(savedInstanceState);
|
||||||
|
SetContentView(Resource.Layout.functions_page);
|
||||||
|
|
||||||
|
dialog = new Show_Dialog(this);
|
||||||
|
|
||||||
|
testButton = FindViewById<Button>(Resource.Id.testButton);
|
||||||
|
pingButton = FindViewById<Button>(Resource.Id.pingButton);
|
||||||
|
shutdownButton = FindViewById<Button>(Resource.Id.shutdownButton);
|
||||||
|
monitorONButton = FindViewById<Button>(Resource.Id.monitorONButton);
|
||||||
|
monitorOFFButton = FindViewById<Button>(Resource.Id.monitorOFFButton);
|
||||||
|
screenshotButton = FindViewById<Button>(Resource.Id.screenshotButton);
|
||||||
|
PCLockButton = FindViewById<Button>(Resource.Id.PCLockButton);
|
||||||
|
//screenshotView = FindViewById<ImageView>(Resource.Id.screenshotView);
|
||||||
|
vibrator = (Vibrator)GetSystemService(Context.VibratorService);
|
||||||
|
|
||||||
|
testButton.Click += Test_Clicked;
|
||||||
|
pingButton.Click += Ping_Clicked;
|
||||||
|
shutdownButton.Click += Shutdown_Clicked;
|
||||||
|
monitorONButton.Click += MonitorOn_Clicked;
|
||||||
|
monitorOFFButton.Click += MonitorOff_Clicked;
|
||||||
|
screenshotButton.Click += TakeScreenshot_Clicked;
|
||||||
|
PCLockButton.Click += PCLock_Clicked;
|
||||||
|
|
||||||
|
connectionTimer = new System.Timers.Timer();
|
||||||
|
connectionTimer.Interval = 1000;
|
||||||
|
connectionTimer.Enabled = true;
|
||||||
|
connectionTimer.Start();
|
||||||
|
connectionTimer.Elapsed += (object sender, System.Timers.ElapsedEventArgs e) =>
|
||||||
|
{
|
||||||
|
if (TCP_Connection.TCP_Instance.client != null)
|
||||||
|
{
|
||||||
|
if (MainActivity.clientIsOpen)
|
||||||
|
{
|
||||||
|
if (TCP_Connection.TCP_Instance.client.Client.Poll(0, SelectMode.SelectRead))
|
||||||
|
{
|
||||||
|
if (TCP_Connection.TCP_Instance.client.Client.Receive(buffer, SocketFlags.Peek) == 0)
|
||||||
|
{
|
||||||
|
//DisplayAlert("Client Disconnected", "Client Disconnected", "OK");
|
||||||
|
ClientDisconnected();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PCLockStatus;
|
||||||
|
protected override void OnResume()
|
||||||
|
{
|
||||||
|
base.OnResume();
|
||||||
|
|
||||||
|
if(MainActivity.alertSuccessfulConnection)
|
||||||
|
{
|
||||||
|
MainActivity.alertSuccessfulConnection = false;
|
||||||
|
dialog.ShowDialog("Connected", "Connected to server successfully!", false, Show_Dialog.MessageResult.OK);
|
||||||
|
writeMessage("{PC_LOCK_STATUS}");
|
||||||
|
string status = getDataAsString(TCP_Connection.TCP_Instance.client);
|
||||||
|
|
||||||
|
if (status.Contains("{PC_LOCK_STATUS}") && status.Contains("{/PC_LOCK_STATUS}"))
|
||||||
|
{
|
||||||
|
string result = getBetween(status, "{PC_LOCK_STATUS}", "{/PC_LOCK_STATUS}");
|
||||||
|
|
||||||
|
if (result.ToLower() == "true")
|
||||||
|
{
|
||||||
|
PCLockStatus = true;
|
||||||
|
PCLockButton.Text = "Lock Computer (Currently: Locked)";
|
||||||
|
}
|
||||||
|
else if (result.ToLower() == "false")
|
||||||
|
{
|
||||||
|
PCLockStatus = false;
|
||||||
|
PCLockButton.Text = "Lock Computer (Currently: Unlocked)";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
connectionTimer.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnPause()
|
||||||
|
{
|
||||||
|
base.OnPause();
|
||||||
|
|
||||||
|
connectionTimer.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async void OnBackPressed()
|
||||||
|
{
|
||||||
|
bool response = await dialog.ShowDialog("Are You Sure?", "Do you wan't to disconnect and go to the login page?", false, Show_Dialog.MessageResult.YES, Show_Dialog.MessageResult.NO) == Show_Dialog.MessageResult.YES ? true : false;
|
||||||
|
if (response)
|
||||||
|
{
|
||||||
|
TCP_Connection.TCP_Instance.client.GetStream().Close();
|
||||||
|
TCP_Connection.TCP_Instance.client.Close();
|
||||||
|
MainActivity.clientIsOpen = false;
|
||||||
|
MainActivity.succesfullyDisconnected = true;
|
||||||
|
//TryResumeActivity(typeof(MainActivity));
|
||||||
|
StartActivity(typeof(MainActivity));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClientDisconnected()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
TCP_Connection.TCP_Instance.client.Close();
|
||||||
|
TCP_Connection.TCP_Instance.client.GetStream().Close();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
if (MainActivity.analyticsEnabled)
|
||||||
|
{
|
||||||
|
MainActivity.developerExceptionList.Add(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
MainActivity.clientIsOpen = false;
|
||||||
|
MainActivity.lostConnection = true;
|
||||||
|
//TryResumeActivity(typeof(MainActivity));
|
||||||
|
StartActivity(typeof(MainActivity));
|
||||||
|
}
|
||||||
|
|
||||||
|
int vibrationTime = 500;
|
||||||
|
private void Test_Clicked(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
|
||||||
|
writeMessage("{TEST}");
|
||||||
|
|
||||||
|
string returnMessage = getDataAsString(TCP_Connection.TCP_Instance.client);
|
||||||
|
|
||||||
|
if (returnMessage == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (returnMessage == "{TEST_RESPOND}")
|
||||||
|
{
|
||||||
|
if (vibrator.HasVibrator)
|
||||||
|
{
|
||||||
|
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
|
||||||
|
{
|
||||||
|
vibrator.Vibrate(VibrationEffect.CreateOneShot(vibrationTime, 255));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vibrator.Vibrate(vibrationTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dialog.ShowDialog("Test Successful", "The server received the message and responded", false, Show_Dialog.MessageResult.OK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void Shutdown_Clicked(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
bool response = await dialog.ShowDialog("Shutdown System", "Are you sure you want to force shutdown your computer?", false, Show_Dialog.MessageResult.YES, Show_Dialog.MessageResult.NO) == Show_Dialog.MessageResult.YES ? true : false;
|
||||||
|
|
||||||
|
if (response)
|
||||||
|
{
|
||||||
|
writeMessage("{SHUTDOWN}");
|
||||||
|
|
||||||
|
string returnMessage = getDataAsString(TCP_Connection.TCP_Instance.client);
|
||||||
|
|
||||||
|
if (returnMessage == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (returnMessage == "{BEGAN_SHUTDOWN}")
|
||||||
|
{
|
||||||
|
await dialog.ShowDialog("Shutdown Successful", "The server has received the message and has begun shutdown", false, Show_Dialog.MessageResult.OK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MonitorOn_Clicked(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
writeMessage("{MONITOR_ON}");
|
||||||
|
|
||||||
|
string returnMessage = getDataAsString(TCP_Connection.TCP_Instance.client);
|
||||||
|
|
||||||
|
if (returnMessage == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (returnMessage == "{MONITOR_TURNED_ON}")
|
||||||
|
{
|
||||||
|
dialog.ShowDialog("Display Settings", "The server has received the message and has turned the monitor on", false, Show_Dialog.MessageResult.OK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MonitorOff_Clicked(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
writeMessage("{MONITOR_OFF}");
|
||||||
|
|
||||||
|
string returnMessage = getDataAsString(TCP_Connection.TCP_Instance.client);
|
||||||
|
|
||||||
|
if (returnMessage == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (returnMessage == "{MONITOR_TURNED_OFF}")
|
||||||
|
{
|
||||||
|
dialog.ShowDialog("Display Settings", "The server has received the message and has turned the monitor off", false, Show_Dialog.MessageResult.OK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TakeScreenshot_Clicked(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
StartActivity(typeof(PicturePage));
|
||||||
|
writeMessage("{TAKE_SCREENSHOT}");
|
||||||
|
|
||||||
|
//var data = getData(Connection.Instance.client);
|
||||||
|
|
||||||
|
//if (data == null)
|
||||||
|
//{
|
||||||
|
// return;
|
||||||
|
//}
|
||||||
|
|
||||||
|
//screenshotView.SetImageBitmap(Android.Graphics.Bitmap.CreateBitmap(Android.Graphics.BitmapFactory.DecodeByteArray(data, 0, data.Length)));//ImageSource.FromStream(() => new MemoryStream(data));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void PCLock_Clicked(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (PCLockStatus)
|
||||||
|
{
|
||||||
|
bool response = await dialog.ShowDialog("Unlock PC?", "Are you sure you want to unlock your computer?", false, Show_Dialog.MessageResult.YES, Show_Dialog.MessageResult.NO) == Show_Dialog.MessageResult.YES ? true : false;
|
||||||
|
|
||||||
|
if (response)
|
||||||
|
{
|
||||||
|
writeMessage("{LOCK_PC}");
|
||||||
|
|
||||||
|
if (getDataAsString(TCP_Connection.TCP_Instance.client) == "{PC_LOCKED}")
|
||||||
|
{
|
||||||
|
dialog.ShowDialog("Unlock Successful", "The Computer Recieved your PC Unlock Message", false, Show_Dialog.MessageResult.OK);
|
||||||
|
PCLockStatus = !PCLockStatus;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dialog.ShowDialog("Unlock PC Cancelled", "Your PC Unlock Attempt was Cancelled", false, Show_Dialog.MessageResult.OK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool response = await dialog.ShowDialog("Lock PC?", "Are you sure you want to lock your computer?", false, Show_Dialog.MessageResult.YES, Show_Dialog.MessageResult.NO) == Show_Dialog.MessageResult.YES ? true : false;
|
||||||
|
|
||||||
|
if (response)
|
||||||
|
{
|
||||||
|
writeMessage("{LOCK_PC}");
|
||||||
|
|
||||||
|
if (getDataAsString(TCP_Connection.TCP_Instance.client) == "{PC_LOCKED}")
|
||||||
|
{
|
||||||
|
dialog.ShowDialog("Lock Successful", "The Computer Recieved your PC Lock Message", false, Show_Dialog.MessageResult.OK);
|
||||||
|
PCLockStatus = !PCLockStatus;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dialog.ShowDialog("Lock PC Cancelled", "Your PC Lock Attempt was Cancelled", false, Show_Dialog.MessageResult.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PCLockStatus)
|
||||||
|
{
|
||||||
|
PCLockButton.Text = "Lock Computer (Currently: Locked)";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PCLockButton.Text = "Lock Computer (Currently: Unlocked)";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Stopwatch swr = new Stopwatch();
|
||||||
|
Stopwatch sww = new Stopwatch();
|
||||||
|
private void Ping_Clicked(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
string information = "Write : Read";
|
||||||
|
for (int i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
sww.Reset();
|
||||||
|
sww.Start();
|
||||||
|
|
||||||
|
//writeMessage("{SPEED_TEST}" + kbbuffer.ToString() + "{/SPEED_TEST}");
|
||||||
|
sww.Stop();
|
||||||
|
//int actualReadBytes = Encoding.UTF8.GetBytes("{SPEED_TEST}" + kbbuffer.ToString() + "{/SPEED_TEST}").Length;
|
||||||
|
//long speedWrite = (actualReadBytes * 8) / (int)sww.ElapsedMilliseconds;
|
||||||
|
|
||||||
|
//information += speedWrite + "mbps";
|
||||||
|
|
||||||
|
swr.Reset();
|
||||||
|
swr.Start();
|
||||||
|
int byteLength = getData(TCP_Connection.TCP_Instance.client).Length;
|
||||||
|
swr.Stop();
|
||||||
|
long speedRead = (byteLength * 8) / (int)swr.ElapsedMilliseconds;
|
||||||
|
|
||||||
|
information += " : " + speedRead + "mbps\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog.ShowDialog("Speed Test", information, false, Show_Dialog.MessageResult.OK);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TryResumeActivity(Type className)
|
||||||
|
{
|
||||||
|
Intent openActivity = new Intent(this, className);
|
||||||
|
openActivity.SetFlags(ActivityFlags.ReorderToFront);
|
||||||
|
StartActivityIfNeeded(openActivity, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public /*async*/ void writeMessage(string input)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
TcpClient client = TCP_Connection.TCP_Instance.client;
|
||||||
|
if (client == null)
|
||||||
|
{
|
||||||
|
throw new ObjectDisposedException(client.ToString());
|
||||||
|
}
|
||||||
|
NetworkStream ns = client.GetStream();
|
||||||
|
byte[] message = Encoding.ASCII.GetBytes(input);
|
||||||
|
ns.Write(message, 0, message.Length);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
if (MainActivity.analyticsEnabled)
|
||||||
|
{
|
||||||
|
MainActivity.developerExceptionList.Add(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
//await dialog.ShowDialog("Error", ex.ToString(), false, Show_Dialog.MessageResult.OK);
|
||||||
|
ClientDisconnected();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string getDataAsString(TcpClient client)
|
||||||
|
{
|
||||||
|
byte[] bytes = getData(client);
|
||||||
|
if (bytes != null)
|
||||||
|
{
|
||||||
|
return Encoding.ASCII.GetString(bytes);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getData(TcpClient client)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
NetworkStream stream = client.GetStream();
|
||||||
|
byte[] fileSizeBytes = new byte[4];
|
||||||
|
int bytes = stream.Read(fileSizeBytes, 0, fileSizeBytes.Length);
|
||||||
|
int dataLength = BitConverter.ToInt32(fileSizeBytes, 0);
|
||||||
|
|
||||||
|
int bytesLeft = dataLength;
|
||||||
|
byte[] data = new byte[dataLength];
|
||||||
|
|
||||||
|
int buffersize = 1024;
|
||||||
|
int bytesRead = 0;
|
||||||
|
|
||||||
|
while (bytesLeft > 0)
|
||||||
|
{
|
||||||
|
int curDataSize = Math.Min(buffersize, bytesLeft);
|
||||||
|
if (client.Available < curDataSize)
|
||||||
|
{
|
||||||
|
curDataSize = client.Available;
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes = stream.Read(data, bytesRead, curDataSize);
|
||||||
|
bytesRead += curDataSize;
|
||||||
|
bytesLeft -= curDataSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
if (MainActivity.analyticsEnabled)
|
||||||
|
{
|
||||||
|
MainActivity.developerExceptionList.Add(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
//dialog.ShowDialog("Error", ex.ToString(), false, Show_Dialog.MessageResult.OK);
|
||||||
|
ClientDisconnected();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string getBetween(string strSource, string strStart, string strEnd)
|
||||||
|
{
|
||||||
|
int Start, End;
|
||||||
|
if (strSource.Contains(strStart) && strSource.Contains(strEnd))
|
||||||
|
{
|
||||||
|
Start = strSource.IndexOf(strStart, 0) + strStart.Length;
|
||||||
|
End = strSource.IndexOf(strEnd, Start);
|
||||||
|
return strSource.Substring(Start, End - Start);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
403
src/MainActivity.cs
Executable file
@ -0,0 +1,403 @@
|
|||||||
|
using Android.App;
|
||||||
|
using Android.OS;
|
||||||
|
using Android.Support.V7.App;
|
||||||
|
using Android.Runtime;
|
||||||
|
using Android.Widget;
|
||||||
|
using System.IO;
|
||||||
|
using System.Xml.Serialization;
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using AlertDialog = Android.App.AlertDialog;
|
||||||
|
using Android.Content;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
//using Java.Lang;
|
||||||
|
using System.Threading;
|
||||||
|
using Android.Views;
|
||||||
|
using Android.Views.InputMethods;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace TCPCommanderAndroid
|
||||||
|
{
|
||||||
|
[Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true, ScreenOrientation = Android.Content.PM.ScreenOrientation.Portrait)]
|
||||||
|
public class MainActivity : AppCompatActivity
|
||||||
|
{
|
||||||
|
byte[] buffer = new byte[1];
|
||||||
|
string folderPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
|
||||||
|
string preferencesFile = "/prefs.xml";
|
||||||
|
bool prefsExist;
|
||||||
|
|
||||||
|
EditText ipAddress;
|
||||||
|
EditText TCP_Port;
|
||||||
|
EditText UDP_Port;
|
||||||
|
Button connectButton;
|
||||||
|
StoredData readStoredData;
|
||||||
|
CheckBox developeranalyticsmodeCheck;
|
||||||
|
public static bool succesfullyDisconnected;
|
||||||
|
public static bool clientIsOpen;
|
||||||
|
public static bool lostConnection;
|
||||||
|
public static bool alertSuccessfulConnection;
|
||||||
|
public static bool analyticsEnabled;
|
||||||
|
//public bool readFile;
|
||||||
|
Show_Dialog dialog;
|
||||||
|
|
||||||
|
public static List<Exception> developerExceptionList = new List<Exception>();
|
||||||
|
protected override void OnCreate(Bundle savedInstanceState)
|
||||||
|
{
|
||||||
|
base.OnCreate(savedInstanceState);
|
||||||
|
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
|
||||||
|
// Set our view from the "main" layout resource
|
||||||
|
SetContentView(Resource.Layout.activity_main);
|
||||||
|
|
||||||
|
dialog = new Show_Dialog(this);
|
||||||
|
|
||||||
|
ipAddress = FindViewById<EditText>(Resource.Id.ipAddress);
|
||||||
|
TCP_Port = FindViewById<EditText>(Resource.Id.TCP_Port);
|
||||||
|
UDP_Port = FindViewById<EditText>(Resource.Id.UDP_Port);
|
||||||
|
connectButton = FindViewById<Button>(Resource.Id.connectButton);
|
||||||
|
developeranalyticsmodeCheck = FindViewById<CheckBox>(Resource.Id.developeranalyticsmodeCheck);
|
||||||
|
developeranalyticsmodeCheck.CheckedChange += Analytics_Checked;
|
||||||
|
|
||||||
|
ipAddress.EditorAction += HandleEditorAction;
|
||||||
|
TCP_Port.EditorAction += HandleEditorAction;
|
||||||
|
UDP_Port.EditorAction += HandleEditorAction;
|
||||||
|
|
||||||
|
ipAddress.TextChanged += IPAddress_TextChanged;
|
||||||
|
connectButton.Click += Connect_Clicked;
|
||||||
|
//Port.TextChanged += Port_TextChanged;
|
||||||
|
|
||||||
|
|
||||||
|
if (Directory.GetFiles(folderPath).Length > 0)
|
||||||
|
{
|
||||||
|
if (File.Exists(folderPath + preferencesFile))
|
||||||
|
{
|
||||||
|
prefsExist = true;
|
||||||
|
XmlSerializer Serializer = new XmlSerializer(typeof(StoredData));
|
||||||
|
FileStream fs = new FileStream(folderPath + preferencesFile, FileMode.Open);
|
||||||
|
readStoredData = (StoredData)Serializer.Deserialize(fs);
|
||||||
|
ipAddress.Text = readStoredData.PrivateIPV4;
|
||||||
|
TCP_Port.Text = readStoredData.TCP_Port;
|
||||||
|
UDP_Port.Text = readStoredData.UDP_Port;
|
||||||
|
fs.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async override void OnBackPressed()
|
||||||
|
{
|
||||||
|
bool response = await dialog.ShowDialog("Quit?", "Would you like to close the application?", false, Show_Dialog.MessageResult.YES, Show_Dialog.MessageResult.NO) == Show_Dialog.MessageResult.YES ? true : false;
|
||||||
|
|
||||||
|
if (response)
|
||||||
|
{
|
||||||
|
Android.OS.Process.KillProcess(Android.OS.Process.MyPid());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async override void OnResume()
|
||||||
|
{
|
||||||
|
developeranalyticsmodeCheck.Checked = analyticsEnabled;
|
||||||
|
|
||||||
|
base.OnResume();
|
||||||
|
|
||||||
|
if (succesfullyDisconnected)
|
||||||
|
{
|
||||||
|
lockButton(true, 0);
|
||||||
|
succesfullyDisconnected = false;
|
||||||
|
dialog.ShowDialog("Disconnection", "Succesfully disconnected from server!", false, Show_Dialog.MessageResult.OK);
|
||||||
|
await Task.Delay(1000);
|
||||||
|
lockButton(false, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (lostConnection)
|
||||||
|
{
|
||||||
|
lostConnection = false;
|
||||||
|
lockButton(true, 0);
|
||||||
|
await Task.Delay(1000);
|
||||||
|
lockButton(false, 0);
|
||||||
|
ConnectionLost();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (analyticsEnabled)
|
||||||
|
{
|
||||||
|
if (developerExceptionList.Count > 0)
|
||||||
|
{
|
||||||
|
bool response = await dialog.ShowDialog("Developer Analytics Mode", "Would you like to see all the previous error messages?", false, Show_Dialog.MessageResult.YES, Show_Dialog.MessageResult.NO) == Show_Dialog.MessageResult.YES ? true : false;
|
||||||
|
|
||||||
|
if (response)
|
||||||
|
{
|
||||||
|
string errorList = "";
|
||||||
|
for (int i = 0; i < developerExceptionList.Count; i++)
|
||||||
|
{
|
||||||
|
errorList += developerExceptionList[i].GetType().ToString() + ":\n" + developerExceptionList[i].Message + "\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
await dialog.ShowDialog("Errors Caught: (" + developerExceptionList.Count + ")", errorList, false, Show_Dialog.MessageResult.OK);
|
||||||
|
developerExceptionList.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected override void OnPause()
|
||||||
|
{
|
||||||
|
base.OnPause();
|
||||||
|
if (clientIsOpen)
|
||||||
|
{
|
||||||
|
lockButton(true, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async void ConnectionLost()
|
||||||
|
{
|
||||||
|
bool response = await dialog.ShowDialog("Connection Lost", "The client has lost connection to the server.\nWould you like to reconnect?", false, Show_Dialog.MessageResult.YES, Show_Dialog.MessageResult.NO) == Show_Dialog.MessageResult.YES ? true : false;
|
||||||
|
|
||||||
|
if (response)
|
||||||
|
{
|
||||||
|
Connect_Clicked(new object(), new EventArgs());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public async void lockButton(bool locked, int timeout)
|
||||||
|
{
|
||||||
|
if (timeout > 0)
|
||||||
|
{
|
||||||
|
await Task.Delay(timeout);
|
||||||
|
}
|
||||||
|
new Handler(MainLooper).Post(new Java.Lang.Runnable(() =>
|
||||||
|
{
|
||||||
|
connectButton.Enabled = !locked;
|
||||||
|
connectButton.Clickable = !locked;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
int tryConnectTime = 1000;
|
||||||
|
public async Task<TcpClient> tryConnect()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (client == null)
|
||||||
|
{
|
||||||
|
client = new TcpClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
var connectionTask = client.ConnectAsync(ipAddress.Text, Convert.ToInt32(TCP_Port.Text)).ContinueWith(task =>
|
||||||
|
{
|
||||||
|
return task.IsFaulted ? null : client;
|
||||||
|
}, TaskContinuationOptions.ExecuteSynchronously);
|
||||||
|
var timeoutTask = Task.Delay(tryConnectTime).ContinueWith<TcpClient>(task => null, TaskContinuationOptions.ExecuteSynchronously);
|
||||||
|
var resultTask = Task.WhenAny(connectionTask, timeoutTask).Unwrap();
|
||||||
|
resultTask.Wait();
|
||||||
|
var resultTcpClient = await resultTask;
|
||||||
|
|
||||||
|
return resultTcpClient;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
if (analyticsEnabled)
|
||||||
|
{
|
||||||
|
developerExceptionList.Add(ex);
|
||||||
|
}
|
||||||
|
await dialog.ShowDialog("Error", ex.ToString(), false, Show_Dialog.MessageResult.OK);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void MasterConnection()
|
||||||
|
{
|
||||||
|
lockButton(true, 0);
|
||||||
|
client = tryConnect().Result;
|
||||||
|
lockButton(false, 250);
|
||||||
|
}
|
||||||
|
|
||||||
|
TcpClient client = new TcpClient();
|
||||||
|
private async void Connect_Clicked(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (ipAddress.Text == "" || TCP_Port.Text == "" || UDP_Port.Text == "")
|
||||||
|
{
|
||||||
|
await dialog.ShowDialog("Error", "The IPAddress or Ports was blank!", false, Show_Dialog.MessageResult.OK);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
MasterConnection();
|
||||||
|
|
||||||
|
if (client != null)
|
||||||
|
{
|
||||||
|
clientIsOpen = true;
|
||||||
|
TCP_Connection.TCP_Instance.client = client;
|
||||||
|
//TryResumeActivity(typeof(FunctionsPage));
|
||||||
|
StartActivity(typeof(FunctionsPage));
|
||||||
|
|
||||||
|
alertSuccessfulConnection = true;
|
||||||
|
FunctionsPage.storedprivIP = ipAddress.Text;
|
||||||
|
|
||||||
|
if (!prefsExist || ipAddress.Text != readStoredData.PrivateIPV4 || TCP_Port.Text != readStoredData.TCP_Port || UDP_Port.Text != readStoredData.UDP_Port)
|
||||||
|
{
|
||||||
|
XmlSerializer Serializer = new XmlSerializer(typeof(StoredData));
|
||||||
|
StoredData SD = new StoredData();
|
||||||
|
SD.PrivateIPV4 = ipAddress.Text;
|
||||||
|
SD.TCP_Port = TCP_Port.Text;
|
||||||
|
SD.UDP_Port = UDP_Port.Text;
|
||||||
|
|
||||||
|
TextWriter Writer = new StreamWriter(folderPath + preferencesFile);
|
||||||
|
Serializer.Serialize(Writer, SD);
|
||||||
|
Writer.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
clientIsOpen = false;
|
||||||
|
bool reconnect = await dialog.ShowDialog("Connection Unsuccessful", "Could not connect to the server!\nWould you like to try to reconnect?", false, Show_Dialog.MessageResult.YES, Show_Dialog.MessageResult.NO) == Show_Dialog.MessageResult.YES ? true : false;
|
||||||
|
if (reconnect)
|
||||||
|
{
|
||||||
|
Connect_Clicked(new object(), new EventArgs());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
if (analyticsEnabled)
|
||||||
|
{
|
||||||
|
developerExceptionList.Add(ex);
|
||||||
|
}
|
||||||
|
await dialog.ShowDialog("Error", ex.ToString(), false, Show_Dialog.MessageResult.OK);
|
||||||
|
clientIsOpen = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void IPAddress_TextChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
//ipAddress.Text.RemoveLetters();
|
||||||
|
//ipAddress.Text.RemoveSpecialChars();
|
||||||
|
|
||||||
|
//if (Regex.IsMatch(ipAddress.Text, @"[^0-9.]"))
|
||||||
|
//{
|
||||||
|
// ipAddress.Text = Regex.Replace(ipAddress.Text, @"[^0-9.]", string.Empty);
|
||||||
|
// ipAddressIgnoreChange = true;
|
||||||
|
//}
|
||||||
|
|
||||||
|
if (ipAddress.Text.Contains(".."))
|
||||||
|
{
|
||||||
|
int location = ipAddress.Text.IndexOf("..");
|
||||||
|
ipAddress.Text = ipAddress.Text.Replace("..", ".");
|
||||||
|
ipAddress.SetSelection(location + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TryResumeActivity(Type className)
|
||||||
|
{
|
||||||
|
Intent openActivity = new Intent(this, className);
|
||||||
|
openActivity.SetFlags(ActivityFlags.ReorderToFront);
|
||||||
|
StartActivityIfNeeded(openActivity, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleEditorAction(object sender, TextView.EditorActionEventArgs e)
|
||||||
|
{
|
||||||
|
e.Handled = false;
|
||||||
|
if (e.ActionId == ImeAction.Next)
|
||||||
|
{
|
||||||
|
EditText etSender = ((EditText)sender);
|
||||||
|
if (etSender.Hint == "IP Address")
|
||||||
|
{
|
||||||
|
TCP_Port.RequestFocus();
|
||||||
|
TCP_Port.SetSelection(TCP_Port.Text.Length);
|
||||||
|
}
|
||||||
|
else if (etSender.Hint == "TCP Port")
|
||||||
|
{
|
||||||
|
UDP_Port.RequestFocus();
|
||||||
|
UDP_Port.SetSelection(UDP_Port.Text.Length);
|
||||||
|
}
|
||||||
|
} else if (e.ActionId == ImeAction.Go)
|
||||||
|
{
|
||||||
|
InputMethodManager IM = (InputMethodManager)GetSystemService(Context.InputMethodService);
|
||||||
|
IM.HideSoftInputFromWindow(UDP_Port.WindowToken, 0);
|
||||||
|
UDP_Port.ClearFocus();
|
||||||
|
connectButton.PerformClick();
|
||||||
|
}
|
||||||
|
e.Handled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Analytics_Checked(object sender, CompoundButton.CheckedChangeEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.IsChecked)
|
||||||
|
{
|
||||||
|
analyticsEnabled = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
analyticsEnabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
|
||||||
|
{
|
||||||
|
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||||
|
|
||||||
|
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class StoredData
|
||||||
|
{
|
||||||
|
public string PrivateIPV4;
|
||||||
|
public string TCP_Port;
|
||||||
|
public string UDP_Port;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Show_Dialog
|
||||||
|
{
|
||||||
|
|
||||||
|
public enum MessageResult
|
||||||
|
{
|
||||||
|
NONE = 0,
|
||||||
|
OK = 1,
|
||||||
|
CANCEL = 2,
|
||||||
|
ABORT = 3,
|
||||||
|
RETRY = 4,
|
||||||
|
IGNORE = 5,
|
||||||
|
YES = 6,
|
||||||
|
NO = 7
|
||||||
|
}
|
||||||
|
|
||||||
|
Activity mcontext;
|
||||||
|
public Show_Dialog(Activity activity) : base()
|
||||||
|
{
|
||||||
|
this.mcontext = activity;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public Task<MessageResult> ShowDialog(string Title, string Message, bool SetCancelable = false, /*bool SetInverseBackgroundForced = false,*/ MessageResult PositiveButton = MessageResult.OK, MessageResult NegativeButton = MessageResult.NONE, MessageResult NeutralButton = MessageResult.NONE, int IconAttribute = Android.Resource.Attribute.AlertDialogIcon)
|
||||||
|
{
|
||||||
|
var tcs = new TaskCompletionSource<MessageResult>();
|
||||||
|
|
||||||
|
var builder = new AlertDialog.Builder(mcontext);
|
||||||
|
builder.SetIconAttribute(IconAttribute);
|
||||||
|
builder.SetTitle(Title);
|
||||||
|
builder.SetMessage(Message);
|
||||||
|
//builder.SetInverseBackgroundForced(SetInverseBackgroundForced);
|
||||||
|
builder.SetCancelable(SetCancelable);
|
||||||
|
|
||||||
|
builder.SetPositiveButton((PositiveButton != MessageResult.NONE) ? PositiveButton.ToString() : string.Empty, (senderAlert, args) =>
|
||||||
|
{
|
||||||
|
tcs.SetResult(PositiveButton);
|
||||||
|
});
|
||||||
|
builder.SetNegativeButton((NegativeButton != MessageResult.NONE) ? NegativeButton.ToString() : string.Empty, delegate
|
||||||
|
{
|
||||||
|
tcs.SetResult(NegativeButton);
|
||||||
|
});
|
||||||
|
builder.SetNeutralButton((NeutralButton != MessageResult.NONE) ? NeutralButton.ToString() : string.Empty, delegate
|
||||||
|
{
|
||||||
|
tcs.SetResult(NeutralButton);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
builder.Show();
|
||||||
|
|
||||||
|
return tcs.Task;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
7
src/Properties/AndroidManifest.xml
Executable file
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.companyname.tcpcommanderandroid" android:installLocation="auto">
|
||||||
|
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28" />
|
||||||
|
<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"></application>
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.VIBRATE" />
|
||||||
|
</manifest>
|
30
src/Properties/AssemblyInfo.cs
Executable file
@ -0,0 +1,30 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using Android.App;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
[assembly: AssemblyTitle("TCPCommanderAndroid")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("")]
|
||||||
|
[assembly: AssemblyProduct("TCPCommanderAndroid")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright © 2018")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
|
// by using the '*' as shown below:
|
||||||
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
|
[assembly: AssemblyVersion("1.0.0.0")]
|
||||||
|
[assembly: AssemblyFileVersion("1.0.0.0")]
|
44
src/Resources/AboutResources.txt
Executable file
@ -0,0 +1,44 @@
|
|||||||
|
Images, layout descriptions, binary blobs and string dictionaries can be included
|
||||||
|
in your application as resource files. Various Android APIs are designed to
|
||||||
|
operate on the resource IDs instead of dealing with images, strings or binary blobs
|
||||||
|
directly.
|
||||||
|
|
||||||
|
For example, a sample Android app that contains a user interface layout (main.xml),
|
||||||
|
an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png)
|
||||||
|
would keep its resources in the "Resources" directory of the application:
|
||||||
|
|
||||||
|
Resources/
|
||||||
|
drawable/
|
||||||
|
icon.png
|
||||||
|
|
||||||
|
layout/
|
||||||
|
main.xml
|
||||||
|
|
||||||
|
values/
|
||||||
|
strings.xml
|
||||||
|
|
||||||
|
In order to get the build system to recognize Android resources, set the build action to
|
||||||
|
"AndroidResource". The native Android APIs do not operate directly with filenames, but
|
||||||
|
instead operate on resource IDs. When you compile an Android application that uses resources,
|
||||||
|
the build system will package the resources for distribution and generate a class called "R"
|
||||||
|
(this is an Android convention) that contains the tokens for each one of the resources
|
||||||
|
included. For example, for the above Resources layout, this is what the R class would expose:
|
||||||
|
|
||||||
|
public class R {
|
||||||
|
public class drawable {
|
||||||
|
public const int icon = 0x123;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class layout {
|
||||||
|
public const int main = 0x456;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class strings {
|
||||||
|
public const int first_string = 0xabc;
|
||||||
|
public const int second_string = 0xbcd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main
|
||||||
|
to reference the layout/main.xml file, or R.strings.first_string to reference the first
|
||||||
|
string in the dictionary file values/strings.xml.
|
8781
src/Resources/Resource.designer.cs
generated
Executable file
447
src/Resources/layout/PicturePage.cs
Executable file
@ -0,0 +1,447 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Android.App;
|
||||||
|
using Android.Content;
|
||||||
|
using Android.Graphics;
|
||||||
|
using Android.OS;
|
||||||
|
using Android.Runtime;
|
||||||
|
using Android.Views;
|
||||||
|
using Android.Widget;
|
||||||
|
|
||||||
|
namespace TCPCommanderAndroid
|
||||||
|
{
|
||||||
|
[Activity(Label = "PicturePage", ScreenOrientation = Android.Content.PM.ScreenOrientation.Landscape)]
|
||||||
|
public class PicturePage : Activity
|
||||||
|
{
|
||||||
|
ImageView screenshotView;
|
||||||
|
Show_Dialog dialog;
|
||||||
|
LinearLayout linearlayout;
|
||||||
|
public bool startingUp;
|
||||||
|
protected async override void OnCreate(Bundle savedInstanceState)
|
||||||
|
{
|
||||||
|
base.OnCreate(savedInstanceState);
|
||||||
|
|
||||||
|
EnterImmersiveMode();
|
||||||
|
SetContentView(Resource.Layout.picture_page);
|
||||||
|
//screenshotView = FindViewById<ImageView>(Resource.Id.screenshotView);
|
||||||
|
screenshotView = new ImageView(this);//new ImageViewExt(this);//new ImageView(this); //ADD IMAGEVIEWEXT(THIS); LATER
|
||||||
|
linearlayout = FindViewById<LinearLayout>(Resource.Id.picturepageLinearLayout);
|
||||||
|
//screenshotView.SetBackgroundColor(Color.Black);
|
||||||
|
//screenshotView.SetBackgroundColor(Color.White);
|
||||||
|
dialog = new Show_Dialog(this);
|
||||||
|
|
||||||
|
screenshotView.LayoutParameters = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.MatchParent);//(bitmap.Width, bitmap.Height);
|
||||||
|
|
||||||
|
//if (Build.VERSION.SdkInt < BuildVersionCodes.JellyBean)
|
||||||
|
//{
|
||||||
|
//RequestWindowFeature(WindowFeatures.NoTitle);
|
||||||
|
//Window.SetFlags(WindowManagerFlags.Fullscreen, WindowManagerFlags.Fullscreen);
|
||||||
|
//}
|
||||||
|
//else
|
||||||
|
//{
|
||||||
|
// Window.DecorView.SystemUiVisibility = StatusBarVisibility.Hidden;
|
||||||
|
// //ActionBar.Hide();
|
||||||
|
//}
|
||||||
|
|
||||||
|
//PowerManager pm = (PowerManager)GetSystemService(Context.PowerService);
|
||||||
|
//PowerManager.WakeLock wl = pm.NewWakeLock(WakeLockFlags.ScreenDim, "ScreenDim");
|
||||||
|
//wl.Acquire();
|
||||||
|
this.Window.AddFlags(WindowManagerFlags.KeepScreenOn);
|
||||||
|
|
||||||
|
linearlayout.AddView(screenshotView);
|
||||||
|
|
||||||
|
|
||||||
|
//timer = new System.Timers.Timer();
|
||||||
|
//timer.Interval = 1000;
|
||||||
|
//timer.Enabled = true;
|
||||||
|
startingUp = true;
|
||||||
|
await Task.Delay(500); //may be too much time
|
||||||
|
startingUp = false;
|
||||||
|
//timer.Start();
|
||||||
|
//timer.Elapsed += (sender, e) =>
|
||||||
|
//{
|
||||||
|
ReplaceImage();
|
||||||
|
//};
|
||||||
|
}
|
||||||
|
|
||||||
|
public void EnterImmersiveMode()
|
||||||
|
{
|
||||||
|
int uiOptions = (int)Window.DecorView.SystemUiVisibility;
|
||||||
|
//uiOptions |= (int)SystemUiFlags.LowProfile;
|
||||||
|
uiOptions |= (int)SystemUiFlags.Fullscreen;
|
||||||
|
uiOptions |= (int)SystemUiFlags.HideNavigation;
|
||||||
|
uiOptions |= (int)SystemUiFlags.ImmersiveSticky;
|
||||||
|
Window.DecorView.SystemUiVisibility = (StatusBarVisibility)uiOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
//System.Timers.Timer timer;
|
||||||
|
protected override void OnResume() //WASTED 3 HOURS BECAUSE OF picture_page.xml's LINEARLAYOUT HAD android:foreground="@android:color/black"!!!! FIXED NOW
|
||||||
|
{
|
||||||
|
base.OnResume();
|
||||||
|
|
||||||
|
//screenshotView.Enabled = true;
|
||||||
|
//screenshotView.Visibility = ViewStates.Visible;
|
||||||
|
//screenshotView.RequestLayout();
|
||||||
|
|
||||||
|
//linearlayout.BringChildToFront(screenshotView);
|
||||||
|
|
||||||
|
if (!startingUp)
|
||||||
|
{
|
||||||
|
//timer.Start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool happenedOnce;
|
||||||
|
bool happenedTwice;
|
||||||
|
string part1;
|
||||||
|
string part2;
|
||||||
|
bool initiated;
|
||||||
|
byte[] data;
|
||||||
|
public async void ReplaceImage()
|
||||||
|
{
|
||||||
|
//if (!happenedOnce)
|
||||||
|
//{
|
||||||
|
// part1 = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff");
|
||||||
|
// happenedOnce = true;
|
||||||
|
//}
|
||||||
|
//else
|
||||||
|
//{
|
||||||
|
// part2 = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff");
|
||||||
|
// await Task.Run(() => RunOnUiThread(async () =>
|
||||||
|
// {
|
||||||
|
// await dialog.ShowDialog("Time Taken", part1 + " : " + part2, false, Show_Dialog.MessageResult.OK);
|
||||||
|
// }));
|
||||||
|
//}
|
||||||
|
|
||||||
|
await Task.Run(() => askForScreenshot());
|
||||||
|
data = await Task.Run(() => getScreenshot(TCP_Connection.TCP_Instance.client));
|
||||||
|
initiated = true;
|
||||||
|
|
||||||
|
if (data == null)
|
||||||
|
{
|
||||||
|
await Task.Run(() => ReplaceImage());
|
||||||
|
}
|
||||||
|
|
||||||
|
await Task.Run(() => RunOnUiThread(() =>
|
||||||
|
{
|
||||||
|
//screenshotView.setimage
|
||||||
|
screenshotView.SetImageBitmap(Android.Graphics.Bitmap.CreateBitmap(Android.Graphics.BitmapFactory.DecodeByteArray(data, 0, data.Length)));//ImageSource.FromStream(() => new MemoryStream(data));
|
||||||
|
//await dialog.ShowDialog("Data Received", "Bytes: " + data.Length, false, Show_Dialog.MessageResult.OK);
|
||||||
|
}));
|
||||||
|
//if (!happenedTwice)
|
||||||
|
//{
|
||||||
|
// happenedTwice = true;
|
||||||
|
await Task.Run(() => ReplaceImage());
|
||||||
|
//}
|
||||||
|
|
||||||
|
//string part1 = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff");
|
||||||
|
//if (!Java.Lang.Thread.Interrupted())
|
||||||
|
//{
|
||||||
|
//RunOnUiThread(() =>
|
||||||
|
//{
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
|
||||||
|
// screenshotView.SetImageBitmap(Android.Graphics.Bitmap.CreateBitmap(Android.Graphics.BitmapFactory.DecodeByteArray(data, 0, data.Length)));//ImageSource.FromStream(() => new MemoryStream(data));
|
||||||
|
// }
|
||||||
|
// catch (Exception ex)
|
||||||
|
// {
|
||||||
|
// dialog.ShowDialog("Error", ex.GetType().ToString() + ": " + ex.Message, false, Show_Dialog.MessageResult.OK);
|
||||||
|
// }
|
||||||
|
//});
|
||||||
|
//}
|
||||||
|
//string part2 = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff");
|
||||||
|
|
||||||
|
//dialog.ShowDialog("Times", "Started at: " + part1 + "\nEnded at: " + part2, false, Show_Dialog.MessageResult.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnPause()
|
||||||
|
{
|
||||||
|
base.OnPause();
|
||||||
|
|
||||||
|
//timer.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClientDisconnected()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
TCP_Connection.TCP_Instance.client.Close();
|
||||||
|
TCP_Connection.TCP_Instance.client.GetStream().Close();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
if (MainActivity.analyticsEnabled)
|
||||||
|
{
|
||||||
|
MainActivity.developerExceptionList.Add(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
MainActivity.clientIsOpen = false;
|
||||||
|
MainActivity.lostConnection = true;
|
||||||
|
//TryResumeActivity(typeof(MainActivity));
|
||||||
|
StartActivity(typeof(MainActivity));
|
||||||
|
}
|
||||||
|
|
||||||
|
//public async Task<byte[]> getScreenshot(TcpClient client)
|
||||||
|
//{
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
// NetworkStream stream = client.GetStream();
|
||||||
|
// byte[] fileSizeBytes = new byte[4];
|
||||||
|
// int bytes = stream.Read(fileSizeBytes, 0, fileSizeBytes.Length);
|
||||||
|
// int dataLength = BitConverter.ToInt32(fileSizeBytes, 0);
|
||||||
|
|
||||||
|
// int bytesLeft = dataLength;
|
||||||
|
// byte[] data = new byte[dataLength]; //System.OverflowException: 'Arithmetic operation resulted in an overflow.' KEEP HAPPENING
|
||||||
|
|
||||||
|
// int buffersize = (1024 * 1024) / 2;
|
||||||
|
// int bytesRead = 0;
|
||||||
|
|
||||||
|
// while (bytesLeft > 0)
|
||||||
|
// {
|
||||||
|
// int curDataSize = Math.Min(buffersize, bytesLeft);
|
||||||
|
// if (client.Available < curDataSize)
|
||||||
|
// {
|
||||||
|
// curDataSize = client.Available;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// bytes = stream.Read(data, bytesRead, curDataSize);
|
||||||
|
// bytesRead += curDataSize;
|
||||||
|
// bytesLeft -= curDataSize;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return data;
|
||||||
|
// }
|
||||||
|
// catch (Exception ex)
|
||||||
|
// {
|
||||||
|
// if (MainActivity.analyticsEnabled)
|
||||||
|
// {
|
||||||
|
// MainActivity.developerExceptionList.Add(ex);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// //dialog.ShowDialog("Error", ex.ToString(), false, Show_Dialog.MessageResult.OK);
|
||||||
|
// ClientDisconnected();
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
public async Task<byte[]> getScreenshot(TcpClient client)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
NetworkStream stream = client.GetStream();
|
||||||
|
byte[] fileSizeBytes = new byte[4];
|
||||||
|
int bytes = stream.Read(fileSizeBytes, 0, fileSizeBytes.Length);
|
||||||
|
int dataLength = BitConverter.ToInt32(fileSizeBytes, 0);
|
||||||
|
|
||||||
|
int bytesLeft = dataLength;
|
||||||
|
byte[] data = new byte[dataLength]; //System.OverflowException: 'Arithmetic operation resulted in an overflow.' KEEP HAPPENING
|
||||||
|
|
||||||
|
int buffersize = (1024 * 1024) / 2;
|
||||||
|
int bytesRead = 0;
|
||||||
|
|
||||||
|
while (bytesLeft > 0)
|
||||||
|
{
|
||||||
|
int curDataSize = Math.Min(buffersize, bytesLeft);
|
||||||
|
if (client.Available < curDataSize)
|
||||||
|
{
|
||||||
|
curDataSize = client.Available;
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes = stream.Read(data, bytesRead, curDataSize);
|
||||||
|
bytesRead += curDataSize;
|
||||||
|
bytesLeft -= curDataSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
if (MainActivity.analyticsEnabled)
|
||||||
|
{
|
||||||
|
MainActivity.developerExceptionList.Add(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
//dialog.ShowDialog("Error", ex.ToString(), false, Show_Dialog.MessageResult.OK);
|
||||||
|
ClientDisconnected();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void askForScreenshot()
|
||||||
|
{
|
||||||
|
//try
|
||||||
|
{
|
||||||
|
TcpClient client = TCP_Connection.TCP_Instance.client;
|
||||||
|
if (client == null)
|
||||||
|
{
|
||||||
|
throw new ObjectDisposedException(client.ToString());
|
||||||
|
}
|
||||||
|
NetworkStream ns = client.GetStream();
|
||||||
|
byte[] message = Encoding.ASCII.GetBytes("{TAKE_SCREENSHOT}");
|
||||||
|
ns.Write(message, 0, message.Length);
|
||||||
|
}
|
||||||
|
//catch (Exception ex)
|
||||||
|
//{
|
||||||
|
// if (MainActivity.analyticsEnabled)
|
||||||
|
// {
|
||||||
|
// MainActivity.developerExceptionList.Add(ex);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// //await dialog.ShowDialog("Error", ex.ToString(), false, Show_Dialog.MessageResult.OK);
|
||||||
|
// ClientDisconnected();
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ImageViewExt : ImageView
|
||||||
|
{
|
||||||
|
private static int INVALID_POINTER_ID = -1;
|
||||||
|
private float mPosX;
|
||||||
|
private float mPosY;
|
||||||
|
|
||||||
|
private float mLastTouchX;
|
||||||
|
private float mLastTouchY;
|
||||||
|
|
||||||
|
private float mLastGestureX;
|
||||||
|
private float mLastGestureY;
|
||||||
|
private int mActivePointerId = INVALID_POINTER_ID;
|
||||||
|
|
||||||
|
private ScaleGestureDetector mScaleDetector;
|
||||||
|
private static float mScaleFactor = 1.0f;
|
||||||
|
|
||||||
|
public ImageViewExt(Context context) : base(context)
|
||||||
|
{
|
||||||
|
mScaleDetector = new ScaleGestureDetector(Context, new ScaleListener());
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool OnTouchEvent(MotionEvent e)
|
||||||
|
{
|
||||||
|
mScaleDetector.OnTouchEvent(e);
|
||||||
|
|
||||||
|
//int action = e.Action;
|
||||||
|
switch (e.Action & MotionEventActions.Mask)
|
||||||
|
{
|
||||||
|
case MotionEventActions.Down:
|
||||||
|
if (!mScaleDetector.IsInProgress)
|
||||||
|
{
|
||||||
|
float x = e.GetX();
|
||||||
|
float y = e.GetY();
|
||||||
|
|
||||||
|
mLastTouchX = x;
|
||||||
|
mLastTouchY = y;
|
||||||
|
mActivePointerId = e.GetPointerId(0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MotionEventActions.Pointer1Down:
|
||||||
|
if (mScaleDetector.IsInProgress)
|
||||||
|
{
|
||||||
|
float gx = mScaleDetector.FocusX;
|
||||||
|
float gy = mScaleDetector.FocusY;
|
||||||
|
|
||||||
|
mLastGestureX = gx;
|
||||||
|
mLastGestureY = gy;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MotionEventActions.Move:
|
||||||
|
if (!mScaleDetector.IsInProgress)
|
||||||
|
{
|
||||||
|
int pointerIdx = e.FindPointerIndex(mActivePointerId);
|
||||||
|
float x = e.GetX(pointerIdx);
|
||||||
|
float y = e.GetY(pointerIdx);
|
||||||
|
|
||||||
|
float dx = x - mLastTouchX;
|
||||||
|
float dy = y - mLastTouchY;
|
||||||
|
|
||||||
|
mPosX += dx;
|
||||||
|
mPosY += dy;
|
||||||
|
|
||||||
|
Invalidate();
|
||||||
|
|
||||||
|
mLastTouchX = x;
|
||||||
|
mLastTouchY = y;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float gx = mScaleDetector.FocusX;
|
||||||
|
float gy = mScaleDetector.FocusY;
|
||||||
|
|
||||||
|
float gdx = gx - mLastGestureX;
|
||||||
|
float gdy = gy - mLastGestureY;
|
||||||
|
|
||||||
|
mPosX += gdx;
|
||||||
|
mPosY += gdy;
|
||||||
|
|
||||||
|
Invalidate();
|
||||||
|
|
||||||
|
mLastGestureX = gx;
|
||||||
|
mLastGestureY = gy;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MotionEventActions.Up:
|
||||||
|
mActivePointerId = INVALID_POINTER_ID;
|
||||||
|
break;
|
||||||
|
case MotionEventActions.Cancel:
|
||||||
|
mActivePointerId = INVALID_POINTER_ID;
|
||||||
|
break;
|
||||||
|
case MotionEventActions.PointerUp:
|
||||||
|
|
||||||
|
int pointerIdx2 = (int)(e.Action & MotionEventActions.PointerIndexMask) >> (int)MotionEventActions.PointerIndexShift;
|
||||||
|
int pointerId = e.GetPointerId(pointerIdx2);
|
||||||
|
|
||||||
|
if (pointerId == mActivePointerId)
|
||||||
|
{
|
||||||
|
int NewPointerIndex = pointerIdx2 == 0 ? 1 : 0;
|
||||||
|
mLastTouchX = e.GetX(NewPointerIndex);
|
||||||
|
mLastTouchY = e.GetY(NewPointerIndex);
|
||||||
|
mActivePointerId = e.GetPointerId(NewPointerIndex);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int TempPointerIdx = e.FindPointerIndex(mActivePointerId);
|
||||||
|
mLastTouchX = e.GetX(TempPointerIdx);
|
||||||
|
mLastTouchY = e.GetY(TempPointerIdx);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnDraw(Canvas canvas)
|
||||||
|
{
|
||||||
|
canvas.Save();
|
||||||
|
|
||||||
|
canvas.Translate(mPosX, mPosY);
|
||||||
|
if (mScaleDetector.IsInProgress)
|
||||||
|
{
|
||||||
|
canvas.Scale(mScaleFactor, mScaleFactor, mScaleDetector.FocusX, mScaleDetector.FocusY);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
canvas.Scale(mScaleFactor, mScaleFactor, mLastGestureX, mLastGestureY);
|
||||||
|
}
|
||||||
|
base.OnDraw(canvas);
|
||||||
|
canvas.Restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private class ScaleListener : ScaleGestureDetector.SimpleOnScaleGestureListener
|
||||||
|
{
|
||||||
|
public override bool OnScale(ScaleGestureDetector detector)
|
||||||
|
{
|
||||||
|
mScaleFactor *= detector.ScaleFactor;
|
||||||
|
|
||||||
|
mScaleFactor = Math.Max(0.1f, Math.Min(mScaleFactor, 10.0f));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
90
src/Resources/layout/activity_main.xml
Executable file
@ -0,0 +1,90 @@
|
|||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:text="Connect to the Server"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:textColor="@android:color/black"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="0.0dp"
|
||||||
|
android:layout_marginRight="0.0dp"
|
||||||
|
android:layout_marginTop="15.0dp"
|
||||||
|
android:layout_marginBottom="0.0dp"
|
||||||
|
android:id="@+id/ConnectText" />
|
||||||
|
<EditText
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:minWidth="25px"
|
||||||
|
android:minHeight="25px"
|
||||||
|
android:id="@+id/ipAddress"
|
||||||
|
android:inputType="phone"
|
||||||
|
android:digits="0123456789."
|
||||||
|
android:maxLines="1"
|
||||||
|
android:hint="IP Address"
|
||||||
|
android:imeOptions="actionNext"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:layout_marginLeft="0.0dp"
|
||||||
|
android:layout_marginRight="0.0dp"
|
||||||
|
android:layout_marginTop="50.0dp"
|
||||||
|
android:layout_marginBottom="0.0dp" />
|
||||||
|
<EditText
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:minWidth="25px"
|
||||||
|
android:minHeight="25px"
|
||||||
|
android:id="@+id/TCP_Port"
|
||||||
|
android:inputType="phone"
|
||||||
|
android:digits="0123456789"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:hint="TCP Port"
|
||||||
|
android:imeOptions="actionNext"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:layout_marginLeft="0.0dp"
|
||||||
|
android:layout_marginRight=".0dp"
|
||||||
|
android:layout_marginTop="100.0dp"
|
||||||
|
android:layout_marginBottom="0.0dp" />
|
||||||
|
<EditText
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:minWidth="25px"
|
||||||
|
android:minHeight="25px"
|
||||||
|
android:id="@+id/UDP_Port"
|
||||||
|
android:inputType="phone"
|
||||||
|
android:digits="0123456789"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:hint="UDP Port"
|
||||||
|
android:imeOptions="actionGo"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:layout_marginLeft="0.0dp"
|
||||||
|
android:layout_marginRight=".0dp"
|
||||||
|
android:layout_marginTop="150.0dp"
|
||||||
|
android:layout_marginBottom="0.0dp" />
|
||||||
|
<Button
|
||||||
|
android:text="Connect"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:textSize="16dp"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_horizontal | center_vertical"
|
||||||
|
android:layout_marginLeft="0.0dp"
|
||||||
|
android:layout_marginRight=".0dp"
|
||||||
|
android:layout_marginTop="220.0dp"
|
||||||
|
android:layout_marginBottom="0.0dp"
|
||||||
|
android:id="@+id/connectButton" />
|
||||||
|
<CheckBox
|
||||||
|
android:text="Developer Analytics Mode"
|
||||||
|
android:textSize="12dp"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentBottom="true"
|
||||||
|
android:layout_marginLeft="7.5dp"
|
||||||
|
android:layout_marginBottom="10dp"
|
||||||
|
android:id="@+id/developeranalyticsmodeCheck" />
|
||||||
|
</RelativeLayout>
|
99
src/Resources/layout/functions_page.xml
Executable file
@ -0,0 +1,99 @@
|
|||||||
|
<RelativeLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:text="Quick Network Test"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:textSize="16dp"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_horizontal | center_vertical"
|
||||||
|
android:layout_marginLeft="0.0dp"
|
||||||
|
android:layout_marginRight=".0dp"
|
||||||
|
android:layout_marginTop="15.0dp"
|
||||||
|
android:layout_marginBottom="0.0dp"
|
||||||
|
android:id="@+id/testButton" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:text="Speed Test"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:textSize="16dp"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_horizontal | center_vertical"
|
||||||
|
android:layout_marginLeft="0.0dp"
|
||||||
|
android:layout_marginRight=".0dp"
|
||||||
|
android:layout_marginTop="65.0dp"
|
||||||
|
android:layout_marginBottom="0.0dp"
|
||||||
|
android:id="@+id/pingButton" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:text="Shutdown System"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:textSize="16dp"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_horizontal | center_vertical"
|
||||||
|
android:layout_marginLeft="0.0dp"
|
||||||
|
android:layout_marginRight=".0dp"
|
||||||
|
android:layout_marginTop="115.0dp"
|
||||||
|
android:layout_marginBottom="0.0dp"
|
||||||
|
android:id="@+id/shutdownButton" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:text="Turn Monitor On"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:textSize="16dp"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_horizontal | center_vertical"
|
||||||
|
android:layout_marginLeft="0.0dp"
|
||||||
|
android:layout_marginRight=".0dp"
|
||||||
|
android:layout_marginTop="165.0dp"
|
||||||
|
android:layout_marginBottom="0.0dp"
|
||||||
|
android:id="@+id/monitorONButton" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:text="Turn Monitor Off"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:textSize="16dp"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_horizontal | center_vertical"
|
||||||
|
android:layout_marginLeft="0.0dp"
|
||||||
|
android:layout_marginRight=".0dp"
|
||||||
|
android:layout_marginTop="215.0dp"
|
||||||
|
android:layout_marginBottom="0.0dp"
|
||||||
|
android:id="@+id/monitorOFFButton" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:text="Take Screenshot"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:textSize="16dp"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_horizontal | center_vertical"
|
||||||
|
android:layout_marginLeft="0.0dp"
|
||||||
|
android:layout_marginRight=".0dp"
|
||||||
|
android:layout_marginTop="265.0dp"
|
||||||
|
android:layout_marginBottom="0.0dp"
|
||||||
|
android:id="@+id/screenshotButton" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:text="Lock Computer (Currently: ...)"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:textSize="16dp"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_horizontal | center_vertical"
|
||||||
|
android:layout_marginLeft="0.0dp"
|
||||||
|
android:layout_marginRight=".0dp"
|
||||||
|
android:layout_marginTop="315.0dp"
|
||||||
|
android:layout_marginBottom="0.0dp"
|
||||||
|
android:id="@+id/PCLockButton" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
17
src/Resources/layout/picture_page.xml
Executable file
@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:background="@android:color/black"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:id="@+id/picturepageLinearLayout">
|
||||||
|
|
||||||
|
<!-- WASTED 3 HOURS BECAUSE OF picture_page.xml's LINEARLAYOUT HAD
|
||||||
|
android:foreground="@android:color/black"!!!! FIXED NOW -->
|
||||||
|
|
||||||
|
<!-- <ImageView
|
||||||
|
android:src="@android:color/dark"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:id="@+id/screenshotView" /> -->
|
||||||
|
</LinearLayout>
|
5
src/Resources/mipmap-anydpi-v26/ic_launcher.xml
Executable file
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@color/ic_launcher_background"/>
|
||||||
|
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
5
src/Resources/mipmap-anydpi-v26/ic_launcher_round.xml
Executable file
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@color/ic_launcher_background"/>
|
||||||
|
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
BIN
src/Resources/mipmap-hdpi/ic_launcher.png
Executable file
After Width: | Height: | Size: 1.6 KiB |
BIN
src/Resources/mipmap-hdpi/ic_launcher_foreground.png
Executable file
After Width: | Height: | Size: 1.4 KiB |
BIN
src/Resources/mipmap-hdpi/ic_launcher_round.png
Executable file
After Width: | Height: | Size: 3.5 KiB |
BIN
src/Resources/mipmap-mdpi/ic_launcher.png
Executable file
After Width: | Height: | Size: 1.3 KiB |
BIN
src/Resources/mipmap-mdpi/ic_launcher_foreground.png
Executable file
After Width: | Height: | Size: 958 B |
BIN
src/Resources/mipmap-mdpi/ic_launcher_round.png
Executable file
After Width: | Height: | Size: 2.4 KiB |
BIN
src/Resources/mipmap-xhdpi/ic_launcher.png
Executable file
After Width: | Height: | Size: 2.3 KiB |
BIN
src/Resources/mipmap-xhdpi/ic_launcher_foreground.png
Executable file
After Width: | Height: | Size: 2.0 KiB |
BIN
src/Resources/mipmap-xhdpi/ic_launcher_round.png
Executable file
After Width: | Height: | Size: 4.7 KiB |
BIN
src/Resources/mipmap-xxhdpi/ic_launcher.png
Executable file
After Width: | Height: | Size: 3.8 KiB |
BIN
src/Resources/mipmap-xxhdpi/ic_launcher_foreground.png
Executable file
After Width: | Height: | Size: 3.3 KiB |
BIN
src/Resources/mipmap-xxhdpi/ic_launcher_round.png
Executable file
After Width: | Height: | Size: 7.8 KiB |
BIN
src/Resources/mipmap-xxxhdpi/ic_launcher.png
Executable file
After Width: | Height: | Size: 4.9 KiB |
BIN
src/Resources/mipmap-xxxhdpi/ic_launcher_foreground.png
Executable file
After Width: | Height: | Size: 4.8 KiB |
BIN
src/Resources/mipmap-xxxhdpi/ic_launcher_round.png
Executable file
After Width: | Height: | Size: 11 KiB |
6
src/Resources/values/colors.xml
Executable file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<color name="colorPrimary">#2c3e50</color>
|
||||||
|
<color name="colorPrimaryDark">#1B3147</color>
|
||||||
|
<color name="colorAccent">#3498db</color>
|
||||||
|
</resources>
|
4
src/Resources/values/ic_launcher_background.xml
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<color name="ic_launcher_background">#2C3E50</color>
|
||||||
|
</resources>
|
4
src/Resources/values/strings.xml
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
<resources>
|
||||||
|
<string name="app_name">TCPCommanderAndroid</string>
|
||||||
|
<string name="action_settings">Settings</string>
|
||||||
|
</resources>
|
11
src/Resources/values/styles.xml
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
<resources>
|
||||||
|
|
||||||
|
<!-- Base application theme. -->
|
||||||
|
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
|
||||||
|
<!-- Customize your theme here. -->
|
||||||
|
<item name="colorPrimary">@color/colorPrimary</item>
|
||||||
|
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||||
|
<item name="colorAccent">@color/colorAccent</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</resources>
|
132
src/TCPCommanderAndroid.csproj
Executable file
@ -0,0 +1,132 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProductVersion>8.0.30703</ProductVersion>
|
||||||
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
<ProjectGuid>{57E1D0A1-8BBB-4C94-8C67-3631D3B0D180}</ProjectGuid>
|
||||||
|
<ProjectTypeGuids>{EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||||
|
<TemplateGuid>{122416d6-6b49-4ee2-a1e8-b825f31c79fe}</TemplateGuid>
|
||||||
|
<OutputType>Library</OutputType>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>TCPCommanderAndroid</RootNamespace>
|
||||||
|
<AssemblyName>TCPCommanderAndroid</AssemblyName>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<AndroidApplication>True</AndroidApplication>
|
||||||
|
<AndroidResgenFile>Resources\Resource.designer.cs</AndroidResgenFile>
|
||||||
|
<AndroidResgenClass>Resource</AndroidResgenClass>
|
||||||
|
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
|
||||||
|
<AndroidUseLatestPlatformSdk>false</AndroidUseLatestPlatformSdk>
|
||||||
|
<TargetFrameworkVersion>v9.0</TargetFrameworkVersion>
|
||||||
|
<AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
|
||||||
|
<MonoAndroidResourcePrefix>Resources</MonoAndroidResourcePrefix>
|
||||||
|
<MonoAndroidAssetsPrefix>Assets</MonoAndroidAssetsPrefix>
|
||||||
|
<AndroidEnableSGenConcurrent>true</AndroidEnableSGenConcurrent>
|
||||||
|
<AndroidUseAapt2>true</AndroidUseAapt2>
|
||||||
|
<AndroidHttpClientHandlerType>Xamarin.Android.Net.AndroidClientHandler</AndroidHttpClientHandlerType>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<DebugSymbols>True</DebugSymbols>
|
||||||
|
<DebugType>portable</DebugType>
|
||||||
|
<Optimize>False</Optimize>
|
||||||
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<AndroidUseSharedRuntime>True</AndroidUseSharedRuntime>
|
||||||
|
<AndroidLinkMode>None</AndroidLinkMode>
|
||||||
|
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
|
||||||
|
<AotAssemblies>false</AotAssemblies>
|
||||||
|
<EnableLLVM>false</EnableLLVM>
|
||||||
|
<AndroidEnableProfiledAot>false</AndroidEnableProfiledAot>
|
||||||
|
<BundleAssemblies>false</BundleAssemblies>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<DebugSymbols>True</DebugSymbols>
|
||||||
|
<DebugType>portable</DebugType>
|
||||||
|
<Optimize>True</Optimize>
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<AndroidManagedSymbols>true</AndroidManagedSymbols>
|
||||||
|
<AndroidUseSharedRuntime>False</AndroidUseSharedRuntime>
|
||||||
|
<AndroidLinkMode>SdkOnly</AndroidLinkMode>
|
||||||
|
<EmbedAssembliesIntoApk>True</EmbedAssembliesIntoApk>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Xml" />
|
||||||
|
<Reference Include="System.Core" />
|
||||||
|
<Reference Include="Mono.Android" />
|
||||||
|
<Reference Include="System.Numerics" />
|
||||||
|
<Reference Include="System.Numerics.Vectors" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Connection.cs" />
|
||||||
|
<Compile Include="FunctionsPage.cs" />
|
||||||
|
<Compile Include="MainActivity.cs" />
|
||||||
|
<Compile Include="Resources\layout\PicturePage.cs" />
|
||||||
|
<Compile Include="Resources\Resource.designer.cs" />
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="Resources\AboutResources.txt" />
|
||||||
|
<None Include="Properties\AndroidManifest.xml" />
|
||||||
|
<None Include="Assets\AboutAssets.txt" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<AndroidResource Include="Resources\layout\activity_main.xml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</AndroidResource>
|
||||||
|
<AndroidResource Include="Resources\values\colors.xml" />
|
||||||
|
<AndroidResource Include="Resources\values\ic_launcher_background.xml" />
|
||||||
|
<AndroidResource Include="Resources\values\strings.xml" />
|
||||||
|
<AndroidResource Include="Resources\values\styles.xml" />
|
||||||
|
<AndroidResource Include="Resources\mipmap-anydpi-v26\ic_launcher.xml" />
|
||||||
|
<AndroidResource Include="Resources\mipmap-anydpi-v26\ic_launcher_round.xml" />
|
||||||
|
<AndroidResource Include="Resources\mipmap-hdpi\ic_launcher.png" />
|
||||||
|
<AndroidResource Include="Resources\mipmap-hdpi\ic_launcher_foreground.png" />
|
||||||
|
<AndroidResource Include="Resources\mipmap-hdpi\ic_launcher_round.png" />
|
||||||
|
<AndroidResource Include="Resources\mipmap-mdpi\ic_launcher.png" />
|
||||||
|
<AndroidResource Include="Resources\mipmap-mdpi\ic_launcher_foreground.png" />
|
||||||
|
<AndroidResource Include="Resources\mipmap-mdpi\ic_launcher_round.png" />
|
||||||
|
<AndroidResource Include="Resources\mipmap-xhdpi\ic_launcher.png" />
|
||||||
|
<AndroidResource Include="Resources\mipmap-xhdpi\ic_launcher_foreground.png" />
|
||||||
|
<AndroidResource Include="Resources\mipmap-xhdpi\ic_launcher_round.png" />
|
||||||
|
<AndroidResource Include="Resources\mipmap-xxhdpi\ic_launcher.png" />
|
||||||
|
<AndroidResource Include="Resources\mipmap-xxhdpi\ic_launcher_foreground.png" />
|
||||||
|
<AndroidResource Include="Resources\mipmap-xxhdpi\ic_launcher_round.png" />
|
||||||
|
<AndroidResource Include="Resources\mipmap-xxxhdpi\ic_launcher.png" />
|
||||||
|
<AndroidResource Include="Resources\mipmap-xxxhdpi\ic_launcher_foreground.png" />
|
||||||
|
<AndroidResource Include="Resources\mipmap-xxxhdpi\ic_launcher_round.png" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="Resources\drawable\" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Xamarin.Android.Support.Design" Version="28.0.0.1" />
|
||||||
|
<PackageReference Include="Xamarin.Android.Support.Core.Utils" Version="28.0.0.1" />
|
||||||
|
<PackageReference Include="Xamarin.Android.Support.CustomTabs" Version="28.0.0.1" />
|
||||||
|
<PackageReference Include="Xamarin.Essentials" Version="1.2.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<AndroidResource Include="Resources\layout\functions_page.xml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</AndroidResource>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<AndroidResource Include="Resources\layout\picture_page.xml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</AndroidResource>
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
|
||||||
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
<Target Name="BeforeBuild">
|
||||||
|
</Target>
|
||||||
|
<Target Name="AfterBuild">
|
||||||
|
</Target>
|
||||||
|
-->
|
||||||
|
</Project>
|
27
src/TCPCommanderAndroid.sln
Executable file
@ -0,0 +1,27 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 16
|
||||||
|
VisualStudioVersion = 16.0.29519.87
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TCPCommanderAndroid", "TCPCommanderAndroid.csproj", "{57E1D0A1-8BBB-4C94-8C67-3631D3B0D180}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{57E1D0A1-8BBB-4C94-8C67-3631D3B0D180}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{57E1D0A1-8BBB-4C94-8C67-3631D3B0D180}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{57E1D0A1-8BBB-4C94-8C67-3631D3B0D180}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||||
|
{57E1D0A1-8BBB-4C94-8C67-3631D3B0D180}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{57E1D0A1-8BBB-4C94-8C67-3631D3B0D180}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{57E1D0A1-8BBB-4C94-8C67-3631D3B0D180}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {5160C534-21C0-4CA2-9CDA-F7311DBCE9DD}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|