Youtube看我Android应用程序意外关闭

时间:2015-09-17 06:25:38

标签: android ffmpeg youtube-api apk live-streaming

我从https://github.com/youtube/yt-watchme创建了android应用程序。

当我尝试使用“CREATE LIVE EVENT”按钮创建事件时。它会抛出一些跟随错误。我认为这是由于相机许可问题而发生的。

ERROR:

09-17 11:43:53.582  32383-32383/com.google.android.apps.watchme E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.google.android.apps.watchme, PID: 32383
    java.lang.NoSuchMethodError: com.google.android.apps.watchme.StreamerActivity.checkSelfPermission
            at com.google.android.apps.watchme.StreamerActivity.startStreaming(StreamerActivity.java:174)
            at com.google.android.apps.watchme.StreamerActivity.access$200(StreamerActivity.java:46)
            at com.google.android.apps.watchme.StreamerActivity$1.onServiceConnected(StreamerActivity.java:63)
            at android.app.LoadedApk$ServiceDispatcher.doConnected(LoadedApk.java:1110)
            at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1127)
            at android.os.Handler.handleCallback(Handler.java:733)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5097)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
            at dalvik.system.NativeStart.main(Native Method)

任何人请建议。我该如何解决这个问题。

提前致谢

代码更新:

清单文件XML

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.google.android.apps.watchme">


    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <!-- For authorization. -->
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <!-- For recording audio and video without going to lock. -->
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission."/>
    <uses-permission android:name="android.permission.CAMERA" />

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

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme">
        <activity
            android:name="com.google.android.apps.watchme.MainActivity"
            android:configChanges="orientation|screenSize"
            android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name="com.google.android.apps.watchme.StreamerActivity"
            android:label="@string/app_name"
            android:screenOrientation="landscape"></activity>

        <service android:name="com.google.android.apps.watchme.StreamerService" />
    </application>
    <uses-sdk
        android:minSdkVersion="23"
        android:targetSdkVersion="23"/>
</manifest>

流活动文件

/*
 * Copyright (c) 2014 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */

package com.google.android.apps.watchme;

import android.Manifest;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.os.Bundle;
import android.os.IBinder;
import android.os.PowerManager;
import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityCompat;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ToggleButton;

import com.google.android.apps.watchme.util.Utils;
import com.google.android.apps.watchme.util.YouTubeApi;

import java.util.ArrayList;
import java.util.List;

/**
 * @author Ibrahim Ulukaya <ulukaya@google.com>
 *         <p/>
 *         StreamerActivity class which previews the camera and streams via StreamerService.
 */
public class StreamerActivity extends Activity {
    // CONSTANTS
    // TODO: Stop hardcoding this and read values from the camera's supported sizes.
    public static final int CAMERA_WIDTH = 640;
    public static final int CAMERA_HEIGHT = 480;
    private static final int REQUEST_CAMERA_MICROPHONE = 0;

