Невозможно воспроизвести видео из внутреннего хранилища с помощью встроенного кодека, предоставленного Google с помощью adb. - PullRequest
0 голосов
/ 22 января 2019

Я использую приложение родного кодека, предоставленное Google: (https://github.com/googlesamples/android-ndk/tree/master/native-codec). В приложении есть папка (ресурсы), в которой содержатся некоторые образцы видео для воспроизведения. Моя цель - прочитать видео из внутренней памяти телефона.(т.е. /sdcard/filename.mp4.) Я добавил эти 2 строки в файл манифеста, но это еще не помогло решить проблему.

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

Я изменил код, чтобы получить имя файла видео какаргумент, заданный оболочкой adb. Вот код:

    mSourceString = getIntent().getStringExtra("arg");
    if (!mCreated) {
        if (mSourceString != null) {
            mCreated = createStreamingMediaPlayer(getResources().getAssets(), mSourceString);
        }
    }

    if (mCreated) {
        mIsPlaying = !mIsPlaying;
        setPlayingStreamingMediaPlayer(mIsPlaying);
    }

Собственный код метода, который читает имя файла видео, следующий:

jboolean Java_com_example_mohammed_myapplication_MainActivity_createStreamingMediaPlayer(JNIEnv* env,                                                                                   jclass clazz, jobject assetMgr, jstring filename)
{
    LOGV("@@@ create");

    // convert Java string to UTF-8
    const char *utf8 = env->GetStringUTFChars(filename, NULL);
    LOGV("opening %s", utf8);

    off_t outStart, outLen;
    int fd = AAsset_openFileDescriptor(AAssetManager_open(AAssetManager_fromJava(env, assetMgr), utf8, 0),
                                       &outStart, &outLen);

    env->ReleaseStringUTFChars(filename, utf8);
    if (fd < 0) {
        LOGE("failed to open file: %s %d (%s)", utf8, fd, strerror(errno));
        return JNI_FALSE;
    }

    data.fd = fd;

    workerdata *d = &data;

    AMediaExtractor *ex = AMediaExtractor_new();
    media_status_t err = AMediaExtractor_setDataSourceFd(ex, d->fd,
                                                         static_cast<off64_t>(outStart),
                                                         static_cast<off64_t>(outLen));
    close(d->fd);
    if (err != AMEDIA_OK) {
        LOGV("setDataSource error: %d", err);
        return JNI_FALSE;
    }

    int numtracks = AMediaExtractor_getTrackCount(ex);

    AMediaCodec *codec = NULL;

    LOGV("input has %d tracks", numtracks);
    for (int i = 0; i < numtracks; i++) {
        AMediaFormat *format = AMediaExtractor_getTrackFormat(ex, i);
        const char *s = AMediaFormat_toString(format);
        LOGV("track %d format: %s", i, s);
        const char *mime;
        if (!AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &mime)) {
            LOGV("no mime type");
            return JNI_FALSE;
        } else if (!strncmp(mime, "video/", 6)) {
            // Omitting most error handling for clarity.
            // Production code should check for errors.
            AMediaExtractor_selectTrack(ex, i);
            codec = AMediaCodec_createDecoderByType(mime);
            AMediaCodec_configure(codec, format, d->window, NULL, 0);
            d->ex = ex;
            d->codec = codec;
            d->renderstart = -1;
            d->sawInputEOS = false;
            d->sawOutputEOS = false;
            d->isPlaying = false;
            d->renderonce = true;
            AMediaCodec_start(codec);
        }
        AMediaFormat_delete(format);
    }

    mlooper = new mylooper();
    mlooper->post(kMsgCodecBuffer, d);

    return JNI_TRUE;
}

Приложение воспроизводит видеоуспешно, когда они находятся в папке «assets», то есть внутри приложения. Но когда видео находится за пределами приложения (внутреннее / внешнее хранилище), приложение перестает работать.

Есть ли решение для этой проблемы?

1 Ответ

0 голосов
/ 14 марта 2019

Помимо добавления разрешения на хранение, пользователь должен также дать разрешение вручную.

В целях тестирования вы можете перейти в Настройки-> Приложения-> Ваше приложение-> Разрешения-> Включить разрешение на хранение. Должно работать нормально тогда.

Для производственных целей, вы должны запросить разрешение через диалог. Для этого есть множество учебных пособий.

...