startRecording() called on an uninitialized AudioRecord? - android-asynctask

I have below code that gives init failure:
recorder = new AudioRecord(AudioSource.MIC, mSamplingRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, iN);
recorder.startRecording();
It's called by my Activity:
new AsyncTask<Void, Void, Void>(){
#Override
protected Void doInBackground(Void... none) {
record();
return null;
}
}.execute();
It gives below exception:
E/AudioRecord: AudioFlinger could not create record track, status: -1
E/AudioRecord-JNI: Error creating AudioRecord instance: initialization check failed with status -1.
E/android.media.AudioRecord: Error code -20 when initializing native AudioRecord object.
E/AudioRecord: AudioFlinger could not create record track, status: -1
E/AudioRecord-JNI: Error creating AudioRecord instance: initialization check failed with status -1.
E/android.media.AudioRecord: Error code -20 when initializing native AudioRecord object.
What could have gone wrong, please?
I believe it's not the problem of the audio recorder, but about async task/ multithreading. Because it works like charm before when I had a fragment including an onCreateView, and I put the AsyncTask call in onClick of a button.
Now I initial the UI in my activity's OnCreate(), I don't have fragment or onCreateView, I thought I'm already using a async thread but still...

Solved - repushing the apk from Android Studio after changing the permissions in the manifest doesn't actually change the permission in the app settings.
I have to manually open Settings ->> App -> Permissions -> slide "Microphone to be on.

Related

xamarin convert long running procedure to asynchronous

