How do you enable webpage caching for WKWebView in Xamarin: iOS? - caching

I have a Xamarin Forms app that uses the WebView component to display our PWA website. We are needing the WebView component to display the cached webpages when the user does not have an internet connection. This works fine in the Xamarin: Android project with no extra code needed. However, the WKWebView that is rendered for the Xamarin: iOS project, does not appear to display any cached pages.
I am fairly new to Xamarin development, and not sure if there is a way to enable the caching for the iOS project, so that it will function offline (like the Android project does). Does anyone know how to make the WKWebView serve up the cached webpages, when there is no internet connection?

There is a ReturnCacheDataElseLoad Cache type of NSUrlRequestCachePolicy , you can use that to load cache data first else load from web .
Have a look at apple's doc about NSURLRequestReturnCacheDataElseLoad
Use existing cache data, regardless or age or expiration date, loading from originating source only if there is no cached data.
Therefore , coding iOS Renderer as follow :
public class CustomWebViewRenderer :WkWebViewRenderer
{
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
if(e.NewElement != null)
{
NSUrlRequest request = new NSUrlRequest(new NSUrl("https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/custom-renderer/hybridwebview"), NSUrlRequestCachePolicy.ReturnCacheDataElseLoad, 5);
LoadRequest(request);
}
}
}

Related

Load startup model in platform project code and pass it to PCL on Xamarin Forms Initialization

The application I'm currently working on requires data to be retrieved from a web service during app startup that roughly takes 1.5 seconds. After the data is retrieved, it needs to be displayed on the MainPage and that is another 1.5 - 2 seconds since the data is mostly URLs of images that have to be displayed, in my case, using ffimageloading library; which means actually downloading those images first to be displayed.
I have splash startup screens for both Android and iOS implemented separately in platform projects but splash screen only stays up for the amount of time Xamarin Forms needs to load and afterwards disappears not waiting for my actual model to load from the web service. I have searched for solutions to extend the splash screen duration and mostly every solution I have read involves creating another splash screen page, loading page if you will, that is already controlled in PCL project but having two separate splash loading screens just seams not feasible to me at the moment.
So I was wondering, how would one load the initial model in platform projects, during the actual splash screen, and then later pass it to PCL project when Xamarin Forms has finished initialization, presumably to App.xaml.cs 's App() constructor function?
There is no code or enough details so I am assuming this is what you want to do.
Call the APIs asynchrnously , till then show splash screen.
Before assigning MainPage in your App.xaml.cs you should call these APIs asynchronously with await and then you use the same for binding of your mainpage
public App()
{
InitializeComponent();
//do all my prefetch stuff for app initialization.
// API and what not
var viewmodel = new AppMainViewModel();
await viewmodel.CallFooFetchAsync();
await viewmodel.BlahBlahAsync();
MainPage = new NavigationPage(new AppMainPage(viewmodel));
}
In Page
public AppMainPage(AppMainViewModel vm)
{
BindingContext =vm;
}
So by the time page loads it has all the data handy.
You can explore adding this code in OnAppearing of the page.
Note that the concept of default Splash screen is just to show an image(with different theme in Android) and setting image in iOS. You need to have conventional UI technically its not splash screen anymore.
Alternatively you can get shared project handle in native
Android Sp
protected override void OnCreate(Bundle bundle)
{
...
var app = new App(); //this will be shared project App object
Device.BeginInvokeOnMainThread(async () => await app.DoPrefetchStuffFirst()); //API calls if needed in this async method
//then
LoadApplicationm(app)
}
You can do similar thing in iOS AppDelegate
And if you call native specific methods in platforms (may be for API calls) then you would use DependencyService feature , that will pass it to shared project or Custom renderer based on where you want to use it.

How to control webapp accessing between webview and web browser?

What I have
A webapp with Laravel 5.6.
A webview with React Native.
What I want to do
Only allow users to access to webapp via Webview.
Allow all users to access to home page of webapp via web browsers.
Allow web administrators to access to admin pages of webapp via both
of webview and web browsers.
My questions
Can I control these golds only with Laravel?
If yes, how to do it?
Should I separate homepage of webapp and content page of webapp into
2 difference domain (or sub domain)?
Or is therer any other suggestion?
Thank you.
Okay here is what i got after extracting android from react, we need to do following changes in android
MainActivity.java
// REMOTE RESOURCE
mWebView.loadUrl("YOUR_URL_HERE");
And
MyWebViewClient.java : just return false
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// if (Uri.parse(url).getHost().endsWith("YOUR_URL_HERE")) {
// return false;
// }
//
// Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
// view.getContext().startActivity(intent);
// return true;
return (false);
}
Hope it helps
Here's is my webview screenshot

