Why Data Can not Pass to Second Activity - xamarin.android

Using XamarinStudio and below code base on the Sample in the tutorial. Here the questions.
Do I need to generate the AndroidManifest from the Project Option> Android Application when testing the App ?
Why there is no data passing over even I have generated an AndroidManifest , the code :
---Activity 1
[Activity (Label = "HelloMultiScreen", MainLauncher = true,Icon = "#drawable/icon")]
public class FirstActivity : Activity
{
int count = 1;
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
//Use UI created in Main.axml
SetContentView (Resource.Layout.Main);
var showSecond = FindViewById (Resource.Id.showSecond);
showSecond.Click += (sender, e) => {
var second = new Intent(this, typeof(SecondActivity));
second.PutExtra("FirstData", "Data from FirstActivity");
StartActivity (typeof(SecondActivity));
};
}
}
---Activity 2
[Activity (Label = "SecondActivity")]
public class SecondActivity : Activity
{
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
// Create your application here
SetContentView (Resource.Layout.Second);
var label = FindViewById (Resource.Id.screen2Label);
label.Text = Intent.GetStringExtra("FirstData") ?? "Data not available";
}
}
Thanks

Ok I found the problem when I remade the project myself.
The problem lies in this piece of code:
var second = new Intent(this, typeof(SecondActivity));
second.PutExtra("FirstData", "Data from FirstActivity");
StartActivity (typeof(SecondActivity));
What happens is that you make an Intent with the right data. But you start a new activity without that data.
To fix it change the code to this:
var second = new Intent(this, typeof(SecondActivity));
second.PutExtra("FirstData", "Data from FirstActivity");
StartActivity(second);`

Related

OnCreateContextMenu not working with webview

i have web-view that i need to create for it context menu when click on link type this what i did :
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.Webview);
wv = (WebView)FindViewById(Resource.Id.WV);
RegisterForContextMenu(wv);
wv.SetWebChromeClient(new WebChromeClient());
wv.SetWebViewClient(new WebViewClient());
wv.Settings.JavaScriptEnabled = true;
wv.Settings.DomStorageEnabled = true;
wv.Settings.SetSupportZoom(true);
wv.Settings.DisplayZoomControls = false;
wv.Settings.BuiltInZoomControls = true;
wv.Settings.CacheMode = CacheModes.Default;
wv.Settings.UseWideViewPort = true;
wv.Settings.LoadWithOverviewMode = true;
wv.SetInitialScale(1);
wv.LoadUrl("file:///android_asset/index.html");
}
public override void OnCreateContextMenu(IContextMenu menu, View v, IContextMenuContextMenuInfo menuInfo)
{
base.OnCreateContextMenu(menu, v, menuInfo);
WebView webView = (WebView)v;
result = webView.GetHitTestResult();
if (result.GetType().ToString().Equals("SRC_ANCHOR_TYPE") || result.GetType().ToString().Equals("ANCHOR_TYPE"))
{
var item = menu.Add("copylink");
item.SetOnMenuItemClickListener(this);
}
}
but "result.GetType()" its its not detect anchor type link the "result.GetType()" is not detect any link in webview when it get pressed longtoch..
If you want to add a item to the menu, you should override OnActionModeStarted method. then add the SetOnMenuItemClickListenerlike following code.
public override void OnActionModeStarted(ActionMode mode)
{
IMenu menu = mode.Menu;
menu.Add("Add To Notes");
menu.GetItem(0).SetOnMenuItemClickListener(new MyMenuItemOnMenuItemClickListener(this));
base.OnActionModeStarted(mode);
}
internal class MyMenuItemOnMenuItemClickListener : Java.Lang.Object, IMenuItemOnMenuItemClickListener
{
private MainActivity mainActivity;
public MyMenuItemOnMenuItemClickListener(MainActivity mainActivity)
{
this.mainActivity = mainActivity;
}
public bool OnMenuItemClick(IMenuItem item)
{
Toast.MakeText(mainActivity, "You click the Add To Notes", ToastLength.Short).Show();
return true;
}
}
Here is running GIF.
If you want to create a new menu, you can use menu.Clear();
public override void OnActionModeStarted(ActionMode mode)
{
IMenu menu = mode.Menu;
menu.Clear();
menu.Add("Add To Notes");
menu.GetItem(0).SetOnMenuItemClickListener(new MyMenuItemOnMenuItemClickListener(this));
base.OnActionModeStarted(mode);
}
Here is running screenshot.
Update
If you want to get the Type of long click, you should make sure type of result.Type is Webkit.HitTestResult, you use result.GetType(), Type is System.Type. So you can get the correct type, you can refer to the following code.
WebView.HitTestResult result = webView.GetHitTestResult();
Android.Webkit.HitTestResult myresult = result.Type;
You can refer to the debug gif.

The attribute android:onClick="FabOnClick" crashes app when Floating Action Button clicked

There doesn't appear to be a lot of people using Xamarin for Visual Studio consequently there isn't a lot of information specific to that platform out there.
Having said that, I've been trying to get a Floating Action Button (FAB) to work and it's been quite the exercise. I finally got it to appear and assign it to a variable in the activity with help from the nice folks who use StackOverflow, but cannot get the android:onClick="FabOnClick" call to work. Clicking on the FAB causes the app to crash with the error:
Unhandled Exception:
Java.Lang.IllegalStateException: Could not find method FabOnClick(View) in a parent or ancestor Context for android:onClick attribute defined on view class android.support.design.widget.FloatingActionButton with id 'fab' occurred
This is the code in my activity:
public void FabOnClick(View v)
{
int x = 1;
}
It doesn't really do anything because I'm just trying to capture the click event for now. I set a breakpoint on the int x = 1 line to see when it's is executed. So what am I missing?
* Update *
I updated my activity code based on #Digitalsa1nt's answer below:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Acr.UserDialogs;
using Android.Net;
using System.Net;
using Android.Support.Design.Widget;
using System.Threading.Tasks;
using Android.Views.InputMethods;
using static Android.Views.View;
namespace OML_Android
{
[Activity(Label = "CreateAccount")]
public class CreateAccount : Activity
{
public string result = "";
public EditText aTextboxUsername;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.CreateAccount);
RequestedOrientation = Android.Content.PM.ScreenOrientation.Portrait;
aTextboxUsername = FindViewById<EditText>(Resource.Id.aTextboxUsername);
EditText aTextboxPassword = FindViewById<EditText>(Resource.Id.aTextboxPassword);
EditText aTextboxPassword2 = FindViewById<EditText>(Resource.Id.aTextboxPassword2);
EditText txtEmailAddress = FindViewById<EditText>(Resource.Id.txtEmailAddress);
EditText txtEmailAddress2 = FindViewById<EditText>(Resource.Id.txtEmailAddress2);
EditText txtFirstName = FindViewById<EditText>(Resource.Id.first_name);
EditText txtMI = FindViewById<EditText>(Resource.Id.mi);
EditText txtLastName = FindViewById<EditText>(Resource.Id.last_name);
EditText txtAddress = FindViewById<EditText>(Resource.Id.address);
EditText txtCity = FindViewById<EditText>(Resource.Id.city);
Spinner spnState = FindViewById<Spinner>(Resource.Id.state);
EditText txtZip = FindViewById<EditText>(Resource.Id.zip);
MaskedEditText.MaskedEditText txtPhone = FindViewById<MaskedEditText.MaskedEditText>(Resource.Id.phone);
Spinner spnCompany = FindViewById<Spinner>(Resource.Id.company_spinner);
Spinner spnDept = FindViewById<Spinner>(Resource.Id.department_spinner);
Spinner spnSection = FindViewById<Spinner>(Resource.Id.section_spinner);
Button ButtonSubmit = FindViewById<Button>(Resource.Id.button_submit);
ScrollView sv = FindViewById<ScrollView>(Resource.Id.scrollView1);
ButtonSubmit.SetBackgroundColor(Android.Graphics.Color.YellowGreen);
// Hide the keyboard (also doesn't work)
InputMethodManager board = (InputMethodManager)GetSystemService(Context.InputMethodService);
board.HideSoftInputFromWindow(aTextboxUsername.WindowToken, 0);
// get the floating action button.
FloatingActionButton myFab = FindViewById< FloatingActionButton>(Resource.Id.fab);
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
DataInterfaceWeb.DataInterface myService = new DataInterfaceWeb.DataInterface();
myFab.Click += FabButton_Click(); // <-- get error here
try
{
ConnectivityManager connectivityManager = (ConnectivityManager)GetSystemService(ConnectivityService);
NetworkInfo activeConnection = connectivityManager.ActiveNetworkInfo;
bool isOnline = (activeConnection != null) && activeConnection.IsConnected;
if (!isOnline)
{
showMessage("There is no internet or cell phone connection. Connect to a network or connect to a cellular network.", "ERROR");
}
}
catch (Exception ex)
{
showMessage("Connectivity Manager failed to create a connection due to error: " + ex.Message, "ERROR");
};
// Create your application here
ButtonSubmit.Click += async (sender, e) =>
{
try
{
result = myService.CheckForUser(Master.username, Master.password, aTextboxUsername.Text);
if (result.ToUpper() == "Y")
{
await showMessage("Username " + aTextboxUsername.Text + " is already in use. Please choose another", "ERROR");
// aTextboxUsername.SetSelectAllOnFocus(true);
aTextboxUsername.RequestFocus();
View insideView = FindViewById<EditText>(Resource.Id.aTextboxUsername);
sv.ScrollTo(0, (int)insideView.GetY());
aTextboxUsername.SelectAll();
}
}
catch (Exception ex)
{
showMessage("Account creation attempt failed due to error: " + ex.Message, "ERROR");
}
};
}
public async Task showMessage(string message, string messageType)
{
var result = await UserDialogs.Instance.ConfirmAsync(new ConfirmConfig
{
Message = messageType + System.Environment.NewLine + message,
OkText = "Ok",
});
}
public void FabButton_Click()
{
int x = 1;
}
}
}
The error I get now is:
Cannot implicitly convert 'void' to 'SystemEventHandler' on the line myFab.Click += FabButton_Click();.
#Digitalsa1nt did point me in the right direction. Instead of
fabButton.Click += FabButton_Click;
I just wired up an event, as the error suggested (duh):
myFab.Click += (sender, e) =>
{
FabButton_Click();
};
It now works as I would expect.
So I'm making a couple of assumptions in this answer. Firstly that you are working with a Xamarin.Native project and not a Xamarin.Forms project.
Secondly I am assuming you are using the FloatingActionButton from one of the support libraries such as: Android.Support.Design.Widget (base / V4 / V7).
Once you've defined your FAB within the AXML Layout page:
<android.support.design.widget.FloatingActionButton
app:backgroundTint="#color/colourPrimary"
android:id="#+id/fabButton"
android:src="#drawable/image"
app:fabSize="normal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:elevation="16dp"
android:translationZ="12dp"
app:rippleColor="#ffa9a9a9" />
You can get it from within your activity as such:
using Android.Support.Design.Widget;
// declare variable
private FloatingActionButton fabButton;
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
// call base
base.OnCreateView(inflater, container, savedInstanceState);
// inflate our view
var view = inflater.Inflate(Resource.Layout.MainTabWishlistPage, container, false);
// get our instance of the button using the resource ID.
fabButton = view.FindViewById<FloatingActionButton>(Resource.Id.fabButton);
// assign to click event
fabButton.Click += FabButton_Click;
}
private void FabButton_Click(object sender, EventArgs e)
{
int x = 1;
}
The above example is based on it being a fragment rather than an activity, but the methodology is the same.
Official Git Repo:
Xamarin/monodroid-samples - Floating Action Button Basic
Random online guide:
android-material-design-floating-action
In case this is a Xamarin.Forms project, look into James Montemagno's library (p.s one of the developers that works on Xamarin and creates tons of libraries to help make your life easier, definitely look through his other repos.)
jamesmontemagno/FloatingActionButton-for-Xamarin.Android

Can I bind the return to a condition?

I have the following problem:
My method opens a JDialog with a bunch of buttons (only one in example code). I want to click a button and thereby choose an ImageIcon for my method to return. But the Method does not wait for me to click a button. It opens the window and then returns an empty ImageIcon.
public class Kartenauswahl {
ImageIcon bandit;
public ImageIcon auswahlfenster() {
int bwidth = new Integer(150);
int bheight = new Integer(225);
bandit = new ImageIcon("cover/Bandit.jpe");
bandit.setImage(bandit.getImage().getScaledInstance(bwidth,bheight,Image.SCALE_DEFAULT));
final JDialog kartenwahl = new JDialog();
kartenwahl.setTitle("Kartenwahl");
kartenwahl.setSize(1500,1000);
kartenwahl.setVisible(true);
kartenwahl.setLayout(new FlowLayout());
ImageIcon returnicon= new ImageIcon();
final JButton b1 = new JButton(); //just to get the Icon out of the void loop
JButton B1 = new JButton(bandit); //this is going to be the button I want to click to choose the ImageIcon which is returned
B1.setContentAreaFilled(false);
B1.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
b1.setIcon(bandit);
kartenwahl.dispose();
}
});
kartenwahl.add(B1);
returnicon = (ImageIcon) b1.getIcon();
return returnicon;
}
}
Question: can I bind the return statement to a condition? Like "only return after I clicked that Button B1"?
Hi sorry for the long wait. I have written an custom JDialog that should work for you.
public class CustomDialog extends JDialog {
JButton[] buttons;
ImageIcon selectedImageIcon;
public CustomDialog() {
setSize(500, 500);
setLayout(new GridLayout(4, 6));
ActionListener actionListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
selectedImageIcon = ((ImageIcon) ((JButton) e.getSource()).getIcon());
dispose();
}
};
buttons = new JButton[24];
for(int i = 0; i < 24; i++) {
buttons[i] = new JButton(new ImageIcon("path_to_your_image_file"));
buttons[i].addActionListener(actionListener);
add(buttons[i]);
}
setVisible(true);
}
public ImageIcon getSelectedImageIcon() {
return selectedImageIcon;
}
}
The initial size is not that important the GridLayout is. you mentioned that you would need 24 buttons so I created an grid with 4 rows and 6 columns.
Then I create the buttons in a loop and adding the same Listener to set the selection icon with the icon of the pressed button. Afterwards I dispose the screen triggering an windowClosed event.
You could simply create this Dialog from your main class and wait for the response like so:
public class main {
public static void main(String[] args) {
CustomDialog customDialog = new CustomDialog();
customDialog.addWindowListener(new WindowAdapter() {
#Override
public void windowClosed(WindowEvent e) {
ImageIcon icon = customDialog.getSelectedImageIcon();
//do something with your icon
}
});
}
}
Don't forget to mark this answer as correct if it fixes your problem.
Have a good one!

Auto OTP verification android xamarin

I am working on an Android App using Xamarin, in which server sends an OTP and the user needs to enter this OTP in the App, to SignUp for my App. What I want is, that my App should be able to automatically read the OTP sent by the server and to be filled in edit text field of OTP.
I'm almost done to read the message but unable to set the otp in edit text field.
SMS broadcast receiver class:
[BroadcastReceiver(Enabled = true, Label = "SMS Receiver")]
[IntentFilter(new string[] { "android.provider.Telephony.SMS_RECEIVED" })]
public class SMSBroadcastReceiver : BroadcastReceiver
{
private const string IntentAction = "android.provider.Telephony.SMS_RECEIVED";
public override void OnReceive(Context context, Intent intent)
{
try
{
if (intent.Action != IntentAction) return;
var bundle = intent.Extras;
if (bundle == null) return;
var pdus = bundle.Get("pdus");
// var castedPdus = JNIEnv.GetArray(pdus.Handle);
var castedPdus = JNIEnv.GetArray<Java.Lang.Object>(pdus.Handle);
var msgs = new SmsMessage[castedPdus.Length];
var sb = new StringBuilder();
string sender = null;
for (var i = 0; i < msgs.Length; i++)
{
var bytes = new byte[JNIEnv.GetArrayLength(castedPdus[i].Handle)];
JNIEnv.CopyArray(castedPdus[i].Handle, bytes);
string format = bundle.GetString("format");
msgs[i] = SmsMessage.CreateFromPdu(bytes,format);
if (sender == null)
sender = msgs[i].OriginatingAddress;
sb.Append(string.Format("SMS From: {0}{1}Body: {2}{1}", msgs[i].OriginatingAddress,System.Environment.NewLine, msgs[i].MessageBody));
Toast.MakeText(context, sb.ToString(), ToastLength.Long).Show();
}
}
catch (System.Exception ex)
{
Toast.MakeText(context, ex.Message, ToastLength.Long).Show();
}
}
}
Here is my main activity:
[Activity(Label = "UserSms", MainLauncher = true, Icon = "#drawable/icon")]
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);
SMSBroadcastReceiver smsReceiver = new SMSBroadcastReceiver();
TextView msg = FindViewById<TextView>(Resource.Id.editTextOtp);
Button btn = FindViewById<Button>(Resource.Id.button3);
RegisterReceiver(smsReceiver, new IntentFilter("android.provider.Telephony.SMS_RECEIVED"));
}
}
How can I achieve this? Any help or guidance in this regard would be highly appreciated.
Update
public void onSMSReceived(string msgs)
{
EditText OtpNumber = (EditText)FindViewById(Resource.Id.editTextOtp);
try
{
OtpNumber.SetText(msgs.ToString(),null);
}
catch (System.Exception ex)
{
}
}
Your are on the finishing line. You only need to do these thing:
Create an interface which will have public method onSMSReceived(String smsMsg)
Instantiate that interface.
Implement that interface in MainActivity activity.
Override onSMSReceived(String smsMsg) in your MainActivity
Notify MainActivity using above created interface from your SMS Broadcast Receiver.
Populate message received in onSMSReceived(String smsMsg) in your MainActivity.
You are done.
I didn't get exactly how you're doing it, but i did in two ways,
1.User has to enter it manually,
2.We have to read automatically through the programming,
But i faced one problem in reading sms automatically, like sending sms and reading sms are calling at the same time may be like register click event, I found one more way to detect automatically like sending otps two times and storing generated otps in a list of string and comparing with message.body
Here the problem is we have to send otp two times, still i'm figuring out how to call reading sms part after sometime,,,!
If you want that solution plz mail me at sailokeshgoud#gmail.com

Change "Active" icon on selected NavigationPage when using TabbedPage

I'm very, very new to Xamarin.Forms. My task, if it is possible, and I'm not sure if it is, is to change our icon from the default blue when it is active.
I was given icons that are orange and they would like to display those or at least the color instead of the default blue. Again, I'm not sure if this is possible.
This is the code I'm using for the tabbed page.
public class LandingPage : TabbedPage
{
public LandingPage ()
{
NavigationPage homepage = new NavigationPage (new CarouselPage {
Title = "Title",
Children = {
//code removed
}
});
NavigationPage eventspage = new NavigationPage (new ContentPage {
Title = "Calendar Event List",
Content = new EventList ()
});
NavigationPage morepage = new NavigationPage (new MorePage ());
homepage.BarBackgroundColor = Device.OnPlatform (Color.FromHex (DependencyService.Get<IContentStrings>().BarBackgroundColor), Color.Transparent, Color.Transparent);
homepage.BarTextColor = Color.FromHex(DependencyService.Get<IContentStrings>().BarTextColor);
homepage.Title = DependencyService.Get<IContentStrings>().HomeTitle;
homepage.Icon = DependencyService.Get<IContentStrings>().HomeImage;
eventspage.BarBackgroundColor = Device.OnPlatform (Color.FromHex (DependencyService.Get<IContentStrings>().BarBackgroundColor), Color.Transparent, Color.Transparent);
eventspage.BarTextColor = Color.FromHex(DependencyService.Get<IContentStrings>().BarTextColor);
eventspage.Title = DependencyService.Get<IContentStrings>().EventTitle;
eventspage.Icon = DependencyService.Get<IContentStrings>().EventImage;
morepage.BarBackgroundColor = Device.OnPlatform (Color.FromHex (DependencyService.Get<IContentStrings>().BarBackgroundColor), Color.Transparent, Color.Transparent);
morepage.BarTextColor = Color.FromHex(DependencyService.Get<IContentStrings>().BarTextColor);
morepage.Title = DependencyService.Get<IContentStrings>().MoreTitle;
morepage.Icon = DependencyService.Get<IContentStrings>().MoreImage;
Children.Add (homepage);
Children.Add (eventspage);
Children.Add (morepage);
}
}
I'm not sure if I'm able to use a custom renderer or anything. I do not know if I have any options and any guidance is greatly appreciated!
You can set the active tab icon color with a simple custom iOS renderer like this:
[assembly: ExportRenderer(typeof(TabbedPage), typeof(MyTabbedPageRenderer))]
namespace MyApp.iOS.Renderers
{
public class MyTabbedPageRenderer : TabbedRenderer
{
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
TabBar.TintColor = UIColor.Orange;
}
}
}
I found was finally able to find the answer after searching the internet a few hours and then coming back to the app on a different day. To change the default from the blue, I changed the UITabbar tint color in the AppDelegate.
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
UIApplication.SharedApplication.SetStatusBarStyle (UIStatusBarStyle.LightContent, false);
global::Xamarin.Forms.Forms.Init ();
LoadApplication (new App ());
//this changes the default iOS tintcolor for the icon when it's activated
UITabBar.Appearance.TintColor = UIColor.FromRGB(223, 112, 13);
return base.FinishedLaunching (app, options);
}

Resources