Get html content from webview in Android (using Xamarin with C#) - c#

What I want to do is basically what was answered here:
how to get html content from a webview?
However, I'm working with Xamarin in C#, and the code given in the top answer is in java. I tried to translate it to C# as follows:
public class LoginWebViewController : Activity
{
WebView localWebView;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.WebView);
localWebView = FindViewById<WebView>(Resource.Id.LocalWebView);
localWebView.SetWebViewClient(new JustWebViewClient());
localWebView.LoadUrl(LoginOperations.GetTPLoginUrl());
localWebView.Settings.JavaScriptEnabled = true;
localWebView.AddJavascriptInterface(new MyJavaScriptInterface(this), "HtmlViewer");
}
class MyJavaScriptInterface
{
private Context ctx;
MyJavaScriptInterface(Context ctx)
{
this.ctx = ctx;
}
public void showHTML(String html)
{
Console.WriteLine(html);
}
}
}
But I get the following error:
I tried changing the class to public but it still gives the same error. What is wrong?
Additional code:
public class MyWebViewClient : WebViewClient
{
public override void OnPageFinished(WebView view, String url)
{
base.OnPageFinished(view,url);
Console.WriteLine("DONE LOADING PAGE");
view.LoadUrl("javascript:HtmlViewer.showHTML" +
"('<html>'+document.getElementsByTagName('html')[0].innerHTML+'</html>');");
}
}

Your constructor is not public and you have to inherit from Java.Lang.Object. You have to add the Export attribute, too.
class MyJavaScriptInterface : Java.Lang.Object
{
private Context ctx;
public MyJavaScriptInterface(Context ctx)
{
this.ctx = ctx;
}
public MyJavaScriptInterface(IntPtr handle, JniHandleOwnership transfer)
: base (handle, transfer)
{
}
[Export("showHTML")]
public void showHTML(string html)
{
Console.WriteLine(html);
}
}
And in your javascript code is an error, too. You are missing a opening ( after showHTML.
view.LoadUrl("javascript:HtmlViewer.showHTML(" + ...

Related

Xamarin Android: Set ExpandableListView.SetOnGroupExpandListener

I want to set a listener for ExpandableList. I have searched around but found only android specific following code. How can I convert the following android code to Xamarin.
ExpandableList expListView; // suppose it is initilized
expListView.setOnGroupExpandListener(new IOnGroupExpandListener() {
int previousItem = -1;
#Override
public void onGroupExpand(int groupPosition)
{
if (groupPosition != previousItem)
expandableList.collapseGroup(previousItem);
previousItem = groupPosition;
}
});
You can implement the interface ExpandableListView.IOnGroupExpandListener on the Activity (or Fragment) or as a separate Java-based object.
Activity Example:
public class MainActivity : Activity, ExpandableListView.IOnGroupExpandListener
{
~~~
ExpandableListView expListView;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
expListView.SetOnGroupExpandListener(this);
}
~~~
public void OnGroupExpand(int groupPosition)
{
// implement your onexpand code
}
~~~
}
Separate Class:
public class MyExpander : Java.Lang.Object, ExpandableListView.IOnGroupExpandListener
{
public void OnGroupExpand(int groupPosition)
{
// implement your onexpand code
}
}

UIWebView delegate method LoadFinished not invoked

I am loading a web page in the web view, the view loads properly but the LoadFinished delegate method is not invoked, all other delegate methods are invoked properly. Here is my code
public partial class TestViewController
{
public TestViewController(){}
public override void ViewDidLoad()
{
base.ViewDidLoad();
MyWebViewDelegate webDelegate = new MyWebViewDelegate();
myWebView.Delegate = webDelegate;
string webUrl = "https://www.google.co.in/"
if (Connectivity.CheckForInternetConnection() && webUrl != null)
{
myWebView.LoadRequest(new NSUrlRequest(new NSUrl(webUrl)));
ProgressView.Show();
}
else
{
ProgressView.Hide();
}
myWebView.ScalesPageToFit = true;
}
}
public class MyWebViewDelegate : UIWebViewDelegate
{
public MyWebViewDelegate() : base(){}
public override void LoadFailed(UIWebView webView, NSError error)
{
ProgressView.Hide();
}
public override bool ShouldStartLoad(UIWebView webView, NSUrlRequest request, UIWebViewNavigationType navigationType)
{
return true;
}
public override void LoadingFinished(UIWebView webView)
{
ProgressView.Hide();
}
}
I need to detect the load finish, to hide the progress view, But I don't know what is wrong with my code Please help me. Thanks in Advance

How to call same service instance from multiple activities in Android

I've just started looking into Xamarin and just can not to wrap around my head how to make multiple Activities have a reference same instance of service.
I am starting KeyPressedReceiver from MainActivity and start listening for power button being pressed.
When three click are being made, I am calling service method InitCancelActivity, which starts playing mp3 file and opens CancelActivity.
In CancelActivity there is a text field and a button. And when user press this button, I want the value from text field to be passes to the GeneralService method KillAlert.
The question is how to reference instance of GeneralService (which is already created) from CancelActivity, so I could call KillAlert?
And this part
if (_service == null)
_service = new GeneralService();
looks absolutely wrong. Should I instantiate it in MainActivity and pass to a KeyPressedReceiver constructor?
[Activity(Label = "TTTT", MainLauncher = true, Icon = "#drawable/icon")]
public class MainActivity : Activity
{
KeyPressedReceiver receiver;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
receiver = new KeyPressedReceiver();
RegisterReceiver(receiver, new IntentFilter(Intent.ActionScreenOn));
}
}
[BroadcastReceiver(Enabled = true)]
public class KeyPressedReceiver : BroadcastReceiver
{
private GeneralService _service;
private int _clicks = 0;
public override void OnReceive(Context context, Intent intent)
{
if (_service == null)
_service = new GeneralService();
_clicks++;
if (_clicks > 5)
{
_service.InitCancelActivity();
}
}
}
[Service(Name = "com.ff.GeneralService")]
public class GeneralService : Service {
private readonly Android.Media.MediaPlayer _player;
public GeneralService()
{
_player = new Android.Media.MediaPlayer();
}
public void RaiseAlert()
{
// start playing .mp3 file
}
public void KillAlert(string pass)
{
// stop playing .mp3 file
}
public void InitCancelActivity()
{
this.RaiseAlert();
var i = new Intent(this, typeof(CancelActivity));
i.SetFlags(ActivityFlags.NewTask);
this.StartActivity(i);
}
}
[Activity(Label = "CancelActivity")]
public class CancelActivity : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.cancel);
this.FindViewById(Resource.Id.cancelButtonYes).Click += delegate
{
var password = this.FindViewById(Resource.Id.cancelPassword);
// call KillAlert method from GeneralServic
};
}
}
Create static GeneralService instance and use in Cancel Activity.
for example
[Service(Name = "com.ff.GeneralService")]
public class GeneralService : Service {
private readonly Android.Media.MediaPlayer _player;
public static generalService;
public GeneralService()
{
_player = new Android.Media.MediaPlayer();
generalService=this
}
public void RaiseAlert()
{
// start playing .mp3 file
}
public void KillAlert(string pass)
{
// stop playing .mp3 file
}
public void InitCancelActivity()
{
this.RaiseAlert();
var i = new Intent(this, typeof(CancelActivity));
i.SetFlags(ActivityFlags.NewTask);
this.StartActivity(i);
}
}
and use in CancelActivity like below example
[Activity(Label = "CancelActivity")]
public class CancelActivity : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.cancel);
this.FindViewById(Resource.Id.cancelButtonYes).Click += delegate
{
var password = this.FindViewById(Resource.Id.cancelPassword);
// call KillAlert method from GeneralServic
GeneralService.generalService.KillAlert(password.TEXT);
};
}
}

