2015-10-07 2 views
0

У меня есть довольно странная проблема. Я пишу приложение для Android, используя инфраструктуру Xamarin, и у меня также есть версия iOS того же приложения, также написанная на Xamarin. В приложении пользователь может отправлять фотографии и видео друзьям, а их друзья могут быть на iOS или Android. Все это прекрасно работает, а видео, сделанные на iPhone, можно воспроизводить на устройстве Android и наоборот.Android: видео, сохраненное в галерее, не будет воспроизводиться

Проблема, с которой я сталкиваюсь, заключается в том, что когда я пытаюсь программно сохранить видео в галерее Android, то это видео не может воспроизводиться в галерее. Похоже, что видеоданные, на самом деле, копируются, но видео как-то не воспроизводится.

Мои видеоролики кодируются в формате mp4 с использованием кодека H.264. Я считаю, что это полностью поддерживается в Android, и, как я уже сказал, видео отлично воспроизводятся при воспроизведении через VideoView в приложении.

Код, который я использую, чтобы скопировать видео в галерею ниже. Кто-нибудь знает, что я делаю неправильно здесь?

public static void SaveVideoToGallery(Activity activity, String filePath) { 

    // get filename from path 
    int idx = filePath.LastIndexOf("/") + 1; 
    String name = filePath.Substring(idx, filePath.Length - idx); 

    // set in/out files 
    File inFile = new File(filePath); 
    File outDir = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryMovies); 
    File outFile = new File(outDir, name); 

    // Make sure the Pictures directory exists. 
    outDir.Mkdirs(); 

    // save the file to disc 
    InputStream iStream = new FileInputStream(inFile); 
    OutputStream oStream = new FileOutputStream(outFile); 
    byte[]data = new byte[iStream.Available()]; 
    iStream.Read(); 
    oStream.Write(data); 
    iStream.Close(); 
    oStream.Close(); 

    // Tell the media scanner about the new file so that it is 
    // immediately available to the user. 
    MediaScannerConnection.ScanFile(
     activity.ApplicationContext, 
     new String[] { outFile.ToString() }, 
     null, 
     null); 
} 

Примечание: Я знаю, что все это в C#, но имейте в виду, что все рамки Xamarin делает это предоставить API для нативных методов Android. Все, что я использую, - это классы или функции, поддерживаемые Java или Android.

Спасибо!

ответ

1

Ваш вопрос в этом фрагменте кода:

byte[]data = new byte[iStream.Available()]; 
iStream.Read(); 
oStream.Write(data); 

Есть несколько вопросов здесь:

  • Вы никогда не читали файлы содержимое в буфер data; iStream.Read() будет читать только один байт и возвращать его как целое число.
  • new byte[iStream.Available()] будет выделять только количество байтов данных, которые можно читать без блокировки. Это не полный файл. См. Документы по методу available.
  • oStream.Write(data) выписывает мусорный блок данных, поскольку в него ничего не читается.

Конечный результат: выведенный видеофайл - это всего лишь блок с пустыми данными, поэтому галерея не может его использовать.

еекнопку считывания данных из потока файлов, а затем записывая их в выходной файл:

int bytes = 0; 
    byte[] data = new byte[1024]; 
    while ((bytes = iStream.Read(data)) != -1) 
    { 
     oStream.Write (data, 0, bytes); 
    } 

Полный пример:

public static void SaveVideoToGallery(Activity activity, String filePath) { 

    // get filename from path 
    int idx = filePath.LastIndexOf("/") + 1; 
    String name = filePath.Substring(idx, filePath.Length - idx); 

    // set in/out files 
    File inFile = new File(filePath); 
    File outDir = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryMovies); 
    File outFile = new File(outDir, name); 

    // Make sure the Pictures directory exists. 
    outDir.Mkdirs(); 

    // save the file to disc 
    InputStream iStream = new FileInputStream(inFile); 
    OutputStream oStream = new FileOutputStream(outFile); 

    int bytes = 0; 
    byte[] data = new byte[1024]; 
    while ((bytes = iStream.Read(data)) != -1) 
    { 
     oStream.Write (data, 0, bytes); 
    } 

    iStream.Close(); 
    oStream.Close(); 

    // Tell the media scanner about the new file so that it is 
    // immediately available to the user. 
    MediaScannerConnection.ScanFile(
     activity.ApplicationContext, 
     new String[] { outFile.ToString() }, 
     null, 
     null); 
} 
+0

Хорошо да, я думал, что удельная площадь странно, когда Я написал это, но я следовал примеру из документации на Android, поэтому просто предположил, что это правильно. Я пробовал это, и теперь он отлично работает, так что спасибо за помощь и отличную информацию. Один вопрос у меня есть, хотя. Если строка «new byte [1024]» создает массив байтов размером 1024 байта, то как он может хранить более 1024 байта данных? Наверное, глупый вопрос, но сейчас мне любопытно. –

+0

Не глупый вопрос, 1024 - временный буфер, который принимает небольшие фрагменты файла 'iStream', а затем добавляет его к' oStream'. Он используется повторно столько раз, сколько необходимо для копирования всего файла. – matthewrdev

+1

А, я вижу, поэтому для каждого прохода требуется 1024 куска по каждому проходу. Имеет смысл. Спасибо дружище! –

Смежные вопросы