Hi I am trying to play a video file on my Android wear.
The video file is located in the sdcard folder on the wearable device.
But I am unable to play it using my Android application.
If i run the same application on my smartphone (Nexus 5), it works.
How can I play a video file on Android Wearable using my android app.
Android Wear only includes Audio codecs as of Android Wear 5.0 so the normal MediaPlayer APIs won't work. You need to roll your own using video libraries like ffmpeg, ...
Finally I made it work. I don't know if this is something Android Wear specific or a bug, but it turns out that
String path = "android.resource://" + getPackageName() + "/" + R.raw.video_file;
File file = new File(path);
does not give access to the file on Android Wear devices.
Instead one has to convert the file into a temp file first:
InputStream ins = MainActivityBackup.this.getResources().openRawResource (R.raw.hyperlapse2);
File tmpFile = null;
OutputStream output;
try {
tmpFile = File.createTempFile("video","mov");
output = new FileOutputStream(tmpFile);
final byte[] buffer = new byte[102400];
int read;
while ((read = ins.read(buffer)) != -1) {
output.write(buffer, 0, read);
}
output.flush();
output.close();
ins.close();
} catch (IOException e) {
e.printStackTrace();
}
And then it can be loaded into a videoView
mVideoView.setVideoPath(tmpFile.getPath());
Provided you are using your own video decoder or a library like ffmpeg or vitamio, since Android Wear does not support native video playback yet.
I implemented vitamio in roughly 5 minutes, if needed it can be imported via gradle dependency (look for it on gradleplease). Built my app around vitamio videoView and it works like a charm. It can even play flash video.
Related
My project is all about media player. I want to store manually hundreds of mp3 files in my project but the problem is I don't know where I can put the large file which is the file size is 300MB into my project. I already search many times on google but the answer is always putting the file into ExternalDirectory by using this code.
File file = new File(getExternalFilesDir(null)+"/");
The problem of this code is you can only store a file to this directory once you downloaded the file. Since my project is an offline app, I don't need an internet connection to it
Here is my first attempt.
I put my one mp3 file to asset folder which is the size is 5mb and make a copy to another directory
File file = new File(getExternalFilesDir(null)+"/newFile.mp3"); please take a look below.
private void copyFile() {
InputStream inputStream;
try {
inputStream = getAssets().open("raw/original.mp3");
File file = new File(getExternalFilesDir(null)+"/newFile.mp3");
OutputStream outputStream = new FileOutputStream(file);
byte[] buffer = new byte[1024];
int length;
while ((length = inputStream.read(buffer)) > 0) {
outputStream.write(buffer,0,length);
}
outputStream.flush();
outputStream.close();
inputStream.close();
Log.d(TAG, "copyFile: copied ");
} catch (IOException e) {
e.printStackTrace();
}
}
the code above works fine. I can see that the file was successfully copied but the problem is during my research they said that asset folder or res/raw folder has a storage limit it means that I can only store a file in asset folder with a file size less than 5MB (I am not sure).
My question is what is the best way to manually store mp3 files (300MB) to my project(without downloading the files)?
Thanks and advance.
I have asked this question in Xamarins forum but nobody has answered, im hoping this forum can provide an answer for me.
My problem is how to play an mp3 file from a shared project on android.
I'm making a Xamarin Forms project and uses interfaces to make platform specific code for playning tha mp3 file.
I have embedded 360 mp3 files in my shared project, and the pass the file to the interface to make the mp3 play.
The class AudioHelper returns a stream by getting the correct mp3 file based on it's name
var assembly = typeof(StaveApp_v2.App).GetTypeInfo().Assembly;
var stream = assembly.GetManifestResourceStream
(resourcePrefix + $"Audio.{name}.mp3");
return stream;
Then I pass the stream to the Interface
var audioStream = AudioHelper.AudioFile("aften");
DependencyService.Get<IPlayWord>().Play(audioStream);
On windows the file plays as expected, but I’m having trouble getting the file to play on android. I'm using AudioTrack to play the sound (the sound should play 2 times). The app plays a scratchy sound 2 times with a duration matching the file length, but I can’t get it to play correctly.
This is the code im using
var memoryStream = new MemoryStream();
audio.CopyTo(memoryStream);
var audioBytes = memoryStream.ToArray();
var byteLenght = audioBytes.Length * sizeof(short);
var audioTrack = new AudioTrack(Android.Media.Stream.Music,
16000,
ChannelOut.Mono,
Encoding.Pcm16bit,
byteLenght,
AudioTrackMode.Static);
for (int i = 0; i < 2; i++)
{
try
{
audioTrack.Write(audioBytes, 0, audioBytes.Length);
audioTrack.Play();
}
catch (IllegalStateException illEx)
{
Log.Debug("StaveApp", $"Unable to initialize audio exception {illEx.Message}");
}
await Task.Delay(2000);
audioTrack.Stop();
audioTrack.ReloadStaticData();
}
audioTrack.Release();
audioTrack.Dispose();
I'm getting no errors in logcat and
I found this two possibilities to show a pdf file.
Open a webView with:
webView.loadUrl("https://docs.google.com/gview?embedded=true&url="+uri);
Open the pdf File with a extern App:
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(outFile),"application/pdf");
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(intent);
Both of them work. But my problem is that the pdf is for internal use only and in both examples the user could download it or save it in another folder.
I know frameworks for this in iOS dev, I looking for a solution that works with Android.
Android provides PDF API now with which it is easy to present pdf content inside application.
you can find details here
Below is the sample snippet to render from a pdf file in assets folder.
private void openRenderer(Context context) throws IOException {
// In this sample, we read a PDF from the assets directory.
File file = new File(context.getCacheDir(), FILENAME);
if (!file.exists()) {
// Since PdfRenderer cannot handle the compressed asset file directly, we copy it into
// the cache directory.
InputStream asset = context.getAssets().open(FILENAME);
FileOutputStream output = new FileOutputStream(file);
final byte[] buffer = new byte[1024];
int size;
while ((size = asset.read(buffer)) != -1) {
output.write(buffer, 0, size);
}
asset.close();
output.close();
}
mFileDescriptor = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
// This is the PdfRenderer we use to render the PDF.
if (mFileDescriptor != null) {
mPdfRenderer = new PdfRenderer(mFileDescriptor);
}
}
update: This snippet is from google developers provided samples.
Many libraries are available for showing pdfs within your own app.
Android PDF Viewer
VuDroid
APDFViewer
droidreader
android-pdf
mupdf
android-pdfView
For a working example using android-pdfView, see this blog post.
It demonstrates the basic usage of the library to display pdf onto the view with vertical and horizontal swipe.
pdfView = (PDFView) findViewById(R.id.pdfView);
pdfView.fromFile(new File("/storage/sdcard0/Download/pdf.pdf")).defaultPage(1).enableSwipe(true).onPageChange(this).load();
You can show the PDF in your own viewer
Tier are few open source pdf viewers you should look at:
http://androiddeveloperspot.blogspot.com/2013/05/android-pdf-reader-open-source-code.html
You can encrypt the pdf and make sure that your viewer only will be able to decrypt it.
My goal:
Download a zip file that contains a video and JS file. Create a webview that runs the JS file which (among other things) contains a video tag to play that video file.
Problem: when I try to play the video I get an error saying "Sorry this video cannot be played". In logcat I get: error( 1, -2147483648)
Here is the code to unzip the files:
String path = context.getFilesDir().getPath()+"/";
InputStream is;
ZipInputStream zis;
try {
is = new FileInputStream(zip file);
zis = new ZipInputStream( new BufferedInputStream(is));
ZipEntry ze = null;
while ((ze = zis.getNextEntry()) != null) {
String filename = ze.getName();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int count;
FileOutputStream fout =
_context.openFileOutput( path + filename, Context.MODE_WORLD_READABLE );
while ((count = zis.read(buffer)) != -1) {
baos.write(buffer, 0, count);
baos.toByteArray();
fout.write(baos.toByteArray());
baos.reset();
}
fout.close();
zis.closeEntry();
baos.close();
}
zis.close();
}
To show the video I override MraidWebChromeClient.onShowCustomView:
super.onShowCustomView(view, callback);
if (view instanceof FrameLayout) {
FrameLayout frame = (FrameLayout) view;
if (frame.getFocusedChild() instanceof VideoView) {
VideoView video = (VideoView) frame.getFocusedChild();
frame.removeView(video);
Activity a = (Activity)getContext();
a.setContentView(video);
video.setOnCompletionListener(this);
video.setOnErrorListener(this);
video.start();
}
}
I do not believe there is an error with the video file, pathing or JS because:
The video plays fine if included as a resource in res or streamed with an external http link.
when loading the js file I use loadDataWithBaseURL and all other image elements show up fine.
I have copied the file from res to the local app folder (using similar code to the unzipping code) and the same error occurs.
I am thinking either:
the file is being corrupted while its being unzipped/copied
there is a permissions issue for playing a local video from a webview (even after I've set the file to world_readable. (from this link WebView NOT opening android default video player?)
Any insights into this issue would be greatly appreciated!
K
Ps: does anyone know why in the normal web-browser it will download .mp4 links while in other cases it will try and stream them?
EDIT:
After researching these two post seem to suggest that Android has security to prevent this:
Android - Load video from private folder of app
Playing an app local video (.mp4) in a webview
Copying files to public external worked fine.
And with regards to the Ps: why some videos stream and some are downloaded, Android 3 doesn't support streaming from https and so will download the file.
Since you're unzipping/reading video to/from the SD card, make sure to add the following line to your manifest file: <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Since you're using JS, make sure to enable it in your WebView as follows:
private WebView mWebView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
...
...
mWebView = (WebView) findViewById(R.id.webview);
mWebView.getSettings().setJavaScriptEnabled(true);
...
}
As for video playback, the most reliable solution I've found so far is to hand it off to the native media player app (cause I found the WebView really buggy). In order to achieve this, you need to Bind JavaScript code to Android code so that when the user taps on a video thumbnail, you create the corresponding intent and launch the media player app as follows:
Intent i = new Intent();
i.setAction(android.content.Intent.ACTION_VIEW);
File file = new File(PATH_TO_YOUR_VIDEO);
i.setDataAndType(Uri.fromFile(file), "video/*");
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
mContext.startActivity(i);
[UPDATE] As per the official documentation (see under "Accessing files on external storage"),
"If you're using API Level 8 or greater, use getExternalFilesDir() to open a File that represents the external storage directory where you should save your files".
"If you're using API Level 7 or lower, use getExternalStorageDirectory(), to open a File representing the root of the external storage".
Your unzipping code contains the line String path = context.getFilesDir().getPath(), try to modify it as per the above.
I have an Android (2.2) project in Eclipse (Helios). I want to add an MP3 file to the project so that the MP3 file is deployed to the device along with the application.
I then would like to open the file as a File object, which means I'd need to know the full path (?) to the file on the device, but I don't know how paths are specified in Android.
Apparently there is a bug in Froyo that prevents WAV playback.
Audio files should be placed in the "res/raw" directory of your project. Then use the id to play it (or attempt to play it)
MediaPlayer mp = MediaPlayer.create(context, R.raw.sound_file_1);
mp.start();
Info: http://developer.android.com/guide/topics/media/index.html
Example (mp3): http://www.helloandroid.com/tutorials/musicdroid-audio-player-part-i
Ok, I saw this on the source of another projet, so I didn't really come up with it, but it works.
To add any file to a project, and later be able to use it, you need to put the file (binary, xml, or whatever) on the assets folder of your project.
In this example I will just copy the asset to the filesystem, so I can later access it as any other user file. You can access the assets directly too, take a look at Resources on the documentation.
public void copyfile(String fileName)
{
if (!new File(fileName).exists()){
try
{
InputStream localInputStream = getAssets().open(fileName);
FileOutputStream localFileOutputStream = getBaseContext().openFileOutput(fileName, MODE_PRIVATE);
byte[] arrayOfByte = new byte[1024];
int offset;
while ((offset = localInputStream.read(arrayOfByte))>0)
{
localFileOutputStream.write(arrayOfByte, 0, offset);
}
localFileOutputStream.close();
localInputStream.close();
// The next 3 lines are because I'm copying a binary that I plan
// to execute, so I need it to have execute permission.
StringBuilder command = new StringBuilder("chmod 700 ");
command.append(basedir + "/" + paramString);
Runtime.getRuntime().exec(command.toString());
Log.d(TAG, "File " + paramString + " copied successfully.");
}
catch (IOException localIOException)
{
localIOException.printStackTrace();
return;
}
}
else
Log.d(TAG, "No need to copy file " + paramString);
}
I believe there is probably a better way to copy the file, but this one works, and does not slow down my app even if it's called from onCreate (all files I copy are below 100kb though, so for bigger files, you probably want a separate thread)
Here is how to get the path to your files:
String path = getBaseContext().getFilesDir().getAbsolutePath();
If you want to write the file to another path, say "/sdcard/DCIM/appPictures", I believe you can use this code:
FileOutputStream outFile = FileOutputStream("/sdcard/DCIM/appPictures/" + fileName);
and then copy it byte by byte like in the example above.