PhoneGap相机重启应用程序

33

我正在使用PhoneGap的navigator.camera.getPicture函数从Android设备的相机中检索照片。

function onSuccess(imageData) {
    alert("Success!");
}

function onFail(message) {
    alert('Failed because: ' + message);
}

$(function() {
    $("button").tap(function() {
        navigator.camera.getPicture(onSuccess, onFail, { quality: 50 }); 
    });
});

当我点击按钮时,它确实启动了摄像头,但是在拍照后点击相机应用程序上的“确定”按钮时,它会重新启动应用程序。
我尝试过:
  • 使用不同的源类型。
  • 使用不同的目标类型。
  • 降低质量。
有什么想法吗?
编辑:我还在github上提出了一个问题

PhoneGap 1.2?安卓的哪个版本? - Raymond Camden
PhoneGap 1.2,Android 2.3.7 MIUI - Alon Gubkin
使用 PhoneGap 1.7 和 Android 2.3 时遇到相同的问题。 - Fotis Adamakis
1
请问您能否更新一下 Github 的 issue 链接,它已经过时了。 - Zorayr
9个回答

36

这个问题实际上与Phonegap无关,在本地 Android 应用程序中也是常见问题。

这是因为当触发相机时,Android 活动会进入后台(停止状态),等待相机拍照。然后垃圾回收器会在相机操作结束之前杀死活动以释放内存,而当相机完成时,您的活动已经被销毁。这就是为什么应用程序会重新启动的原因。

