The speech is working fine on my real device.
using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using Android.Speech.Tts;
namespace App7
{
[Activity(Label = "App7", MainLauncher = true, Icon = "#drawable/icon")]
public class MainActivity : Activity, TextToSpeech.IOnInitListener
{
public TextToSpeech SpeechText
{
get;
set;
}
int count = 1;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
// create text to speech object to use synthesize and speak functions.
// first parameter: context
// second parameter: object implemeting TextToSpeech.IOnInitListener
this.SpeechText = new TextToSpeech(this, this);
Button testButton = FindViewById<Button>(Resource.Id.button1);
testButton.Click += delegate
{
this.SpeechText.Speak("Hello World, You shall not pass", QueueMode.Flush, null);
};
// Get our button from the layout resource,
// and attach an event to it
Button button = FindViewById<Button>(Resource.Id.MyButton);
button.Click += delegate { button.Text = string.Format("{0} clicks!", count++); };
}
public void OnInit(OperationResult status)
{
// here you can setup language settings
if (status.Equals(OperationResult.Success))
Toast.MakeText(this, "Text To Speech Succeed!", ToastLength.Long).Show();
else
Toast.MakeText(this, "Text To Speech Fail", ToastLength.Long).Show();
}
}
}
The warning is on this line:
this.SpeechText.Speak("Hello World, You shall not pass", QueueMode.Flush, null);
Under this line there is a green line and the warning message is:
Warning 1 'Android.Speech.Tts.TextToSpeech.Speak(string, Android.Speech.Tts.QueueMode, System.Collections.Generic.IDictionary)' is obsolete: 'deprecated'
Tried to google didn't find anything.
I can ignore it but I would like to know what does it mean ? And how can I fix it ?
It means this overload is deprecated in Xamarin (because Google marked it as deprecated as of API level 21).
Use the other two overloads (1, 2) that aren't deprecated if the warning bothers you and your target API level allows it, or just ignore the warning.
Related
I can't get OnNewIntent to fire. I've read dozens of articles on the issue and tried all combinations of code.
Regardless of whether I use LaunchMode.SingleTask or SingleTop it won't fire and always passes through the OnCreate method.
What am I doing wrong here? Am I missing something? What do I need to add to get it to work?
using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.OS;
using Android.Runtime;
using System;
using System.Threading.Tasks;
using Xamarin.Forms;
using static MyApp.ClipboardMgr;
namespace MyApp.Droid
{
//[Activity(Label = "SplashActivity")]
[Activity(LaunchMode = LaunchMode.SingleTask, Theme = "#style/Theme.Splash",
MainLauncher = true, NoHistory = true)]
//Can't get this to work with LaunchMode.SingleTop or SingleTask. Always creates a new instance.
[IntentFilter(new[] { Intent.ActionProcessText },
Categories = new[] { Intent.CategoryDefault },
DataMimeType = #"text/plain", Icon = "#drawable/icon", Label = "MyApp")]
public class SplashActivity : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
try
{
//taking these out for readability
//AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
//TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
//AndroidEnvironment.UnhandledExceptionRaiser += AndroidEnvironment_UnhandledExceptionRaiser;
base.OnCreate(savedInstanceState);
// Create your application
StartActivity(typeof(MainActivity));
//don't want to do this here, better to do it in event
if (Intent.Action == Intent.ActionProcessText)
{
//always comes here
HandleProcessTextIntent();
}
}
catch(Exception e)
{
App.LogException(e);
throw;
}
}
/// <summary>
/// this is not firing!
/// </summary>
/// <param name="intent"></param>
protected override void OnNewIntent(Intent intent)
{
base.OnNewIntent(intent);
HandleProcessTextIntent();
}
void HandleProcessTextIntent()
{
string input = Intent.GetStringExtra(Intent.ExtraProcessText).Trim();
if (input == string.Empty)
return;
ClipMgr.SetText(input);
}
}
}
You didn't miss anything since when I test with my own intent to start your activity, it works well and the OnNewIntent() is called when SingleTask or SingleTop used, here's how I call the activity from another project(I did this in native Android):
ComponentName component = new ComponentName("com.example.textHandlerDemo", "com.example.textHandlerDemo.TextHandlerActivity");
Intent intent = new Intent();
intent.setAction(Intent.ACTION_PROCESS_TEXT);
intent.setComponent(component);
startActivity(intent);
I did some research and find something that may explain why the OnNewIntent() never gets fired:
According to the guidance of ACTION_PROCESS_TEXT, it mentioned:
You can use this as a hint to offer the ability to return altered text to the sending app, replacing the selected text. This works as your Activity was actually started with startActivityForResult()
So, when you click your app's label in the floating text selection toolbar, Android will start your activity registered with ActionProcessText with startActivityForResult(), and by using startActivityForResult(), your activity will be started as a sub-activity of current activity(implied from Android doc of startActivityForResult), that is to say, rather than redirecting to your app which is already running, Android will put your activity into current app's stack.
This way, your target activity will still be called from OnCreate() since it's isolated from your running app.
Moreover, the floating text selection toolbar is used to provide a quick in-app experience for text operations like translation as mentioned in this blog, I didn't find any swich to enable/disable redirect to app, you may need to handle the intent in both OnCreate() and OnNewIntent() if you're using LaunchMode.SingleTask or SingleTop.
i'm working on an android app at the moment that has the purpose of playing a particular song at exactly midnight. I know that there might already be apps in the appstore that serve that purpose, but I'm new to coding and wanted to try to program the app myself.
So now I reached the point where I don't know what to do anymore. I tried debugging the App on my LG H818P running Android 6.0. It posted, The Icon, the Name and everything were correct, but i didn't play the song, even when i set the time when it should've played it to two minutes after the start if the building.
So that's the code of the MainActivity.cs in Visual Studio 2017, can anyone find any errors?
using Android.App;
using Android.Widget;
using Android.OS;
using System;
using Android.Media;
namespace Name of the App
{
[Activity(Label = "Name of the App", MainLauncher = true)]
public class MainActivity : Activity
{
string text = "status";
protected void onCreate(Bundle savedInstanceState)
{
}
public void main()
{
try
{
string systemtime = DateTime.Now.ToString();
for (int i = 0; i > 0; i++)
{
if (systemtime == "09:07:00 pm")
{
StartPlayer();
player.Start();
}
}
}
catch
{
text = "Error!";
}
}
protected MediaPlayer player;
public void StartPlayer()
{
if (player == null)
{
player = new MediaPlayer();
player.SetDataSource("Ressources.raw.file2beplayed.mp3");
player.Prepare();
player.Start();
text = "Playing!";
}
else
{
player.Reset();
player.SetDataSource("Ressources.raw.file2beplayed.mp3");
player.Prepare();
player.Start();
}
}
}
}
As I said, I'm a Noob in coding, so sorry for the maybe ugly code :)
Thanks for your replies!
The default format for ToString in a DateTime is MM/dd/yyyy, so your comparation systemtime == "09:07:00 pm" will never be true.
You can use a TimeSpan and the property TimeOfDay from DateTime;
if(DateTime.Now.TimeOfDay == new Timespan(21,7,0))
//...
Also, your loop will never be executed as you initialize i as 0, so at the first check i will not be greater than 0 so the loop isn't executed.
Finally, Android does not use the main function, is an special type of program, your initialization code should be in the OnCreate function, but if you create an infinite loop in that function Android will close the application as it will not finish it's initialization, you need to use a timer and check the condition each second.
I'm writing an app in Xamarin Android, that is supposed to print the LAN address of the device using the app.
Here is what I try:
using System;
using Android.OS;
using Android.App;
using Android.Views;
using Android.Widget;
using Android.Net.Wifi;
using Android.Content;
using Java.Util;
using Java.Net;
namespace checks
{
[Activity(Label = "checks", MainLauncher = true, Icon = "#drawable/icon")]
public class MainActivity : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView (Resource.Layout.Main);
Button dataButton = FindViewById<Button>(Resource.Id.connectionDataButton);
dataButton.Click += (object sender, EventArgs e) =>
{
WifiManager wifiManager = (WifiManager)GetSystemService(Context.WifiService);
var d = wifiManager.DhcpInfo;
Console.WriteLine("My IP IS: {0}",d.IpAddress);
};
}
}
}
I keep getting: MY IP IS: 0
Can anybody tell me what's wrong?
You should check if any wifi network is available first, if not, DhcpInfo.ipAdress returns 0.
After I've added the Done button on iOS numeric keyboard in Xamarin Forms, I encountered another problem: the Done button not firing Completed event (like return button does).
On my way to implement this, I found the following code on Xamarin Forums:
using System;
using System.Drawing;
using System.Reflection;
using Xamarin.Forms.Platform.iOS;
using Xamarin.Forms;
using UIKit;
using KeyboardTest.iOS;
using KeyboardTest;
[assembly: ExportRenderer(typeof(EntryDone), typeof(EntryDoneRenderer))]
namespace KeyboardTest.iOS
{
public class EntryDoneRenderer : EntryRenderer
{
// used to cache the MethodInfo so we only have the reflection hit once
private MethodInfo baseEntrySendCompleted = null;
public EntryDoneRenderer ()
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged (e);
if (this.Element.Keyboard == Keyboard.Numeric)
{
// only want the Done on the numeric keyboard type
UIToolbar toolbar = new UIToolbar (new RectangleF (0.0f, 0.0f, (float)Control.Frame.Size.Width, 44.0f));
var doneButton = new UIBarButtonItem (UIBarButtonSystemItem.Done, delegate {
this.Control.ResignFirstResponder ();
Type baseEntry = this.Element.GetType();
if(baseEntrySendCompleted==null)
{
// use reflection to find our method
baseEntrySendCompleted = baseEntry.GetMethod("SendCompleted",BindingFlags.NonPublic|BindingFlags.Instance);
}
try
{
baseEntrySendCompleted.Invoke(this.Element,null);
}
catch (Exception ex)
{
// handle the invoke error condition
}
});
toolbar.Items = new UIBarButtonItem[] {
new UIBarButtonItem (UIBarButtonSystemItem.FlexibleSpace),
doneButton
};
this.Control.InputAccessoryView = toolbar;
}
}
}
}
I don't know why, but I receive the error:
System.NullReferenceException: Object reference not set to an instance of an object
at myGame.iOS.DoneEntryRenderer.<OnElementChanged>m__0 (System.Object , System.EventArgs ) [0x0005d] in /Users/silviu/Projects/myGame/iOS/DoneEntry.cs:37
On that line I have the code:
baseEntrySendCompleted.Invoke(this.Element, null);
I’ve tried to debug the problem and I found that the SendCompleted method does not exist, but I don’t understand how to solve this problem in the lastest version of Xamarin, because I think on the moment when that guy posted the code, worked.
Thanks!
SendCompleted() was actually added for IEntryController so you don't need to use reflection for this any longer. In fact it appears that way no longer works. Just call SendCompleted() directly from your button press like so.
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
var toolbar = new UIToolbar(new CGRect(0.0f, 0.0f, Control.Frame.Size.Width, 44.0f));
toolbar.Items = new[]
{
new UIBarButtonItem(UIBarButtonSystemItem.FlexibleSpace),
new UIBarButtonItem(UIBarButtonSystemItem.Done, delegate {
Control.ResignFirstResponder();
((IEntryController)Element).SendCompleted();
})
};
this.Control.InputAccessoryView = toolbar;
}
I have this code:
using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using Android.Speech.Tts;
using System.Collections.Generic;
namespace SayItAndroid{ [Activity (Label = "SayItAndroid", MainLauncher = true)]
public class Activity1 : Activity, TextToSpeech.IOnInitListener
{
int count = 1;
TextToSpeech mTts;
public void OnInit (int status)
{
Console.WriteLine ("Listening to text to speech");
}
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);// Set our view from the "main" layout resource
SetContentView (Resource.Layout.Main);
Intent checkIntent = new Intent();
checkIntent.SetAction(TextToSpeech.Engine.ActionCheckTtsData);
StartActivityForResult(checkIntent, 100); // Get our button from the layout resource, // and attach an event to it
Button button = FindViewById<Button> (Resource.Id.myButton);
button.Click += delegate
{
string myText1 = "Did you sleep well?";
string myText2 = "I hope so, because it's time to wake up.";
mTts.Speak(myText1, QueueMode.Add, new Dictionary<string, string>());
mTts.Speak(myText2, QueueMode.Flush, new Dictionary<string, string>());
};
}
protected override void OnActivityResult (int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult (requestCode, resultCode, data);
if(requestCode == 100)
{
mTts = new TextToSpeech(this, this);
}
}
}}
But on the two places i have Resource im getting red line error under the Resource:
Error 1 The name 'Resource' does not exist in the current context
How can i solve it ?
Thanks.
The reason that Resource cannot be found is 9 out of 10 times because the Resource is not in the same namespace as the file you are referring it from.
As stated on this page by Xamarin, the project's default namespace is used to store the generated Resource class file in.
If your class resides in another namespace things break.
Hope that clears things up for you.