diff --git a/App/QR2Web/QR2Web.Droid/HybridWebViewRenderer.cs b/App/QR2Web/QR2Web.Droid/HybridWebViewRenderer.cs new file mode 100644 index 0000000..fcfb300 --- /dev/null +++ b/App/QR2Web/QR2Web.Droid/HybridWebViewRenderer.cs @@ -0,0 +1,136 @@ +using Android.Content; +using Android.OS; +using AndroidX.Lifecycle; +using QR2Web; +using QR2Web.Droid; +using System; +using Xamarin.Forms; +using Xamarin.Forms.Platform.Android; + +[assembly: ExportRenderer(typeof(HybridWebView), typeof(HybridWebViewRenderer))] +namespace QR2Web.Droid +{ + public class HybridWebViewRenderer : WebViewRenderer + { + //const string JavascriptFunction = "function invokeCSharpAction(data){jsBridge.invokeAction(data);}"; + readonly Context _context; + + public HybridWebViewRenderer(Context context) : base(context) + { + _context = context; + } + + protected override void OnElementChanged(ElementChangedEventArgs e) + { + base.OnElementChanged(e); + + if (e.OldElement != null) + { + Control.RemoveJavascriptInterface("jsBridge"); + ((HybridWebView)Element).Cleanup(); + } + if (e.NewElement != null) + { + ((MainActivity)_context).SetWebView(this); + + Control.Settings.SetSupportMultipleWindows(true); + Control.Settings.JavaScriptCanOpenWindowsAutomatically = true; + Control.SetWebChromeClient(new MyWebViewClient(this)); + //Control.SetWebViewClient(new JavascriptWebViewClient(this, $"javascript: {JavascriptFunction}")); + //Control.AddJavascriptInterface(new JSBridge(this), "jsBridge"); + //Control.LoadUrl($"file:///android_asset/Content/{((HybridWebView)Element).Uri}"); + } + } + + public override void OnViewAdded(Android.Views.View child) + { + base.OnViewAdded(child); + } + + protected override void Dispose(bool disposing) + { + if (disposing) + { + ((HybridWebView)Element).Cleanup(); + } + base.Dispose(disposing); + } + + + public void SaveView(Bundle bundle) + { + var res = Control.SaveState(bundle); + if(res == null) + { + Console.WriteLine("[QR2WEB Task] - ERROR ON SAVING"); + } + else + { + Console.WriteLine("[QR2WEB Task] - SUCCESSFULLY SAVED"); + } + } + + public void RestoreView(Bundle bundle) + { + Control.RestoreState(bundle); + } + + } + + public class MyWebViewClient2 : Android.Webkit.WebViewClient + { + readonly HybridWebViewRenderer _hybridRenderer = null; + Android.Net.Uri _url = null; + + public MyWebViewClient2(HybridWebViewRenderer hybridRenderer) : base() + { + _hybridRenderer = hybridRenderer; + } + + public override bool ShouldOverrideUrlLoading(Android.Webkit.WebView view, Android.Webkit.IWebResourceRequest request) + { + _url = request.Url; + if (_url.ToString().StartsWith("http")) + { + //new Task(async () => + { + var butt = new Button { Text = "Open" }; + butt.Pressed += (s, e) => + { + ((MainActivity)_hybridRenderer.Context).OpenExternalUrl(_url.ToString()); + }; + var butt2 = new Button { Text = "Cancel" }; + + App.Instance.ShowDialog("Open external link?\n" + _url.ToString(), butt, butt2); + }//); + } + + this.Dispose(); + return true; + } + } + + public class MyWebViewClient : Android.Webkit.WebChromeClient + { + readonly HybridWebViewRenderer _hybridRenderer = null; + + public MyWebViewClient(HybridWebViewRenderer hybridRenderer) : base() + { + _hybridRenderer = hybridRenderer; + new WebViewRenderer(_hybridRenderer.Context); + } + + + public override bool OnCreateWindow(Android.Webkit.WebView view, bool isDialog, bool isUserGesture, Android.OS.Message resultMsg) + { + Android.Webkit.WebView newWebView = new Android.Webkit.WebView(_hybridRenderer.Context); + newWebView.SetWebViewClient(new MyWebViewClient2(_hybridRenderer)); + + Android.Webkit.WebView.WebViewTransport transport = (Android.Webkit.WebView.WebViewTransport)resultMsg.Obj; + transport.WebView = newWebView; + resultMsg.SendToTarget(); + return true; + } + + } +} \ No newline at end of file diff --git a/App/QR2Web/QR2Web.Droid/MainActivity.cs b/App/QR2Web/QR2Web.Droid/MainActivity.cs index b90d96f..0bd992f 100644 --- a/App/QR2Web/QR2Web.Droid/MainActivity.cs +++ b/App/QR2Web/QR2Web.Droid/MainActivity.cs @@ -2,25 +2,41 @@ using Android.App; using Android.Content.PM; -using Android.Runtime; +using Android.Util; using Android.Views; using Android.Widget; using Android.OS; using ZXing.Mobile; using System.Threading.Tasks; -using Plugin.CurrentActivity; using Android.Content; using Xamarin.Forms.PlatformConfiguration.AndroidSpecific; using Xamarin.Essentials; +using Android.Window; +using AndroidX.AppCompat.App; +using Xamarin.Forms.Platform.Android; +using Android.Bluetooth; +//using Xamarin.Forms; namespace QR2Web.Droid { [Activity(Label = "QR2Web", Icon = "@drawable/icon", + Theme = "@style/MyTheme.QR", MainLauncher = false, Exported = true, + NoHistory = false, + AlwaysRetainTaskState = true, + HardwareAccelerated = true, + ResumeWhilePausing = true, + ClearTaskOnLaunch = false, + ScreenOrientation = ScreenOrientation.Portrait, + WindowSoftInputMode = SoftInput.AdjustPan,/* + StateNotNeeded = false, + UiOptions = UiOptions.SplitActionBarWhenNarrow, + FinishOnTaskLaunch = false, + DocumentLaunchMode = DocumentLaunchMode.IntoExisting,*/ ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation, - LaunchMode = LaunchMode.SingleTask)] + LaunchMode = LaunchMode.SingleTop)] [IntentFilter(new[] { Intent.ActionView }, DataScheme = "qr2web", Categories = new[] { Intent.CategoryDefault, Intent.CategoryBrowsable })] @@ -33,25 +49,30 @@ namespace QR2Web.Droid [IntentFilter(new[] { Intent.ActionView }, DataScheme = "mochabarcode", Categories = new[] { Intent.CategoryDefault, Intent.CategoryBrowsable })] - public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity, OSInterface + public class MainActivity : /*global::Xamarin.Forms.Platform.Android.FormsApplicationActivity*/ global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity, OSInterface { bool intentDataRead = false; int oldViewHeight = -1; + HybridWebViewRenderer _myWebView = null; + Bundle _savedBundle = null; protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); + Console.WriteLine("[QR2WEB Task] - CREATE " + bundle != null ? " WITH BUNDLE" : "."); + ShowFullScreen(); Xamarin.Forms.Forms.Init(this, bundle); - CrossCurrentActivity.Current.Init(this, bundle); - LoadApplication(new App(this, false)); + _savedBundle = bundle; InitOSSettings(bundle); InitExternalLibraries(); - + + LoadApplication(new App(this, false)); + LockPortrait(Parameters.Options.LockPortrait); intentDataRead = false; @@ -59,6 +80,93 @@ protected override void OnCreate(Bundle bundle) View v = Window.DecorView; v.ViewTreeObserver.GlobalLayout += ViewTreeObserver_GlobalLayout; + Xamarin.Essentials.Platform.ActivityStateChanged += Platform_ActivityStateChanged; + BackPressed += MainActivity_BackPressed; + + if (_myWebView != null && bundle != null) + { + _myWebView.RestoreView(bundle); + } + } + + public void InitExternalLibraries() + { + //Xamarin.Essentials.Platform.Init(Application); + ZXing.Net.Mobile.Forms.Android.Platform.Init(); + Rg.Plugins.Popup.Popup.Init(this); + } + + public void InitOSSettings(Bundle bundle) + { + Xamarin.Essentials.Platform.Init(this, bundle); + } + + + private void Platform_ActivityStateChanged(object sender, ActivityStateChangedEventArgs e) + { + Console.WriteLine("[QR2WEB Task] - STATE CHANGE - " + e.State.ToString()); + } + + public void SetWebView(HybridWebViewRenderer webview) + { + _myWebView = webview; + if(_savedBundle != null) + { + _myWebView.RestoreView(_savedBundle); + } + } + + + protected override void OnPause() + { + Console.WriteLine("[QR2WEB Task] - PAUSE"); + base.OnPause(); + } + + protected override void OnResume() + { + Console.WriteLine("[QR2WEB Task] - RESUME"); + base.OnResume(); + } + + + protected override void OnStop() + { + Console.WriteLine("[QR2WEB Task] - STOP"); + base.OnStop(); + } + + protected override void OnDestroy() + { + Console.WriteLine("[QR2WEB Task] - DESTROY"); + base.OnDestroy(); + } + + protected override void OnRestart() + { + Console.WriteLine("[QR2WEB Task] - RESTART"); + base.OnRestart(); + } + + protected override void OnSaveInstanceState(Bundle outState) + { + Console.WriteLine("[QR2WEB Task] - SAVE INSTANCE"); + _myWebView?.SaveView(outState); + base.OnSaveInstanceState(outState); + } + + public override void OnSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) + { + Console.WriteLine("[QR2WEB Task] - SAVE INSTANCE 2"); + _myWebView?.SaveView(outState); + base.OnSaveInstanceState(outState, outPersistentState); + } + + protected override void OnRestoreInstanceState(Bundle savedInstanceState) + { + Console.WriteLine("[QR2WEB Task] - RESTORE INSTANCE"); + _myWebView?.RestoreView(savedInstanceState); + base.OnRestoreInstanceState(savedInstanceState); } /*Hack to resize browser size when kayboard is overlapping the form inside*/ @@ -83,7 +191,10 @@ private void ViewTreeObserver_GlobalLayout(object sender, EventArgs e) new Task(() => { Task.Delay(200); - App.Current.On().UseWindowSoftInputModeAdjust(WindowSoftInputModeAdjust.Resize); + MainThread.BeginInvokeOnMainThread(() => + { + App.Current.On().UseWindowSoftInputModeAdjust(WindowSoftInputModeAdjust.Resize); + }); }).Start(); } } @@ -93,7 +204,9 @@ protected override void OnNewIntent(Intent intent) { base.OnNewIntent(intent); - if(intent.Data != null) + Console.WriteLine("[QR2WEB Task] - NEW INTENT"); + + if (intent.Data != null) { if (!intentDataRead) { @@ -111,6 +224,8 @@ protected override void OnStart() { base.OnStart(); + Console.WriteLine("[QR2WEB Task] - START"); + if (Intent.Data != null) { if (!intentDataRead) @@ -143,26 +258,23 @@ public void LockPortrait(bool tryToLock) } } - public void InitExternalLibraries() + private bool MainActivity_BackPressed(object sender, EventArgs e) { - Xamarin.Essentials.Platform.Init(Application); - ZXing.Net.Mobile.Forms.Android.Platform.Init(); - Rg.Plugins.Popup.Popup.Init(this); - } - - public void InitOSSettings(Bundle bundle) - { - + if (Rg.Plugins.Popup.Popup.SendBackPressed(null)) + return true; + return App.InvokeBack(); } + // obsolete since android 13 + /* public override void OnBackPressed() { Rg.Plugins.Popup.Popup.SendBackPressed(base.OnBackPressed); - } + }*/ public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults) { - Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults); + Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults); Plugin.Permissions.PermissionsImplementation.Current.OnRequestPermissionsResult(requestCode, permissions, grantResults); base.OnRequestPermissionsResult(requestCode, permissions, grantResults); } diff --git a/App/QR2Web/QR2Web.Droid/Properties/AndroidManifest.xml b/App/QR2Web/QR2Web.Droid/Properties/AndroidManifest.xml index a782e4b..5ca7537 100644 --- a/App/QR2Web/QR2Web.Droid/Properties/AndroidManifest.xml +++ b/App/QR2Web/QR2Web.Droid/Properties/AndroidManifest.xml @@ -1,12 +1,12 @@  - - + + - +