I am creating a web wrapper app, and am wanting to only show certain elements in an html page. I have the current code below, and I know I need to use javascript possibly but am not sure where to go to from here.
public class MainActivity : Activity
{
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.Main);
var webView = FindViewById<WebView> (Resource.Id.webView);
webView.Settings.JavaScriptEnabled = true;
// Use subclassed WebViewClient to intercept hybrid native calls
webView.SetWebViewClient (new WebViewClient ());
webView.LoadUrl ("http://bobhoil.com/");
}
public override bool OnCreateOptionsMenu(IMenu menu)
{
base.OnCreateOptionsMenu (menu);
MenuInflater inflater = this.MenuInflater;
inflater.Inflate (Resource.Menu.menu, menu);
return true;
}
}
Thanks
You can use something like this:
StringBuilder sb = new StringBuilder();
sb.Append("your javascript");
webView.LoadUrl("javascript:" + sb.ToString());
Related
I am new to Xamarin and Android programming and am struggling with an exception.
My app uses the navigation drawer layout and fragments.
It has a data file stored on the android device that contains profiles to load. These are built into a URL for use in a webview control on a fragment.
When the app is run for the first time it asks for permission to access external storage (I am using the plugin.permissions package for this). The app waits for permission and then opens the file and gets the profile selected as default. It then runs a procedure (which takes the profile as a parameter) and this creates the fragment in the main layout. There will be a method called from the fragment class which is why I create an object rather than doing it in the SupportFragmentManager.BeginTransaction line.
There is a check to see if the profile parameter was null. If it was not then I call the fragment method. _permissionsGranted is passed so that an error message can be displayed on the webview if the app did not have permission to access to file.
This all works fine when the app is first installed and waits to be granted permissions. After that restarts, bringing up the recents list and going back to the app all cause it to crash.
I am getting this error:
Time Device Name Type PID Tag Message 01-02 10:54:14.003 Samsung
SM-G930F Info 15603 MonoDroid System.NullReferenceException: Object
reference not set to an instance of an object. at
WebRDT2.Fragment_Classes.WebViewFragment.OpenURL
(WebRDT2.Classes.EnviromentProfile _environment, System.Boolean
_permissionsGranted) [0x00014] in C:\Users\eversonm\source\repos\WebRDT2\WebRDT2\Fragment
Classes\WebViewFragment.cs:85 at WebRDT2.MainActivity.LoadProfile
(WebRDT2.Classes.EnviromentProfile _ep) [0x00081] in
C:\Users\eversonm\source\repos\WebRDT2\WebRDT2\MainActivity.cs:236
at WebRDT2.MainActivity.OnCreate (Android.OS.Bundle
savedInstanceState) [0x002fd] in
C:\Users\eversonm\source\repos\WebRDT2\WebRDT2\MainActivity.cs:121
at
System.Runtime.CompilerServices.AsyncMethodBuilderCore+<>c.b__7_0
(System.Object state) [0x00000] in
<6de48997d0c0445dbea8d4d83492d8c6>:0 at
Android.App.SyncContext+<>c__DisplayClass2_0.b__0 () [0x00000]
in <11a340ccc8de43f09c97400139266ef5>:0 at
Java.Lang.Thread+RunnableImplementor.Run () [0x00008] in
<11a340ccc8de43f09c97400139266ef5>:0 at
Java.Lang.IRunnableInvoker.n_Run (System.IntPtr jnienv, System.IntPtr
native__this) [0x00009] in <11a340ccc8de43f09c97400139266ef5>:0 at
(wrapper dynamic-method)
Android.Runtime.DynamicMethodNameCounter.22(intptr,intptr)
This is referring to the webview object wv. I know this because I've taken then code that uses wv out of this method and the app does not crash. It just calls the method and only clears the cookies.
I have read through the fragment lifecycle documentation
but I cannot understand what the issue is. Again, I'm new to this.
MainActivity.cs (work in progress so not asking for hints, just if there's some way I should recode for the webview fragment)
namespace WebRDT2
{
[Activity(Label = "#string/app_name", Theme = "#style/AppTheme", MainLauncher = true)]
public class MainActivity : AppCompatActivity, NavigationView.IOnNavigationItemSelectedListener
{
List<EnviromentProfile> envList;
Plugin.Permissions.Abstractions.PermissionStatus permissionStatus;
Bundle mainSavedInstanceState;
protected async override void OnCreate(Bundle savedInstanceState)
{
Plugin.CurrentActivity.CrossCurrentActivity.Current.Init(this, savedInstanceState);
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
//Set current activity for permissions
Plugin.CurrentActivity.CrossCurrentActivity.Current.Activity = this;
//Ask for permissions if we need them
await CrossPermissions.Current.RequestPermissionsAsync(Plugin.Permissions.Abstractions.Permission.Storage);
// Check if permissions were granted
permissionStatus = await CrossPermissions.Current.CheckPermissionStatusAsync(Plugin.Permissions.Abstractions.Permission.Storage);
mainSavedInstanceState = savedInstanceState;
// If we received a list of profiles then load else report issue to user
if (envList != null)
{
EnviromentProfile ep = null;
if (mainSavedInstanceState == null)
{
//Then the application is being loaded for the first time
LoadProfile(ep);
}
}
}
private void LoadProfile(EnviromentProfile _ep)
{
Fragment_Classes.WebViewFragment wvf = new Fragment_Classes.WebViewFragment();
SupportFragmentManager.BeginTransaction()
.Replace(Resource.Id.fragment_container, wvf)
.Commit();
SupportFragmentManager.ExecutePendingTransactions();
if (_ep != null)
{
wvf.OpenURL(_ep, true);
Toast.MakeText(Application.Context, "_ep is not null", ToastLength.Long).Show();
}
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
PermissionsImplementation.Current.OnRequestPermissionsResult(requestCode, permissions, grantResults);
//base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
}
WebViewFragment.cs
namespace WebRDT2.Fragment_Classes
{
class WebViewFragment : Fragment
{
private View view;
WebView wv;
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
//LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.Inflate(Resource.Layout.webview, container, false);
return view;
}
public override void OnViewCreated(View view, Bundle savedInstanceState)
{
base.OnViewCreated(view, savedInstanceState);
wv = view.FindViewById<WebView>(Resource.Id.webView);
}
public override void OnStart()
{
base.OnStart();
wv = view.FindViewById<WebView>(Resource.Id.webView);
}
public override void OnResume()
{
base.OnResume();
wv = view.FindViewById<WebView>(Resource.Id.webView);
}
public void OpenURL(EnviromentProfile _environment, bool _permissionsGranted)
{
//WebView wv = view.FindViewById<WebView>(Resource.Id.webView);
var cookieManager = CookieManager.Instance;
cookieManager.RemoveAllCookie(); // Clear cache
string myURL = ""; // URL to load
wv.SetWebViewClient(new XPOWebViewClient());
wv.Settings.JavaScriptEnabled = true;
wv.Settings.BuiltInZoomControls = true;
wv.Settings.SetSupportZoom(true);
wv.ScrollBarStyle = ScrollbarStyles.OutsideOverlay;
wv.ScrollbarFadingEnabled = false;
wv.LoadDataWithBaseURL(null, "<html><body>---TESTING---</body></html>",
"text/html", "utf-8", null);
}
}
}
I hope that's enough detail. Apologies if it's too much.
If anyone can help with this I would greatly appreciate it. I have searched the forum and cannot find an answer.
So after some debugging thanks to #y3z1 for pointing out where to start, it turns out the issue was that while the events in the fragment do execute they were not doing so in the correct order. My OpenURL method was being called prior to the OnCreateView method.
Thanks to this thread Wait until fragment has been added to the UI I then found the way to modify my code. Now the call to OpenURL is triggered from the events in the fragment, thus ensuring that it only happens after everything is initialized.
LoadProfile
private void LoadProfile()
{
Fragment_Classes.WebViewFragment wvf = new Fragment_Classes.WebViewFragment();
SupportFragmentManager.BeginTransaction()
.Replace(Resource.Id.fragment_container, wvf)
.Commit();
SupportFragmentManager.ExecutePendingTransactions();
}
WebViewFragment.OnResume
public override void OnResume()
{
base.OnResume();
wv = view.FindViewById<WebView>(Resource.Id.webView);
((MainActivity)this.Activity).OpenURL(this);
}
MainActivity.OpenURL
public void OpenURL(Fragment_Classes.WebViewFragment wvf)
{
wvf.OpenURL(ep, true);
}
I am a beginner in xamarin android.I want to take photo using my device camera,I am using the following code to to capture the image but, I got an exception when running the code
Here is my Fragment.CS
public class ScanFragments : Fragment
{
ImageView imageView;
public override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
}
public static ScanFragments NewInstance()
{
var scan = new ScanFragments { Arguments = new Bundle() };
return scan;
}
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
var ignored = base.OnCreateView(inflater, container, savedInstanceState);
imageView =View.FindViewById<ImageView>(Resource.Id.Iv_ScanImg);
var btnCamera =View. FindViewById<Button>(Resource.Id.btnCamera);
btnCamera.Click += BtnCamera_Click;
return inflater.Inflate(Resource.Layout.ScanLayout, null);
}
private void BtnCamera_Click(object sender, EventArgs e)
{
Intent intent = new Intent(MediaStore.ActionImageCapture);
StartActivityForResult(intent, 0);
}
}
Well now I see your mistake its actually very simple you get the null reference because of the following reasons
1.OnCreateView does not contain a definition of View basically what I mean here is View is a class which you are using as an object of that class.
2.The actual way I recommend using fragments is first you define it an XML or an AXML as its foreground view in on OnCreateView as follows :
return inflater.Inflate(Resource.Layout.ScanLayout, null);
3.Override the OnViewCreated method and use its View to do all your work as follows :
public override void OnViewCreated(View view, Bundle savedInstanceState)
{
base.OnViewCreated(view, savedInstanceState);
imageView =view.FindViewById<ImageView>(Resource.Id.Iv_ScanImg);
var btnCamera =view. FindViewById<Button>(Resource.Id.btnCamera);
btnCamera.Click += BtnCamera_Click;
}
4.For details related to the Android Activity and Fragment lifecycle check here
Goodluck!
In my app I have implemented a webview to show a website link into that webview. Now that website has a button that contains a pdf file link. If I click on that button on website it shows a pdf file on the web. But if I try to open it into the webview in my app, nothing happens. I am very new in Xamarin android. I could not find any suitable way to that. Here is my code to show the website into the webview.
I want to relod the pdf when click on link from the website. But the result is same as before
Modified Code
namespace Xamarin.PDFView
{
[Activity (Label = "PDFView", MainLauncher = true, Icon = "#drawable/icon")]
public class MainActivity : Activity
{
private string _documentsPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments);
private string _pdfPath;
private string _pdfFileName = "thePDFDocument.pdf";
private string _pdfFilePath;
private WebView _webView;
private string _webUrl = "https://Link of thewebsite";
private string _pdfURL = "https://Link of thewebsite/25052016.pdf";
private WebClient _webClient = new WebClient();
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.Main);
_webView = FindViewById<WebView> (Resource.Id.webView1);
var settings = _webView.Settings;
settings.JavaScriptEnabled = true;
settings.AllowFileAccessFromFileURLs = true;
settings.AllowUniversalAccessFromFileURLs = true;
settings.BuiltInZoomControls = true;
_webView.SetWebViewClient(new WebViewClient());
_webView.SetWebChromeClient(new WebChromeClient());
_webView.LoadUrl(_webUrl);
}
public override bool OnTouchEvent(MotionEvent e)
{
if (_webUrl.Contains(".pdf"))
{
DownloadPDFDocument();
}
return base.OnTouchEvent(e);
}
protected override void OnResume ()
{
base.OnResume ();
_webView.LoadUrl( "javascript:window.location.reload( true )" );
}
protected override void OnPause ()
{
base.OnPause ();
_webView.ClearCache(true);
}
private void DownloadPDFDocument()
{
AndHUD.Shared.Show(this, "Downloading PDF\nPlease Wait ..", -1, MaskType.Clear);
_pdfPath = _documentsPath + "/PDFView";
_pdfFilePath = Path.Combine(_pdfPath, _pdfFileName);
// Check if the PDFDirectory Exists
if(!Directory.Exists(_pdfPath)){
Directory.CreateDirectory(_pdfPath);
}
else{
// Check if the pdf is there, If Yes Delete It. Because we will download the fresh one just in a moment
if (File.Exists(_pdfFilePath)){
File.Delete(_pdfFilePath);
}
}
// This will be executed when the pdf download is completed
_webClient.DownloadDataCompleted += OnPDFDownloadCompleted;
// Lets downlaod the PDF Document
var url = new Uri(_pdfURL);
_webClient.DownloadDataAsync(url);
}
private void OnPDFDownloadCompleted (object sender, DownloadDataCompletedEventArgs e)
{
// Okay the download's done, Lets now save the data and reload the webview.
var pdfBytes = e.Result;
File.WriteAllBytes (_pdfFilePath, pdfBytes);
if(File.Exists(_pdfFilePath))
{
var bytes = File.ReadAllBytes(_pdfFilePath);
}
_webView.LoadUrl("file:///android_asset/pdfviewer/index.html?file=" + _pdfFilePath);
AndHUD.Shared.Dismiss();
}
public class HelloWebViewClient : WebViewClient
{
public override bool ShouldOverrideUrlLoading(WebView view, IWebResourceRequest request)
{
view.LoadUrl(request.Url.ToString());
return false;
}
}
}
}
Mentioned in the link below:
Read this link
You will need to implement following code using WebViewRenderer
namespace DisplayPDF.Droid
{
public class CustomWebViewRenderer : WebViewRenderer
{
protected override void OnElementChanged (ElementChangedEventArgs<WebView> e)
{
base.OnElementChanged (e);
if (e.NewElement != null) {
var customWebView = Element as CustomWebView;
Control.Settings.AllowUniversalAccessFromFileURLs = true;
Control.LoadUrl (string.Format ("file:///android_asset/pdfjs/web/viewer.html?file={0}", string.Format ("file:///android_asset/Content/{0}", WebUtility.UrlEncode (customWebView.Uri))));
}
}
}
}
is there any way to show pdf file from a link
As discussed android webview doesn't support pdf files. As a workaround, you can use Google Docs in android webview:
Create a custom webview client and override ShouldOverrideUrlLoading like this:
public class MyWebViewClient: WebViewClient
{
public override bool ShouldOverrideUrlLoading(WebView view, string url)
{
//if PDF file then use google client to show it
if (url.ToLower().EndsWith(".pdf"))
{
var newUrl = "https://docs.google.com/viewer?url=" + url;
view.LoadUrl(newUrl);
}
return true;
}
}
Use your custom webview client:
mWebview.SetWebViewClient(new MyWebViewClient());
Notes: If you use android:layout_height="wrap_content" for your webview, you need to change it to a fixed dp like android:layout_height="400dp", otherwise the webview won't show pdf correctly.
I writing app for Android using Xamarin.
I have this code in Activity for OnCreate method.
protected override int LayoutResource
{
get { return Resource.Layout.Main; }
}
private RecyclerView recyclerView;
private ProgressBar activityIndicator;
private RecyclerView.LayoutManager layoutManager;
protected override async void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
recyclerView = FindViewById<RecyclerView>(Resource.Id.recyclerView);
activityIndicator = FindViewById<ProgressBar>(Resource.Id.activityIndicator);
activityIndicator.Visibility = Android.Views.ViewStates.Visible;
layoutManager = new LinearLayoutManager(this, LinearLayoutManager.Vertical, false);
recyclerView.SetLayoutManager(layoutManager);
var repository = new TestAppRepository();
var films = await repository.GetAllFilms();
var formsAdapter = new FormAdapter(films.results);
recyclerView.SetAdapter(formsAdapter);
activityIndicator.Visibility = Android.Views.ViewStates.Gone;
SupportActionBar.SetDisplayHomeAsUpEnabled(false);
SupportActionBar.SetHomeButtonEnabled(false);
I have Button in toolbar and need to refresh Recycler when I tap this button.
Here is calling of it for display
public override bool OnCreateOptionsMenu(IMenu menu)
{
MenuInflater.Inflate(Resource.Menu.home, menu);
return base.OnCreateOptionsMenu(menu);
}
How I need to write code to refresh Recycler?
Thank's for help
Use the button's setOnClickListener method and implement the onClick method of the new OnClickListener In the onClick method called the RecyclerView adapter's notifydatasetchanged()
My app is supposed to have a button in the main activity that when pressed should show a custom dialog box that will be used as a register form for users. The problem is when I remove the title bar of my custom dialog window collapses horizontally. Any advise on how to fix this? Is the idea of using a fragment as a registration form a good one? TIA
Here is the image to Illustrate
Here is what it looks like with the title bar
Here is the code for the Main Activity
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
mbtnfragment = FindViewById<Button>(Resource.Id.MyButton);
mbtnfragment.Click += mbtnfragment_Click;
}
void mbtnfragment_Click(object sender, EventArgs e)
{
FragmentTransaction transaction = FragmentManager.BeginTransaction();
create_dialog dialog = new create_dialog();
dialog.Show(transaction, "Fragment Dialog");
Console.WriteLine("Fragment created");
}
Code for the create_dialog class
class create_dialog: DialogFragment
{
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstancesState)
{
base.OnCreateView(inflater, container, savedInstancesState);
var view = inflater.Inflate(Resource.Layout.fragment_dialog, container, false);
return view;
}
public override void OnActivityCreated(Bundle savedInstanceState)
{
Dialog.Window.RequestFeature(WindowFeatures.NoTitle);
base.OnActivityCreated(savedInstanceState);
}
}
}
change the fragment_dialog layout's width from wrap_content to match_parent or a defined size
You can set a style without title to your custom dialog
#Override
public void onCreateDialog(Bundle savedInstanceState) {
setStyle(STYLE_NO_TITLE, 0);
}
Or you can set a theme in the second parameter like Theme.AppCompat.Dialog...