using Android.App; using Android.Graphics; using Android.OS; using Android.Views; using Android.Widget; using System; using System.IO; using System.Net.Sockets; using System.Threading.Tasks; namespace ScrExtDroid { [Activity(Label = "ScrExtDroid", MainLauncher = true, Icon = "@drawable/icon")] public class MainActivity : Activity { private FlushView _view; private bool _isRunning; private string _target; private string ConfigFilePath { get { var dataPath = Application.FilesDir.AbsolutePath; if (Directory.Exists(dataPath) == false) Directory.CreateDirectory(dataPath); return System.IO.Path.Combine(dataPath, "sxd_config.txt"); } } private void AskAndConnect() { EditText et = new EditText(this); et.Text = File.Exists(ConfigFilePath) ? File.ReadAllText(ConfigFilePath) : "192.168.233.233:61234"; AlertDialog.Builder ad = new AlertDialog.Builder(this); ad.SetTitle("Connect"); ad.SetView(et); ad.SetPositiveButton("OK", delegate { _target = et.Text; StartDisplay(); }); ad.SetNegativeButton("Cancel", delegate { Finish(); }); ad.Show(); } private void StartDisplay(bool askAgainOnFail = false) { _isRunning = true; Task.Run(() => { var client = new Socket(SocketType.Stream, ProtocolType.Tcp); try { var parts = _target.Split(':'); var port = int.Parse(parts[1]); RunOnUiThread(delegate { Toast.MakeText(this, "Connecting...", ToastLength.Short).Show(); }); var wait = client.BeginConnect(parts[0], port, null, null); wait.AsyncWaitHandle.WaitOne(2000, true); //等待2秒 if (!wait.IsCompleted) throw new TimeoutException("Time out"); RunOnUiThread(delegate { Toast.MakeText(this, "Connected", ToastLength.Short).Show(); }); File.WriteAllText(ConfigFilePath, _target); } catch (Exception e) { RunOnUiThread(delegate { Toast.MakeText(this, "Connect fail:" + e.Message, ToastLength.Short).Show(); }); RunOnUiThread(delegate { if (askAgainOnFail) { AskAndConnect(); } else { System.Threading.Thread.Sleep(1000); StartDisplay(true); } }); return; } client.Send(new byte[1]); client.ReceiveTimeout = 1000; var ns = new NetworkStream(client); ns.ReadTimeout = 1000; var r = new BinaryReader(ns); try { do { var l = r.ReadInt32(); if (l == 0) { RunOnUiThread(() => Finish()); break; } var b = r.ReadBytes(l); var ms = new MemoryStream(b); var bm = BitmapFactory.DecodeStream(ms); RunOnUiThread(() => { _view.DrawBitmap(bm); }); askAgainOnFail = false; } while (_isRunning); } catch (Exception e) { RunOnUiThread(delegate { Toast.MakeText(this, "Lost Connection:" + e.Message, ToastLength.Short).Show(); if (askAgainOnFail) { AskAndConnect(); } else { System.Threading.Thread.Sleep(1000); StartDisplay(true); } }); } client.Close(); }); } // protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); RequestWindowFeature(WindowFeatures.NoTitle); Window.AddFlags(WindowManagerFlags.KeepScreenOn); _view = new FlushView(this); SetContentView(_view); } protected override void OnResume() { base.OnResume(); AskAndConnect(); } protected override void OnPause() { base.OnPause(); _isRunning = false; } private class FlushView : View { private readonly MainActivity context; private Bitmap _bmp; public FlushView(MainActivity context) : base(context) { this.context = context; } public void DrawBitmap(Bitmap bmp) { _bmp = bmp; Invalidate(); } public override void Draw(Canvas canvas) { var b = _bmp; if (b != null) { canvas.DrawBitmap(b, 0, 0, new Paint()); _bmp = null; b.Dispose(); } } } } }