android - 使用 YouTube Android 播放器 api 1.2.2 时发生 OutOfMemoryError

标签 android android-youtube-api

使用 youtube 播放器 sdk 播放视频大约 30~40 次导致 Youtube 应用程序崩溃,然后由于远程进程的死亡,我的应用程序将引发 DeadObjectException。重现步骤:

  1. 启动 Activity 并初始化 YouTubePlayer
  2. 加载并播放几秒钟的视频
  3. 释放 YouTubePlayer 并退出 Activity
  4. 重复步骤1-3约30~40次

OutOfMemoryError 日志(full logs):

08-22 12:01:01.461 E/AndroidRuntime( 3017): FATAL EXCEPTION: main
08-22 12:01:01.461 E/AndroidRuntime( 3017): Process: com.google.android.youtube.player, PID: 3017
08-22 12:01:01.461 E/AndroidRuntime( 3017): java.lang.OutOfMemoryError: Could not allocate JNI Env
08-22 12:01:01.461 E/AndroidRuntime( 3017):     at java.lang.Thread.nativeCreate(Native Method)
08-22 12:01:01.461 E/AndroidRuntime( 3017):     at java.lang.Thread.start(Thread.java:1063)
08-22 12:01:01.461 E/AndroidRuntime( 3017):     at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:921)
08-22 12:01:01.461 E/AndroidRuntime( 3017):     at java.util.concurrent.ThreadPoolExecutor.ensurePrestart(ThreadPoolExecutor.java:1556)
08-22 12:01:01.461 E/AndroidRuntime( 3017):     at java.util.concurrent.ScheduledThreadPoolExecutor.delayedExecute(ScheduledThreadPoolExecutor.java:310)
08-22 12:01:01.461 E/AndroidRuntime( 3017):     at java.util.concurrent.ScheduledThreadPoolExecutor.schedule(ScheduledThreadPoolExecutor.java:527)
08-22 12:01:01.461 E/AndroidRuntime( 3017):     at java.util.concurrent.ScheduledThreadPoolExecutor.execute(ScheduledThreadPoolExecutor.java:616)
08-22 12:01:01.461 E/AndroidRuntime( 3017):     at reo.a(SourceFile:134)
08-22 12:01:01.461 E/AndroidRuntime( 3017):     at sgh.a(SourceFile:722)
08-22 12:01:01.461 E/AndroidRuntime( 3017):     at gan.a(SourceFile:310)
08-22 12:01:01.461 E/AndroidRuntime( 3017):     at gan.b(SourceFile:338)
08-22 12:01:01.461 E/AndroidRuntime( 3017):     at com.google.android.apps.youtube.embeddedplayer.service.service.jar.ApiPlayerService$2.run(SourceFile:215)
08-22 12:01:01.461 E/AndroidRuntime( 3017):     at android.os.Handler.handleCallback(Handler.java:739)
08-22 12:01:01.461 E/AndroidRuntime( 3017):     at android.os.Handler.dispatchMessage(Handler.java:95)
08-22 12:01:01.461 E/AndroidRuntime( 3017):     at android.os.Looper.loop(Looper.java:148)
08-22 12:01:01.461 E/AndroidRuntime( 3017):     at android.app.ActivityThread.main(ActivityThread.java:5417)
08-22 12:01:01.461 E/AndroidRuntime( 3017):     at java.lang.reflect.Method.invoke(Native Method)
08-22 12:01:01.461 E/AndroidRuntime( 3017):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
08-22 12:01:01.461 E/AndroidRuntime( 3017):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

和 DeadObjectException

