ver - sistema de vigilancia casera con telefonos android viejos
¿Puede una videovigilancia reproducir un video almacenado en el almacenamiento interno? (6)
Estoy tratando de proporcionar a mis usuarios la capacidad de usar almacenamiento externo o interno. Estoy mostrando imágenes y videos (de naturaleza científica). Al almacenar los medios en la tarjeta SD, todo está bien. Pero cuando almaceno los medios internamente, solo se mostrarán las imágenes. No importa lo que intente, obtengo varios errores al intentar cargar y mostrar los medios almacenados en applicationcontext.getFilesDir ().
¿Hay algún truco para configurar el contenido de una videovisión en un archivo de este tipo?
¿Puede un ContentResolver ayudarme?
En una nota relacionada, ¿se considera incorrecto suponer que existe almacenamiento externo?
Gracias por adelantado,
Sid
A continuación hay una versión que falla con "No se puede reproducir el video. Lo sentimos, este video no se puede reproducir". Pero tengo muchos otros modos de fracaso. Puedo copiar el video interno al almacenamiento temporal (externo) y reproducirlo, por lo que esta copia al interno crea una película válida. Solo falla cuando intento reproducirlo directamente desde el almacenamiento interno.
videoFile = new File(this.getFilesDir() + File.separator + "test.mp4");
InputStream data = res.openRawResource(R.raw.moviegood);
try {
OutputStream myOutputStream = new FileOutputStream(videoFile);
byte[] buffer = new byte[8192];
int length;
while ( (length = data.read(buffer)) > 0 ) {
myOutputStream.write(buffer);
}
//Close the streams
myOutputStream.flush();
myOutputStream.close();
data.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
vview.setKeepScreenOn(true);
vview.setVideoPath(videoFile.getAbsolutePath());
vview.start();
Encontré este hilo con el mismo problema, estoy descargando mis videos de la web al almacenamiento interno, resulta que al guardar puede especificar el modo RW, es decir, cambiar de PRIVATE
a WORLD_READABLE
URL url = new URL(_url);
InputStream input = null;
FileOutputStream output = null;
try {
String outputName = "video.mp4";
input = url.openConnection().getInputStream();
output = c.openFileOutput(outputName, Context.MODE_WORLD_READABLE);
int read;
byte[] data = new byte[5120]; //5MB byte array
while ((read = input.read(data)) != -1)
output.write(data, 0, read);
return true;
} finally {
if (output != null)
output.close();
if (input != null)
input.close();
}
}
MediaPlayer requiere que el archivo que se está reproduciendo tenga permisos de lectura mundial. Puede ver los permisos del archivo con el siguiente comando en el shell adb:
ls -al /data/data/com.mypackage/myfile
Probablemente verá "-rw ------", lo que significa que solo el propietario (su aplicación, no MediaPlayer) tiene permisos de lectura / escritura.
Nota: su teléfono debe estar rooteado para poder usar el comando ls sin especificar el archivo (en la memoria interna).
Si su teléfono está rooteado, puede agregar permisos de lectura mundial en el shell adb con el siguiente comando:
chmod o+r /data/data/com.mypackage/myfile
Si necesita modificar estos permisos mediante programación (¡requiere un teléfono rooteado!), Puede usar el siguiente comando en el código de su aplicación:
Runtime.getRuntime().exec("chmod o+r /data/data/com.mypackage/myfile");
Que es básicamente un comando de linux. Consulte https://help.ubuntu.com/community/FilePermissions para obtener más información sobre chmod.
EDITAR: Encontró otro enfoque simple here (útil para aquellos sin teléfonos rooteados). Como la aplicación es propietaria del archivo, puede crear un descriptor de archivo y pasarlo a mediaPlayer.setDataSource ():
FileInputStream fileInputStream = new FileInputStream("/data/data/com.mypackage/myfile");
mediaPlayer.setDataSource(fileInputStream.getFD());
Este enfoque evita el problema del permiso por completo.
No puedes simplemente jugarlo directamente.
Debe implementar un ContentProvider y luego pasar el Uri definido al método setVideoUri (uri).
Para más detalles consulte este tutorial.
public class AndroidVideoViewExample extends Activity {
private VideoView myVideoView;
private int position = 0;
private ProgressDialog progressDialog;
private MediaController mediaControls;
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// set the main layout of the activity
setContentView(R.layout.activity_main);
//set the media controller buttons
if (mediaControls == null) {
mediaControls = new MediaController(AndroidVideoViewExample.this);
}
//initialize the VideoView
myVideoView = (VideoView) findViewById(R.id.video_view);
// create a progress bar while the video file is loading
progressDialog = new ProgressDialog(AndroidVideoViewExample.this);
// set a title for the progress bar
progressDialog.setTitle("JavaCodeGeeks Android Video View Example");
// set a message for the progress bar
progressDialog.setMessage("Loading...");
//set the progress bar not cancelable on users'' touch
progressDialog.setCancelable(false);
// show the progress bar
progressDialog.show();
try {
//set the media controller in the VideoView
myVideoView.setMediaController(mediaControls);
//set the uri of the video to be played
myVideoView.setVideoURI(Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.kitkat));
} catch (Exception e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
myVideoView.requestFocus();
//we also set an setOnPreparedListener in order to know when the video file is ready for playback
myVideoView.setOnPreparedListener(new OnPreparedListener() {
public void onPrepared(MediaPlayer mediaPlayer) {
// close the progress bar and play the video
progressDialog.dismiss();
//if we have a position on savedInstanceState, the video playback should start from here
myVideoView.seekTo(position);
if (position == 0) {
myVideoView.start();
} else {
//if we come from a resumed activity, video playback will be paused
myVideoView.pause();
}
}
});
}
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
//we use onSaveInstanceState in order to store the video playback position for orientation change
savedInstanceState.putInt("Position", myVideoView.getCurrentPosition());
myVideoView.pause();
}
@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
//we use onRestoreInstanceState in order to play the video playback from the stored position
position = savedInstanceState.getInt("Position");
myVideoView.seekTo(position);
}
}
Publiqué una implementación personalizada de VideoView there .
La implementación de VideoView tiene el setVideoFD(FileDescriptor fd)
y resuelve este problema.
Puedes usar:
videoView.setVideoURI(Uri.parse(file.getAbsolutePath()));
si el archivo es legible en todo el mundo
O puedes usar un proveedor de contenido