How to Use interface IValueEventListener in object DatabaseReference Xamarin.Firebase.Database?

I'm new in C# Xamarin. I have a sample Java class here (from this tutorial). It's difficult to me to implement ValueEventListener in C# using xamarin.firebase.database. Would you like to help me? Thank you.
public class ChatInteractor implements ChatContract.Interactor {
private static final String TAG = "ChatInteractor";
#Override
public void sendMessageToFirebaseUser(final Context context, final Chat chat, final String receiverFirebaseToken) {
final DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference();
databaseReference.child(Constants.ARG_CHAT_ROOMS).getRef().addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
#Override
public void getMessageFromFirebaseUser(String senderUid, String receiverUid) {
final DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference();
databaseReference.child(Constants.ARG_CHAT_ROOMS).getRef().addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
First of all: do you have a Xamarin Android Binding for the Firebase Android SDK? If you don't, you can't really follow any Java-Android tutorial, since the Firebase specific classes / interfaces won't exist. If that's the case: install https://www.nuget.org/packages/Xamarin.Firebase.Database/
If you do - implement the interface like that:
(inline implementations - like you can do in java; and it's done in your example - are not supported in C#. So you'll have to create a regular class)
public class MyValueEventListener : Java.Lang.Object, Firebase.Database.IValueEventListener
{
public void OnCancelled(DatabaseError error)
{
throw new NotImplementedException();
}
public void OnDataChange(DataSnapshot snapshot)
{
throw new NotImplementedException();
}
}
and pass it as an eventlistener
DatabaseReference databaseReference = FirebaseDatabase.Instance.Reference;
databaseReference.Child(Constants.ARG_CHAT_ROOMS).Ref.AddListenerForSingleValueEvent(new MyValueEventListener())

How to override OnLaunched() from Template10

I am trying to override the OnLaunched() function in a Template 10 Windows Application, but the problem is that it is sealed in Template 10 BootStrapper class (which inherits from the Application class).
Here's my method:
using Windows.UI.Xaml;
...
namespace Sample {
...
sealed partial class App : Template10.Common.BootStrapper {
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
/*************** My stuff *****************
***********************************************/
}
...
}
I am using Template10 Blank app for this app, and the OnLaunched() method in BootStrapper class is this:
namespace Template10.Common
{
public abstract class BootStrapper : Application
{
...
protected sealed override void OnLaunched(LaunchActivatedEventArgs e);
...
}
...
}
I cannot remove the sealed modifier from OnLaunched() in BootStrapper (guess because it is "from metadata").
What's the point of including a sealed method in an abstract class?
Do we get some other method to override, like OnResume(), OnStartAsync(), etc, instead of OnLaunched()?
Update: For reference, here are all the members in BootStrapper:
public abstract class BootStrapper : Application
{
public const string DefaultTileID = "App";
protected BootStrapper();
public static BootStrapper Current { get; }
public TimeSpan CacheMaxDuration { get; set; }
public INavigationService NavigationService { get; }
public StateItems SessionState { get; set; }
public bool ShowShellBackButton { get; set; }
protected Func<SplashScreen, UserControl> SplashFactory { get; set; }
public event EventHandler<WindowCreatedEventArgs> WindowCreated;
public static AdditionalKinds DetermineStartCause(IActivatedEventArgs args);
public NavigationService NavigationServiceFactory(BackButton backButton, ExistingContent existingContent);
[AsyncStateMachine(typeof(<OnInitializeAsync>d__44))]
public virtual Task OnInitializeAsync(IActivatedEventArgs args);
public virtual void OnResuming(object s, object e);
public abstract Task OnStartAsync(StartKind startKind, IActivatedEventArgs args);
[AsyncStateMachine(typeof(<OnSuspendingAsync>d__45))]
public virtual Task OnSuspendingAsync(object s, SuspendingEventArgs e);
public Dictionary<T, Type> PageKeys<T>() where T : struct, IConvertible;
public virtual T Resolve<T>(Type type);
public virtual INavigable ResolveForPage(Type page, NavigationService navigationService);
public void UpdateShellBackButton();
[AsyncStateMachine(typeof(<OnActivated>d__26))]
protected sealed override void OnActivated(IActivatedEventArgs e);
[AsyncStateMachine(typeof(<OnCachedFileUpdaterActivated>d__27))]
protected sealed override void OnCachedFileUpdaterActivated(CachedFileUpdaterActivatedEventArgs args);
[AsyncStateMachine(typeof(<OnFileActivated>d__28))]
protected sealed override void OnFileActivated(FileActivatedEventArgs args);
[AsyncStateMachine(typeof(<OnFileOpenPickerActivated>d__29))]
protected sealed override void OnFileOpenPickerActivated(FileOpenPickerActivatedEventArgs args);
[AsyncStateMachine(typeof(<OnFileSavePickerActivated>d__30))]
protected sealed override void OnFileSavePickerActivated(FileSavePickerActivatedEventArgs args);
protected sealed override void OnLaunched(LaunchActivatedEventArgs e);
[AsyncStateMachine(typeof(<OnSearchActivated>d__31))]
protected sealed override void OnSearchActivated(SearchActivatedEventArgs args);
[AsyncStateMachine(typeof(<OnShareTargetActivated>d__32))]
protected sealed override void OnShareTargetActivated(ShareTargetActivatedEventArgs args);
protected sealed override void OnWindowCreated(WindowCreatedEventArgs args);
public enum AdditionalKinds
{
Primary,
Toast,
SecondaryTile,
Other
}
public enum BackButton
{
Attach,
Ignore
}
public enum ExistingContent
{
Include,
Exclude
}
public enum StartKind
{
Launch,
Activate
}
}
Please help :}
Template 10 does not allow us to override OnLaunched() method. Instead we can override the OnInitializeAsync() and OnStartAsync() methods for this purpose.
The reason is that Template 10 recommends us to use something called the Single Page Model, which is nothing but using a single instance of the Page class to put in the empty Frame provided by the Framework. How is that benefit to us? Well, if we need to put a menu, say a Hamburger menu, in our app, then we need to copy the code for the menu in each and every page we create in our app. This would lead to things like redundancy, inconsistency, WET code, etc. etc.
Therefore, template 10, initially, creates a Page, which they call the Shell, and then contents of each page is loaded into this Shell page, instead of creating new Pages.
We can override these methods in the following way:
sealed partial class App : BootStrapper
{
public App()
{
this.InitializeComponent();
}
public override Task OnInitializeAsync(IActivatedEventArgs args)
{
var nav = NavigationServiceFactory(BackButton.Attach, ExistingContent.Include);
Window.Current.Content = new Views.Shell(nav);
return Task.FromResult<object>(null);
}
public override Task OnStartAsync(BootStrapper.StartKind startKind, IActivatedEventArgs args)
{
NavigationService.Navigate(typeof(Views.MainPage));
return Task.FromResult<object>(null);
}
}
Here's where I figured the answer:
https://github.com/Windows-XAML/Template10/wiki/Docs-%7C-HamburgerMenu
So, long story short, override OnInitializeAsync() or OnStartAsync(), instead of OnLaunched().
You're trying to override OnLaunched in MyPage.xaml.cs and I'm pretty safe to assume that your MyPage class does not inherit from Application. So it does not have OnLaunched() method (at least not with that signature). What you need to do is override it in App.xaml.cs, as it's Application.OnLaunched(). App class, which is in App.xaml.cs, inherits from Application.
By the way, this is the example from the blank app template, which you've mentioned:

Categories

Resources