    // Member variables
    private StreamerService streamerService;
    private ServiceConnection streamerConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName className, IBinder service) {
            Log.d(MainActivity.APP_NAME, "onServiceConnected");

            streamerService = ((StreamerService.LocalBinder) service).getService();

            restoreStateFromService();
            startStreaming();
        }

        @Override
        public void onServiceDisconnected(ComponentName className) {
            Log.e(MainActivity.APP_NAME, "onServiceDisconnected");

            // This should never happen, because our service runs in the same process.
            streamerService = null;
        }
    };
    private PowerManager.WakeLock wakeLock;
    private Preview preview;
    private String rtmpUrl;
    private String broadcastId;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        Log.d(MainActivity.APP_NAME, "onCreate");
        super.onCreate(savedInstanceState);

        broadcastId = getIntent().getStringExtra(YouTubeApi.BROADCAST_ID_KEY);
        //Log.v(MainActivity.APP_NAME, broadcastId);

        rtmpUrl = getIntent().getStringExtra(YouTubeApi.RTMP_URL_KEY);

        if (rtmpUrl == null) {
            Log.w(MainActivity.APP_NAME, "No RTMP URL was passed in; bailing.");
            finish();
        }
        Log.i(MainActivity.APP_NAME, String.format("Got RTMP URL '%s' from calling activity.", rtmpUrl));

        setContentView(R.layout.streamer);
        preview = (Preview) findViewById(R.id.surfaceViewPreview);

        if (!bindService(new Intent(this, StreamerService.class), streamerConnection,
                BIND_AUTO_CREATE | BIND_DEBUG_UNBIND)) {
            Log.e(MainActivity.APP_NAME, "Failed to bind StreamerService!");
        }

        final ToggleButton toggleButton = (ToggleButton) findViewById(R.id.toggleBroadcasting);
        toggleButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (toggleButton.isChecked()) {
                    streamerService.startStreaming(rtmpUrl);
                } else {
                    streamerService.stopStreaming();
                }
            }
        });
    }

    @Override
    protected void onResume() {
        Log.d(MainActivity.APP_NAME, "onResume");

        super.onResume();

        if (streamerService != null) {
            restoreStateFromService();
        }
    }

    @Override
    protected void onPause() {
        Log.d(MainActivity.APP_NAME, "onPause");

        super.onPause();

        if (preview != null) {
            preview.setCamera(null);
        }

        if (streamerService != null) {
            streamerService.releaseCamera();
        }
    }

    @Override
    protected void onDestroy() {
        Log.d(MainActivity.APP_NAME, "onDestroy");

        super.onDestroy();

        if (streamerConnection != null) {
            unbindService(streamerConnection);
        }

        stopStreaming();

        if (streamerService != null) {
            streamerService.releaseCamera();
        }
    }

    private void restoreStateFromService() {
        preview.setCamera(Utils.getCamera(Camera.CameraInfo.CAMERA_FACING_FRONT));
    }

    private void startStreaming() {
        Log.d(MainActivity.APP_NAME, "startStreaming");

        PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
        wakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, this.getClass().getName());
        wakeLock.acquire();

        if (!streamerService.isStreaming()) {

            String cameraPermission = Manifest.permission.CAMERA;
            String microphonePermission = Manifest.permission.RECORD_AUDIO;
            int hasCamPermission = checkSelfPermission(cameraPermission);
            int hasMicPermission = checkSelfPermission(microphonePermission);
            List<String> permissions = new ArrayList<String>();
            if (hasCamPermission != PackageManager.PERMISSION_GRANTED) {
                permissions.add(cameraPermission);
                if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                        Manifest.permission.CAMERA)) {
                    // Provide rationale in Snackbar to request permission
                    Snackbar.make(preview, R.string.permission_camera_rationale,
                            Snackbar.LENGTH_INDEFINITE).show();
                } else {
                    // Explain in Snackbar to turn on permission in settings
                    Snackbar.make(preview, R.string.permission_camera_explain,
                            Snackbar.LENGTH_INDEFINITE).show();
                }
            }
            if (hasMicPermission != PackageManager.PERMISSION_GRANTED) {
                permissions.add(microphonePermission);
                if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                        Manifest.permission.RECORD_AUDIO)) {
                    // Provide rationale in Snackbar to request permission
                    Snackbar.make(preview, R.string.permission_microphone_rationale,
                            Snackbar.LENGTH_INDEFINITE).show();
                } else {
                    // Explain in Snackbar to turn on permission in settings
                    Snackbar.make(preview, R.string.permission_microphone_explain,
                            Snackbar.LENGTH_INDEFINITE).show();
                }
            }
            if (!permissions.isEmpty()) {
                String[] params = permissions.toArray(new String[permissions.size()]);
                ActivityCompat.requestPermissions(this, params, REQUEST_CAMERA_MICROPHONE);
            } else {
                // We already have permission, so handle as normal
                streamerService.startStreaming(rtmpUrl);
            }
        }
    }

    /**
     * Callback received when a permissions request has been completed.
     */
    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           String permissions[], int[] grantResults) {
        switch (requestCode) {
            case REQUEST_CAMERA_MICROPHONE: {
                Log.i(MainActivity.APP_NAME, "Received response for camera with mic permissions request.");

                // We have requested multiple permissions for contacts, so all of them need to be
                // checked.
                if (Utils.verifyPermissions(grantResults)) {
                    // permissions were granted, yay! do the
                    // streamer task you need to do.
                    streamerService.startStreaming(rtmpUrl);
                } else {
                    Log.i(MainActivity.APP_NAME, "Camera with mic permissions were NOT granted.");
                    Snackbar.make(preview, R.string.permissions_not_granted,
                            Snackbar.LENGTH_SHORT)
                            .show();
                }
                break;
            }

            // other 'switch' lines to check for other
            // permissions this app might request
        }
        return;
    }


    private void stopStreaming() {
        Log.d(MainActivity.APP_NAME, "stopStreaming");

        if (wakeLock != null) {
            wakeLock.release();
            wakeLock = null;
        }

        if (streamerService.isStreaming()) {
            streamerService.stopStreaming();
        }
    }

    public void endEvent(View view) {
        Intent data = new Intent();
        data.putExtra(YouTubeApi.BROADCAST_ID_KEY, broadcastId);
        if (getParent() == null) {
            setResult(Activity.RESULT_OK, data);
        } else {
            getParent().setResult(Activity.RESULT_OK, data);
        }
        finish();
    }

}