Xamarin.forms OnAppLinkRequestReceived

I'm trying to use https://developer.xamarin.com/api/member/Xamarin.Forms.Application.OnAppLinkRequestReceived/p/System.Uri/ but can't seem to get it to be called in any way.
Did anyone ever tried to implement this new method?
I've tried several ways to implement different deeplinks, all of them open the app fine so they're correctly configured but that method never gets called.
Thanks.
This is how I set it up in Android.
Put this above your MainActivity.cs
[IntentFilter(new[] { Android.Content.Intent.ActionView },
Categories = new[]
{
Android.Content.Intent.CategoryDefault,
Android.Content.Intent.CategoryBrowsable
},
DataScheme = "http",
DataPathPrefix = "/tesla/",
DataHost = "exrin.net")]
This registers the activity when the app is installed. Change the URL to your desired URL.
For Android only (no need to do this with iOS) you need to also install the Nuget Xamarin Forms AppLinks
In your OnCreate make sure you do this after your Xamarin Forms Init
AndroidAppLinks.Init(this);
Then when you load the URL in a browser (in my example http://exrin.net/tesla) you will get this:
Then if you open the app it will enter here with the full URL as the URI parameter. This is in the App.cs (Xamarin.Forms.Application)
protected override void OnAppLinkRequestReceived(Uri uri)
{
base.OnAppLinkRequestReceived(uri);
}
You can then decode the URI as you see fit to move to the specific page in your app that the URL relates to/
More details at Xamarin Forms AppLinks
Also, your MainActivity must be derived from FormsAppCompatActivity for it to work. Once I changed it to that from FormsApplicationActivity, it started working.

Closing Android Activity opened from Forms.Context.StartActivity

I am working on facebook authentication in a Xamarin forms app and want to use "native" login on each device.
The Facebook SDK (by Xamarin) is not designed for forms since it requires passing in an Android activity that implements some specific interfaces.
However; I was able to get the UI to display using a custom page renderer and then in that renderer calling StartActitivty with an activity that uses the exact implementation described in the Facebook SDK getting started. https://components.xamarin.com/view/facebookandroid
So far everything works perfect. The android app starts, xamarin forms kicks in, the custom page renderer is loaded the login android activity starts and the user logs in with facebook and we get to the console.writeline below.
So, how do I dismiss this intent or otherwise get back to xamarin forms?
Do I:
Dismiss this intent? - if so then what?
Inject something to "reset" the main page?
Other?
public void OnCompleted (Xamarin.Facebook.Model.IGraphUser user, Response response)
{
//TODO: show user details with welcome and button that takes them to main app.
//TODO: switch back to xam forms from here on out.
//TODO: figure out how to change the `main` activity to xam forms.
// 'Me' request callback
if (user != null) {
//How do I get back to Xamarin forms from here?
Console.WriteLine ("GOT USER: " + user.Name);
} else {
Console.WriteLine ("Failed to get 'me'!");
}
}
You should call Finish();
Anyway, if you want to see exactly how I did it, you can check it here:
https://github.com/IdoTene/XamarinFormsNativeFacebook

How do I clear the cache of Cordova Web View on Windows Phone 8?

I'm developing a Cordova 2.9.0 app for Windows Phone 8. The app in question utilises external content heavily, using the JS and HTML content that's being served from another source. It all works fine, but the browser component caches heavily.
The only way I have discovered to clear caches is to uninstall-install the app again to take effect. The downside to this is that my localStorage also clears, slowing down my cycles.
I presume the cache can be cleared by writing extra C# into the Cordova template they serve, which I use by the way.
So while it was not that critical, I did stumble to a working answer. The WebBrowser class does have a suitable method to call: ClearInternetCacheAsync.
Since CordovaBrowser inherits from WebBrowser, it's just a matter of adding one line to MainPage.xaml.cs where the C# init of the start page happens:
namespace FooBarApp
{
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();
this.CordovaView.Loaded += CordovaView_Loaded;
// blammo!
this.CordovaView.CordovaBrowser.ClearInternetCacheAsync();
}
Phonegap Cookies Plugin can be found HERE
A simple, lightweight jQuery plugin for reading, writing and deleting cookies can be found HERE
I hope it will resolve your problem. Thanks!!

Resources