I'm making a mobile rhythm game. I get songs from /storage/emulated/0/Music using Android plugin.
Get song title and music album cover
public class Impormation {
private MediaMetadataRetriever metaRetriver;
private byte[] image;
private String title;
private Context context;
public Impormation(Context context)
{
this.context = context;
}
public String setPath(String path)
{
metaRetriver = new MediaMetadataRetriever();
metaRetriver.setDataSource(path);
image = metaRetriver.getEmbeddedPicture();
title = metaRetriver.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
return path;
}
public byte[] getart()
{
return image;
}
public String gettitle()
{
return title;
}
}
But I don't know how to return mp3 file plugin to unity.
At first, I convert mp3 file to byte[], but I can convert byte[] to audioclip in unity. I consider to convert mp3 to wav. but It's too slow :(
please help me.
I assume that your final goal is to play the music file selected from the plugin. Since you are already able to retrieve the path of the music file. The next step is to put this music file into a AudioClip in Unity. And then using a AudioSource to play it.
And I found this Post. Though the creation of the AudioClip is been made on Windows system, I think it would work as long as you pass the correct file path on Android system.
Related
I'm making a mobile rhythm game. I get absolute path of song like this.
/storage/emulated/0/Music/a.mp3
I want to convert the mp3 file to audioClip.
But I can't a receive mp3 file from absolute path.
here is my code :
IEnumerator GetSoundFile(string path)
{
//path : '/storage/emulated/0/Music/a.mp3'
testText.text = path;
source = GetComponent<AudioSource>();
using (var www = new WWW(path))
{
yield return www;
source.clip = www.GetAudioClip();
}
SoundManager.instance.PlaySingle(source.clip);
}
How can I receive a music file?
You need to get the persistent path for android location , Try this
https://docs.unity3d.com/ScriptReference/Application-persistentDataPath.html
In android, add this function to get correct path:
...
path = GetUri(path);
...
private string GetUri(string uri)
{
if (uri.Contains("://") || uri.Contains(":///"))
return uri;
return "file://" + uri;
}
How can we find if a video contains Audio or not in Android
Is there any way in Android to find if a video contains audio
Yes. It is possible. You need to look into the MediaMetadataRetriever
By using METADATA_KEY_HAS_AUDIO you can check whether the video has the audio or not.
private boolean isVideoHaveAudioTrack(String path) {
boolean audioTrack =false;
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
retriever.setDataSource(path);
String hasAudioStr = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_AUDIO);
if(hasAudioStr!=null && hasAudioStr.equals("yes")){
audioTrack=true; }
else{
audioTrack=false; }
return audioTrack;
}
Here path is your video file path.
Just to add to #KingofMasses answer, if the file doesn't have a audio file then String hasAudioStr will return null. The string will then through a nullpointerexception.
here is how I resolved this:
private boolean doesVideoHaveAudioTrack(String path) {
boolean audioTrack;
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
retriever.setDataSource(path);
String hasAudioStr = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_AUDIO);
if (hasAudioStr==null){
audioTrack = false;
}else {
audioTrack = true;
}
return audioTrack;
}
All credit goes to #KingofMasses, I just wanted to point out the issue.
more simple, null pointer exception safe
boolean hasAudio = "yes".equals(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_AUDIO));
I have followed all the steps in testing an expansion file for my application. Where I am stuck now is how to play a video file contained in that expansion file.
I have successfully been able to download it from Google Play, and I can see it in the folder it is supposed to be in when I browse through my file manager.
I have looked for the past couple of days in trying to figure out how to play the file. At the moment there is only one for, to maintain appropriate size for testing.
I have tried to parse the URI and set it in the videoview, however, it always shows that the video cannot be played.
I have also tried this code so far to access it (as read in the documentation, and I have replaced the parameters with my parameters):
// Get a ZipResourceFile representing a merger of both the main and patch files
ZipResourceFile expansionFile = APKExpansionSupport.getAPKExpansionZipFile(appContext,
mainVersion, patchVersion);
// Get an input stream for a known file inside the expansion file ZIPs
InputStream fileStream = expansionFile.getInputStream(pathToFileInsideZip);
What do I do with the input stream in order to play the video?
Code for provider
public class EHZipUriProvider extends APEZProvider {
#Override
public String getAuthority() {
// TODO Auto-generated method stub
return "your.package.name.Utility.EHZipUriProvider";
}
}
Custom video player
public static final Uri CONTENT_URI = Uri
.parse("content://your.package.name.Utility.EHZipUriProvider");
public static VideoView mview;
public static void playVideo(Context context, VideoView resource, String VIDEO_NAME) {
position = 0;
mview = resource;
Uri video = Uri.parse((CONTENT_URI + "/" + VIDEO_NAME));
mview.setVideoURI(video);
mview.start();
mview.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
// TODO Auto-generated method stub
mview = null;
}
});
}
Calling in activity
VideoPlayer.playVideo(context, vv, "rulesofenglish.mp4");
For example, my application package name is:
com.bluewindsolution.android.sampleapp
Then my expansion file should be
main.1.com.bluewindsolution.android.sampleapp.obb
In detail, you can follow in here:
[main|patch].< expansion-version >.< package-name >.obb
From expansion you can get it via three ways:
via AssetFileDescriptor
// This one works with an image file and a media file.
// Get a ZipResourceFile representing a specific expansion file
// mainContext, version number of your main expansion, version number of your patch
ZipResourceFile expansionFile = APKExpansionSupport.getAPKExpansionZipFile(this, 1, 0);
AssetFileDescriptor afd_img1 = expansionFile.getAssetFileDescriptor("your_path/your_file.jpg");
AssetFileDescriptor afd_mpbg = expansionFile.getAssetFileDescriptor("your_path/your_file.mp3");
// To set image
ImageView imageView1 = (ImageView)findViewById(R.id.iv1);
imageView1.setImageBitmap(BitmapFactory.decodeFileDescriptor(afd_iv1.getFileDescriptor()));
// To set sound
try {
mpbg.setDataSource(afd_mpbg.getFileDescriptor(), afd_mpbg.getStartOffset(), afd_mpbg.getDeclaredLength());
mpbg.prepareAsync();
mpbg.start();
} catch (IllegalStateException e) {
Log.w("Error=====", "Failed to prepare media player", e);
}
Via InputStream:
// This one works with an image file and a media file.
// Get a ZipResourceFile representing a specific expansion file
ZipResourceFile expansionFile = new ZipResourceFile(filePathToMyZip);
// Get an input stream for a known file inside the expansion file ZIPs
InputStream fileStream = expansionFile.getInputStream(pathToFileInsideZip);
Via Uri
// This one can use in almost thing such as jpg, mp3, mp4, pdf, etc.
// You need to create a new class to override APEZProvider
public class ZipFileContentProvider extends APEZProvider {
#Override
public String getAuthority() {
return "com.bluewindsolution.android.sampleapp";
}
}
// You need to add <provider> in AndroidManifest.xml
<provider
android:name="com.bluewindsolution.android.sampleapp.ZipFileContentProvider"
android:authorities="com.bluewindsolution.android.sampleapp"
android:exported="false"
android:multiprocess="true"
>
<meta-data android:name="mainVersion"
android:value="1"></meta-data>
</provider>
// After that, you can use it any time by this code:
String filename2 = "image/i_commu_a_1_1_1_1.jpg"; // suppose you store put your file in directory in .obb
String uriString2 = "content://com.bluewindsolution.android.sampleapp" + File.separator + filename2;
Uri uri2 = Uri.parse(uriString2);
imageView2.setImageURI(uri2);
// Filename inside my expansion file
String filename = "video/v_do_1_1_1.mp4"; // Suppose you store put your file in directory in .obb
String uriString = "content://com.bw.sample_extension_download_main" + File.separator + filename;
Uri uri = Uri.parse(uriString);
v1 = (VideoView)findViewById(R.id.videoView1);
v1.setVideoURI(uri);
v1.start();
Using a provider (the best solution for me)! I tested it, and it works perfectly.
See Android: read media file from .obb using APEZ.
I'm using MediaRecorder class to record an audio file and I used
final String MEDIA_OUTPUT_FILE = "MyOutPutFile";
mediaRecorder.setOutputFile(MEDIA_OUTPUT_FILE);'
to give a name to my output file.
I also know how to Play an Audio File from Resources:
MediaPlayer mpRes = MediaPlayer.create(getApplicationContext(), R.raw.audiofile);
mpRes.start();'
My Question Is, Now, how to play the recorded file while I dont know where my MEDIA_OUTPUT_FILE is saved?
Instead of using constant as argument for mediaRecorder.setOutputFile() use a variable like below.
private String filePath;
filePath = Environment.getExternalStorageDirectory().getAbsolutePath();
filePath += "/myrecording.mpeg";
Then pass the filePath variable as the argument as follow;
mediaRecorder.setOutputFile(filePath);
Then you can play the recorded file as follows;
mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(filePath);
mediaPlayer.start();
That's it.
In my app I have two buttons play and download. In the downlod button I download video from internet and store in SD card, i will play video from the SD card when press play button.
Video is successfully downloaded and stored in SD card. If I press play button, I will list videos from SD card(in logcat) and play the downloaded video. It does not show the downloaded video name, but if I open the SD card from my system the downloaded video is stored in SD card. i do not know where i am wrong.
You have to add media files to Media Store in order to be seen by gallery widget. Use MediaScanner. I use this convenient wrapper in my code:
public class MediaScannerWrapper implements
MediaScannerConnection.MediaScannerConnectionClient {
private MediaScannerConnection mConnection;
private String mPath;
private String mMimeType;
// filePath - where to scan;
// mime type of media to scan i.e. "image/jpeg".
// use "*/*" for any media
public MediaScannerWrapper(Context ctx, String filePath, String mime){
mPath = filePath;
mMimeType = mime;
mConnection = new MediaScannerConnection(ctx, this);
}
// do the scanning
public void scan() {
mConnection.connect();
}
// start the scan when scanner is ready
public void onMediaScannerConnected() {
mConnection.scanFile(mPath, mMimeType);
Log.w("MediaScannerWrapper", "media file scanned: " + mPath);
}
public void onScanCompleted(String path, Uri uri) {
// when scan is completes, update media file tags
}
}
Then instantiate MediaScannerWrapper and start it with scan(). You could tweak it to handle more than one file at the time. Hint: pass List of File paths, and then loop around mConnection.scanFile.