My app contains a procedure which could be long-running. I would like to give users the opportunity to stop it.
The procedure is:
void longRunningProcedure()
(it does not access the file system or the Internet)
And within it, once certain variables are initialized, it calls doIt();
I tried this:
async void longRunningProcedure()
and within this procedure, I have tried:
await Task.Run(() => doIt());
and have tried:
await Task.Run(async () => await doIt());
But when the code reaches this point I get this error:
The selected debug engine does not support any code executing on the current thread (e.g. only native runtime code is executing).
Unhandled Exception:
Android.Util.AndroidRuntimeException: <Timeout exceeded getting exception details> occurred
The long-running code doesn't even run at all.
What to do?
I changed the void longRunningProcedure() to async void, like below:
async void runLongRunningProcedure()
{
await Task.Run(() => actualProcedure());
for my app, the actualProcedure() is just:
void actualProcedure()
Now, apart from this code, I have a variable,
bool cancelPressed
which starts off as false
I have a button and a menu item which sets this to true when pushed or clicked.
And this all works. I can kick off the procedure and stop it with the button or menu click.
There was another issue: The long running procedure writes data to one of the app's text boxes.
Doing that resulted in this error:
The selected debug engine does not support any code executing on the current thread (e.g. only native runtime code is executing).
SO, I had to modify the data writing section to this:
RunOnUiThread( () => {
txtBox.Text += modifiedData.ToString();
});
modifiedData is a StringBuilder type of variable.
And, this all works.
At the appropriate moment during the procedure I have:
if (cancelPressed == true) return
Just to be safe, I enclosed this in try/catch.
Of course if I wanted to notify the user that the procedure was cancelled (or anything else while it is running) via a Toast message I have to do this:
RunOnUiThread(() => {
MakeToast(Message);
return;
});
I have a procedure called MakeToast which handles the message formatting, etc.

How to fix System.Reflection.TargetInvocationException in Xamrin google maps

I'm setting the Xamarin.Forms.GoogleMaps on my Xamarin app , but when i try to display the map I get a "application is in break mode" status
with an Unhandled Exception:
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
I've tried Initiliazing it from the App Delegate class (which I'm not sure i've done properly)
I tried both in xaml and xaml.cs but still did not budge. Same error.
using Xamarin.Forms.GoogleMaps;
public partial class Discover : ContentPage
{
public Discover ()
{
InitializeComponent ();
Map map = new Map();
StackLayout layout = new StackLayout();
layout.Children.Add(map);
Content = layout;
}
}
What i need to happen is get a map to appear and everything to compile.
---------------------------- FIXED -----------------------------------------
The problem was in the android execution , when adding the API to the nugetPackages you need to add some code aswell.
This is what I added to the android OnCreate method :
Xamarin.FormsGoogleMaps.Init(this, savedInstanceState);
So after I did that I'm good to go.

Amazon IAP Plugin for Xamarin - crash when using TaskCompletionSource

I'm trying to implement a wrapper for the Amazon IAP Plugin for Xamarin. It uses an event based system in the following way:
You can initiate method calls and listen for events. Method calls initiate requests, some of which return a response. Events are asynchronous system-generated messages that are sent in response to method calls to return the requested data to you.
See more here
My goal is to wrap this event based system into some API which allows me to use the plugin with tasks, so I can use the async-await syntax. To achieve that I'm using the TaskCompletionSource like in the following example:
public async Task<bool> GetProductInfoAsync(params string[] productIds)
{
var iapService = AmazonIapV2Impl.Instance;
var tcs = new TaskCompletionSource<bool>();
var skus = new SkusInput { Skus = productIds.ToList() };
var requestId = iapService.GetProductData(skus).RequestId;
GetProductDataResponseDelegator delegator = null;
delegator = new GetProductDataResponseDelegator(response =>
{
if(response.Id == requestId) {
var result = GetResultFromResponse(response);
tcs.SetResult(result);
//iapService.RemoveGetProductDataResponseListener(delegator.responseDelegate);
}
});
iapService.AddGetProductDataResponseListener(delegator.responseDelegate);
return await tcs.Task;
}
This code seems to work fine if the method gets called once, but if it gets called two times in a row the app crashes immediately and the only thing printed to the console is the following message..
[mono] Unhandled Exception:
[mono] System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
[mono-rt] [ERROR] FATAL UNHANDLED EXCEPTION: System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
..which kinda makes no sense at all.
So is there something obvious I'm missing here? Or could it be a bug from the plugin?
I have created a repository with the code above so you can reproduce the problem. It's my playground, so please ignore the whole structure of the project and just focus on the classes AmazonIAPService and MainActivity.
Hint 1:
The commented line //iapService.RemoveGetProductDataResponseListener(delegator.responseDelegate); causes also a crash with the same message but already at the first call of the method.
Hint 2:
The AmazonIAPService contains a commented method which uses await Task.Delay(TimeSpan.FromMilliseconds(1)) and solves the problem from above in a very hacky way which I really don't like.
Problem seems to be that those functions have to run asynchronously. Also mentioned here in the doc. So once you run those functions synchronously somehow they throw exception, i dont what is happening in the library but your hacky solution is the actual solution for that. If you write the function as below. it also works.
PurchaseResponseDelegator delegator = null;
delegator = new PurchaseResponseDelegator(async response =>
{
await Task.Run(() =>
{
if (response.RequestId == requestId)
{
var result = GetPurchaseEventHandler(response);
var sucess = taskCompletionSource.TrySetResult(result);
context.RemovePurchaseResponseListener(delegator.responseDelegate);
}
} );
});
// Register for an event
context.AddPurchaseResponseListener(delegator.responseDelegate);
One other exception I had despite the async-await solution, somehow, it always throws exception for the line taskCompletionSource.SetResult(result); for PurchaseUpdates functions only. if i use instead this line var sucess = taskCompletionSource.TrySetResult(result); it works fine

rxBindings - How to know what consumer type should be when debouncing click events?

using rxBindings im trying to slow down a click event but i would like to know what the parameter is need.
For example, here is a call i am doing on a imageview. So ImageView v;
RxView.clicks(v)
.throttleFirst(400, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread())
.subscribe(new Consumer<Object>() {
#Override
public void accept(#io.reactivex.annotations.NonNull Object v) throws Exception {
showBottomSheet(getAdapterPosition());
}
});
but im im not sure what the parameter in accept should be ?
I was expecting i would get the view here but when i try changing the type to View i get an error of no such method.
If you look at the source code of the Observable generate using RxView.clicks(), you will see that when the click happens, the following code is triggered:
observer.onNext(Notification.INSTANCE);
that is defined in the library, as:
public enum Notification {
INSTANCE
}
It is just a convenient way for indicating that the event happened, it doesn't carry any extra information.

UWP App unknown exception

I am making a media app. In which I load playlists and then when I play from one playlist, it plays fine, but I have the same file in another playlist, It gives an exception, of system dubugger like this
I am using following code when gridview selection changes to play the file.
private async void PlaylistGridView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
try
{
if (PlaylistGridView.SelectedIndex != -1)
{
CurrentlyPlayingVideo = (VideoFile)PlaylistGridView.SelectedItem;
CurrentlyPlayingFile = CurrentlyPlayingVideo.File;
var s = await CurrentlyPlayingFile.OpenReadAsync();
var sq = me;
me.SetSource(s, CurrentlyPlayingFile.ContentType);
}
}
catch { }
}
the message in e.Message is 'Object refrence is not set to instance of object',
I surely know it is null type error, but problem is i dnt know which object is null!!, I am even using try catch blocks, but still its giving that exception in the picture above, and not telling me the object which is null, until i dnt know which object is null, how can i fix the error?
EDIT :
I tried to run in release mode with visual studio and this is the error i get even before trying to play anything.
Object reference is not set to instance of an object
I had seen this error when I build an uwp too. If I'm not mistaken, any of your Control (Button , Textblock , etc) is called by any of your method (including event) before they have been initialized to the Page Check the calling once again

Resources