08-22 12:01:01.842 E/MonitoringInstrumentation( 2976): java.lang.IllegalStateException: android.os.DeadObjectException
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at gix.surfaceCreated(SourceFile:189)
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at android.view.SurfaceView.updateWindow(SurfaceView.java:582)
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at android.view.SurfaceView$3.onPreDraw(SurfaceView.java:177)
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:944)
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2055)
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1107)
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6013)
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at android.view.Choreographer$CallbackRecord.run(Choreographer.java:858)
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at android.view.Choreographer.doCallbacks(Choreographer.java:670)
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at android.view.Choreographer.doFrame(Choreographer.java:606)
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:844)
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at android.os.Handler.handleCallback(Handler.java:739)
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at android.os.Handler.dispatchMessage(Handler.java:95)
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at android.os.Looper.loop(Looper.java:148)
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at android.app.ActivityThread.main(ActivityThread.java:5417)
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at java.lang.reflect.Method.invoke(Native Method)
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976): Caused by: android.os.DeadObjectException
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at android.os.BinderProxy.transactNative(Native Method)
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at android.os.BinderProxy.transact(Binder.java:503)
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at com.google.android.apps.youtube.embeddedplayer.service.service.jar.ISurfaceHolderService$Stub$Proxy.a(SourceFile:110)
08-22 12:01:01.842 E/MonitoringInstrumentation( 2976):  at gix.surfaceCreated(SourceFile:186)

YouTube 应用程序版本为 11.29.55,带有 Marshmallow 的 Nexus 5 模拟器 , 我已经用其他版本的 YouTube App 测试过,比如 10.25.57 和 10.40.58,仍然会出现 OOM。

一开始我遇到这个问题的时候我以为是一些不正确的api方法调用引起的,但是经过几个小时的研究我发现这应该是YouTube App的问题,希望有人能帮我解决它,或者至少避免它。

com.google.android.youtube.player 进程的内存在播放器初始化和从内存监视器播放视频时增加,许多 YoutubeService 实例创建但未回收从转储文件。有什么想法吗?

我使用基于官方 YouTubeAndroidAPI 示例的演示应用程序对其进行了测试,但也出现了 OutOfMemory 错误,我只是将 cueVideo(String) 替换为 loadVideo(String)PlayerViewDemoActivity中实现自动播放,在onDestroy()中添加了YouTubePlayer#release(),同时我添加了一个基于Espresso的测试代码重现内存泄漏问题。

这里是测试代码,here完整的演示代码。

package com.examples.youtubeapidemo.play;

import android.os.SystemClock;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.LargeTest;
import android.util.Log;

import com.examples.youtubeapidemo.YouTubeAPIDemoActivity;

import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.Espresso.pressBack;
import static android.support.test.espresso.action.ViewActions.click;
import static android.support.test.espresso.matcher.ViewMatchers.withText;

/**
 * for YouTubePlayerView testing
 */
@RunWith(AndroidJUnit4.class)
@LargeTest
public class PlayerViewTest {

    @Rule
    public ActivityTestRule<YouTubeAPIDemoActivity> mActivityTestRule =
            new ActivityTestRule<YouTubeAPIDemoActivity>(YouTubeAPIDemoActivity.class);

    @Test
    public void testYouTubeMemoryLeaks() {
        int count = 0;
        while(count < 100) {
            onView(withText("Simple PlayerView")).perform(click());
            SystemClock.sleep(10000); // waiting for video start playing
            pressBack();
            count++;
            Log.i("PlayerViewTest", "count: " + count);
        }
    }
}

最佳答案

我通过将 youtube 调用(如 youtubePlayer.loadVideo()、cueVideo()、getCurrentTimeMillis() 等)放在 try catch block 中并捕获 IllegalStateException 异常然后重新初始化 youtube 播放器来减少错误的发生。

并通过捕获这些异常并重新启动 Activity 来解决它,

请看我在这个帖子上的回答: Getting a lot of crashes from android youtube player api

关于android - 使用 YouTube Android 播放器 api 1.2.2 时发生 OutOfMemoryError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39099156/

相关文章:

java - 我的电脑缺少 R.java

android - 在 Android 中,如何在 Receiver 中处理 facebook session 过期 (SDK 3.0)

android - YouTubePlayerView 在屏幕方向更改时重新加载视频

android - 将 css 文件包含到 android studio 中的按钮

android - 无法为intent android打开pdf文件

android - 使用 Android MediaCodec 从摄像头编码 H.264

android - 如何检查用户是否使用 YouTube api 观看了整个视频

android - java.lang.IllegalStateException : YouTubeServiceEntity not initialized with YouTubeThumbnailView 错误

android - 使用 Youtube Player API 播放不同的 youtube 视频

android - 根据区域获取YouTube趋势( HitTest 门) channel 和播放列表