这在 Android 生命周期文档 (http://developer.android.com/reference/android/app/Activity.html) 中有说明:

如果一个活动完全被另一个活动遮挡,它会停止。它仍保留所有状态和成员信息,但它不再对用户可见,所以它的窗口被隐藏起来,并且在需要释放内存时通常会被系统杀掉。

访问媒体库或其他导致您的活动转至后台的资源也会发生同样的情况。Phonegap(现在是Cordova)团队正在努力改进这个问题(https://issues.apache.org/jira/browse/CB-14)。

我们公司也遇到了这个问题,解决方法是本地开发一个 Phonegap 插件,使用我们自定义的相机,这样我们的活动就不会进入 onStop 状态。请按照 Android API 说明 (http://developer.android.com/guide/topics/media/camera.html#custom-camera) 操作并尝试。

祝好!


编辑 1:

我们提交了一个名为 Foreground Camera Plugin 的 Google Code 项目,可以解决 Android 相机重新启动 Phonegap 应用程序的问题。此外,还有一些使用说明。请参见:http://code.google.com/p/foreground-camera-plugin/


编辑 2:

由于这个问题也会发生在画廊上,我们提交了另一个名为Foreground Gallery Plugin的Google Code项目,它可以与Cordova一起使用并修复此问题。请参见:http://code.google.com/p/foreground-gallery-plugin/


4
如果现在我无法使用PhoneGap拍照,那最初使用PhoneGap的原因是什么?这没有道理。 - Zorayr
1
嗨@keune,我会先与我的团队商量,如果开源插件没问题,我会尝试上传一个带有可工作插件的“hello world”项目,并在此处粘贴链接。但还是谢谢你的建议。 - Vinícius Fonseca
2
嗨Vicinius,您有计划将这个更新到更高版本的PhoneGap吗? - Dan Smart
好的插件,但在当前的PhoneGap版本中已被弃用,该插件现在适用于Cordova 2.1,而Cordova已经更新到3.1版本。在Cordova 3.1中,需要修复插件的问题。 - Víctor Dueñas Robles
这个问题在新版的安卓或者cordova中解决了吗?我在MOTO X上遇到了这个问题,直到我关闭了设置中的开发者调试选项。理想情况下,无论设置如何,它都应该能够正常工作。但现在我在想它是否适用于所有的安卓设备。你有什么想法吗? - Yashvit
显示剩余4条评论

29
请注意,如果您直接在Android手机上测试此应用程序,则在“开发者选项”中有一个名为“不保留活动”的选项。勾选此选项会在离开活动时删除该活动。特别是对于相机(以及从您的活动启动的其他应用程序),它会重新启动您的活动。
取消勾选此选项,看看是否有所帮助。

1
请访问https://dev59.com/EG3Xa4cB1Zd3GeqPjuFj并获得绿色勾号。 - ocodo
谢谢!你的回答帮了我大忙。 - Ataru
这对我有用,是一个很好的开发解决方法。但是如何让我的用户不必执行此步骤呢? - wilblack
您应该在"不保留活动"的情况下进行一些测试,以确保您的应用程序在低内存状态下得到适当的维护。 - Sasha
这只是一个测试,但恐怕这不是一个真正的解决方案。 - Dani
显示剩余2条评论

4

我有一台三星Galaxy Note II。我遇到了同样的问题。我在AndroidManifest.xml中进行了更改,现在它可以在三星和HTC Thunderbolt上正常工作。

<uses-feature android:name="android.hardware.camera" android:required="false"/>

<uses-sdk android:minSdkVersion="7" android:targetSdkVersion="10"/>

<activity  android:configChanges="orientation|keyboardHidden" />

在Galaxy S5上运行得像魔法一样(我只是从你的片段中添加了第一行代码)。谢谢。 - born2fr4g

2

用户不希望重启手机以释放内存,或在设置中勾选框。我发现的用户友好的方法是,在离开相机后返回我的应用程序活动,只需添加以下行:

intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

在相机cordova插件的CameraLauncher.java文件中,就在this.cordova.startActivityForResult()尝试返回相机结果之前,确保检索到旧活动,而不是被垃圾回收并启动新实例。参考android Intent API:
int FLAG_ACTIVITY_CLEAR_TOP:“如果设置,并且正在启动的活动已经在当前任务中运行,则除了该活动的新实例外,所有其他顶部活动都将关闭,此Intent将被传递到(现在位于顶部的)旧活动作为新的Intent。”

对我无效 :( 应用程序仍在重新启动.. (cordova 4.1.2, Android 5.0.2) - Redfox
我也尝试了在Android lolipop、三星S5和cordova 3.5.0上运行,但是它没有成功。 - Phyxx

2

在Android拍照后重新启动应用程序时,会向应用程序发送一个resume事件。该事件包含拍摄的照片数据。因此,可能的解决方法是捕获该事件:

document.addEventListener('resume', function(evt) {
  if(evt.action === 'resume' && evt.pendingResult) {
    var r = evt.pendingResult;
    if(r.pluginServiceName === 'Camera' && r.pluginStatus === 'OK') {
      // r.result contains file:/// url or a base64 image.
    }
  }
}, false);

当然,您还需要恢复应用程序的状态。为此,在打开相机之前,请将状态信息保存到例如localStorage中。


1

对我来说,使用Cordova背景插件很有帮助:https://www.npmjs.com/package/cordova-plugin-background-mode

在config.xml中包含:

<gap:plugin name="cordova-plugin-background-mode" source="npm"/>

然后触发点击事件启动相机插件并将应用程序发送到后台:

$(document).on("click","#btn_bild_aufnehmen",function(){        
    cordova.plugins.backgroundMode.setDefaults({ text:'desc',title:'appname'});
    cordova.plugins.backgroundMode.enable();
    //do your camera stuff
});

不要忘记在相机插件成功后禁用背景模式:

cordova.plugins.backgroundMode.disable();

请确保在 onResume 中禁用它,在 onPause 中启用它:
function onResume(){
   window.plugin.backgroundMode.disable();
}
function onPause(){
   window.plugin.backgroundMode.enable();
}

我无法让这个程序运行起来。我能在安卓通知面板中看到它在后台“正在进行繁重的任务”。但是在拍完照片之后,活动仍然被重新启动了。有任何想法吗?我已经按照您的示例将相机和条码调用进行封装了。 - Ryan
抱歉,我无法提供一个好的建议来解决问题。看起来后台模式启动正常。也许你没有在相机插件的成功函数中首先禁用后台模式?或者它进入了错误回调? - zuluk

0

当您的设备活动被垃圾回收器杀死时,实际上就会发生这种情况。当某些应用程序事件被触发时,您的默认活动将转到后台,因此它被杀死了。

要解决这个问题,您需要进入开发人员选项。在那里,您将看到不保留活动选项,只需取消选中即可。重新启动您的应用程序,现在尝试相机,它将平稳运行。


2
这不解决问题 - 那个设置是为了您能够复制使用情况,当操作系统由于低内存使用而一直杀死应用程序时。如果用户运行您的应用程序的设备内存较低,则会杀死应用程序(执行此设置的操作)。 - Lee Brindley

0

我遇到了一个类似的问题,即使在相机文档提供的完整示例也会导致应用程序在Android设备(三星,Galaxy S)上崩溃。这是我得到的日志输出:

enter image description here


0

我也遇到了同样的问题。我清除了手机上的所有数据,以增加手机内存大小。然后停止了所有正在运行的应用程序,并重新启动了我的应用程序。这次当捕获事件被调用时,我的应用程序没有崩溃。

基本上,这个问题存在于内存较少的手机上。在高端手机上,这将正常工作。

注意:还要添加这些额外的参数到捕获的图像中:

 navigator.camera.getPicture(onPhotoDataSuccess, onFail, {
                   quality: 20,
                   destinationType:Camera.DestinationType.DATA_URL,
                   targetWidth: 200,
                   targetHeight: 200,
                   saveToPhotoAlbum : true
 });

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接