更新错误代码:

08:57:14.447  18829-18829/com.google.android.apps.watchme E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.google.android.apps.watchme, PID: 18829
    java.lang.UnsatisfiedLinkError: Couldn't load ffmpeg from loader dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.google.android.apps.watchme-1.apk"],nativeLibraryDirectories=[/data/app-lib/com.google.android.apps.watchme-1, /vendor/lib, /system/lib]]]: findLibrary returned null
            at java.lang.Runtime.loadLibrary(Runtime.java:358)
            at java.lang.System.loadLibrary(System.java:526)
            at com.google.android.apps.watchme.Ffmpeg.<clinit>(Ffmpeg.java:26)
            at com.google.android.apps.watchme.VideoStreamingConnection.open(VideoStreamingConnection.java:71)
            at com.google.android.apps.watchme.StreamerService.startStreaming(StreamerService.java:80)
            at com.google.android.apps.watchme.StreamerActivity.startStreaming(StreamerActivity.java:212)
            at com.google.android.apps.watchme.StreamerActivity.access$200(StreamerActivity.java:47)
            at com.google.android.apps.watchme.StreamerActivity$1.onServiceConnected(StreamerActivity.java:64)
            at android.app.LoadedApk$ServiceDispatcher.doConnected(LoadedApk.java:1110)
            at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1127)
            at android.os.Handler.handleCallback(Handler.java:733)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5097)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
            at dalvik.system.NativeStart.main(Native Method)

2 个答案:

答案 0 :(得分:1)

在调用发生的活动代码中,用一个支票包装它:

int hasCamPermission = checkSelfPermission(cameraPermission);
int hasMicPermission = checkSelfPermission(microphonePermission);

首先将以下方法添加到StreamerActivity:

private boolean shouldCheckForPermission() {
  return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
}

将这些行更改为:

int hasCamPermission = shouldCheckForPermission() ? checkSelfPermission(cameraPermission) : PackageManager.PERMISSION_GRANTED;
int hasMicPermission = shouldCheckForPermission() ? checkSelfPermission(microphonePermission) : PackageManager.PERMISSION_GRANTED;

为此,您需要使用SDK 23进行编译和定位,如上面的答案中所述。

答案 1 :(得分:0)

此方法仅适用于API版本&gt; = 23,

targetSdkVersion 23
compileSdkVersion 23

在您的代码中,您需要在调用此方法之前检查当前的API版本。

    public static boolean shouldCheckForPermission() {
      return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
    }

如果此方法返回true,则可以调用方法&#34; checkSelfPermission&#34;。