jamesmontemagno / MediaPlugin

Take & Pick Photos and Video Plugin for Xamarin and Windows
MIT License
712 stars 358 forks source link

[Android]Background service and "Only one operation can be active at a time" #144

Open pbielinski opened 7 years ago

pbielinski commented 7 years ago

Bug

Version Number of Plugin: 2.6.1 Device Tested On: Motorola Moto G3 (Android)

Expected Behavior

We launch application with background service and notification. We run TakePhotoAsync, click home button and remove from recent apps (close application), but background application still running. On resume application we can run second time TakePhotoAsync without errors.

Actual Behavior

We launch application with background service and notification. We run TakePhotoAsync, click home button and remove from recent apps (close application), but background application still running. On resume application, second run TakePhotoAsync inform with exception: "System.InvalidOperationException: Only one operation can be active at a time"

Steps to reproduce the Behavior

I create sample application to test: https://github.com/pbielinski/BugHomeButtonMediaPlugin

On sample app:

Feature Request:

I think the best will be closing connected Activity with TakePhotoAsync, when application close (even background service still running)

pbielinski commented 7 years ago

any suggestion? I can modify and test it, but I need some hint.

pbielinski commented 7 years ago

@jamesmontemagno any suggestion? I can modify and test it, but I need some hint.

mannyvw commented 6 years ago

i have similar issue on 3.0.1 with just a regular forms app.

Take photo using TakePhotoAsync, hit home button while in camera, relaunch app, run TakePhotoAsync again, and get exception "Only one operation can be active at a time"

How can I get app to cancel the first call when app backgrounds.

thanks

kavitPatel commented 6 years ago

@jamesmontemagno We are also facing the same issue as @mannyvw reported in previous comment. -- Start capturing video and minimise the app. -- Open the app again and start capture again. This time it doesn't start video capture because previous activity is not closed. Do we have any provision to check & close if any previous video activity is running for the app?

Only way to start the video capture again is you need to kill the app.

kavitPatel commented 6 years ago

@jamesmontemagno I found that the issue occurs when LaunchMode is set as SingleInstance for the MainActivity. LaunchMode = LaunchMode.SingleInstance

If we remove the above line and use the default (standard) launch mode then it works as expected. Can you please check and provide any suggestion to fix when we have LaunchMode set?

cbagpipe commented 6 years ago

confirm it's still actual.

LeoJHarris commented 5 years ago

Error exception threw using the sample project...

07-17 09:40:57.205 I/MonoDroid(18254): UNHANDLED EXCEPTION: 07-17 09:40:57.322 I/MonoDroid(18254): System.InvalidOperationException: Only one operation can be active at a time 07-17 09:40:57.322 I/MonoDroid(18254): at Plugin.Media.MediaImplementation.TakeMediaAsync (System.String type, System.String action, Plugin.Media.Abstractions.StoreMediaOptions options) [0x00039] in <5939e997f291496f805023da28f3a447>:0 07-17 09:40:57.322 I/MonoDroid(18254): at Plugin.Media.MediaImplementation+d17.MoveNext () [0x000ab] in <5939e997f291496f805023da28f3a447>:0 07-17 09:40:57.322 I/MonoDroid(18254): --- End of stack trace from previous location where exception was thrown --- 07-17 09:40:57.322 I/MonoDroid(18254): at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x0003e] in :0 07-17 09:40:57.322 I/MonoDroid(18254): at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x00028] in :0 07-17 09:40:57.322 I/MonoDroid(18254): at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x00008] in :0 07-17 09:40:57.322 I/MonoDroid(18254): at System.Runtime.CompilerServices.TaskAwaiter`1[TResult].GetResult () [0x00000] in :0 07-17 09:40:57.322 I/MonoDroid(18254): at MediaSample.MediaPage+<<-ctor>b0_0>d.MoveNext () [0x000ba] in C:\Users\Admin\Source\Repos\MediaPlugin\samples\MediaSample\MediaSample\MediaPage.xaml.cs:27 07-17 09:40:57.322 I/MonoDroid(18254): --- End of stack trace from previous location where exception was thrown --- 07-17 09:40:57.322 I/MonoDroid(18254): at System.Runtime.CompilerServices.AsyncMethodBuilderCore+<>c.b6_0 (System.Object state) [0x00000] in :0 07-17 09:40:57.322 I/MonoDroid(18254): at Android.App.SyncContext+<>c__DisplayClass2_0.b0 () [0x00000] in <256e144820b246b7855b4c426b5ccea1>:0 07-17 09:40:57.322 I/MonoDroid(18254): at Java.Lang.Thread+RunnableImplementor.Run () [0x00008] in <256e144820b246b7855b4c426b5ccea1>:0 07-17 09:40:57.322 I/MonoDroid(18254): at Java.Lang.IRunnableInvoker.n_Run (System.IntPtr jnienv, System.IntPtr nativethis) [0x00009] in <256e144820b246b7855b4c426b5ccea1>:0 07-17 09:40:57.322 I/MonoDroid(18254): at (wrapper dynamic-method) System.Object.d3aaa131-156d-4adb-a622-72e212915200(intptr,intptr) 07-17 09:40:57.448 W/art (18254): JNI RegisterNativeMethods: attempt to register 0 native methods for android.runtime.JavaProxyThrowable 07-17 09:40:57.462 D/Mono (18254): DllImport searching in: 'Internal' ('(null)'). 07-17 09:40:57.462 D/Mono (18254): Searching for 'java_interop_jnienv_throw'. 07-17 09:40:57.462 D/Mono (18254): Probing 'java_interop_jnienv_throw'. 07-17 09:40:57.462 D/Mono (18254): Found as 'java_interop_jnienv_throw'. An unhandled exception occured.

vagrawal1986 commented 5 years ago

We are having the same issue too. A fix sooner will be much appreciated! Thanks

DuncWatts commented 3 years ago

I think I've made some progress on this one when running with LaunchMode=SingleTask.

My first attempt was to pass a CancellationToken to the TakePhotoAsync, then cancel it on the OnResume of the application, so when you get back to the application after pressing home then the photo process is cancelled and the application can continue.

This fails with a NullReferenceException as the OnDestroy of the MediaPickerActivity is called when you press the home button and this method sets the CompletionSource to null.

I've tweaked the OnDestroy method of the MediaPickerActivity to SetResult(null) so it is automatically cancelled when you switch from the application by pressing the home page and this seems to get the behaviour I'm after without needing to pass a CancellationToken. If I remove the SingleTask from the Activity, then the OnDestroy doesn't get called and the camera reappears when reopening from the app icon.

        /// <summary>
        /// On Destroy
        /// </summary>
        protected override void OnDestroy()
        {
            if (!completed)
            {
                DeleteOutputFile();

                MediaImplementation.CompletionSource?.SetResult(null);
                MediaImplementation.CompletionSourceMulti?.SetResult(null);

                MediaImplementation.CompletionSource = null;
                MediaImplementation.CompletionSourceMulti = null;
                MediaPicked = null;
            }
            base.OnDestroy();
        }

Are there any other issues to be aware with with this workaround?