I am developing a test app that does nothing else than play music. The idea behind this app is that normally you have a music player that takes ages to load and has all those extra gadgets and gizmos that nobody, or at least not you, uses. This app only plays music, period. And it loads almost instantly.
But I got something funny. I need to find a way for the user to select a song from the filesystem, but I haven't got that working yet, so I am using a fixed song URI to play it. When I put this song on the local filesystem(i.e. /storage/emulated/0/Music/SongName.mp3), the app crashes upon pressing the play button. But when I put the song on the SD card(i.e. /storage/extSdCard/Music/SongName.mp3) it works fine.
Well, I got it to work, but I don't know how or why it works. Normally I would be surprised and not touch that piece of code again so that it keeps working, but this time I am learning programming on Android and I want to know why it works.
This is the code for playing from the SD card(works):
p = new MediaPlayer();
p.setAudioStreamType(AudioManager.STREAM_MUSIC);
p.setDataSource(getApplicationContext(), Uri.fromFile(new File("/storage/extSdCard/Tests/Take Back The Night.mp3")));
p.prepare();
p.start();
And this is the code for playing from the local fs(does not work):
p = new MediaPlayer();
p.setAudioStreamType(AudioManager.STREAM_MUSIC);
p.setDataSource(getApplicationContext(), Uri.fromFile(new File("/storage/emulated/0/Music/heybrother.mp3")));
p.prepare();
p.start();
As you can see, it's pretty much the same, so I concluded that there is probably something wrong in the URI. But I can't see any typos, and I retyped it multiple times. Is the URI malformed for this purpose?
I got it working!
First, you need to get the path of the music folder like this:
String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC)
.getPath() + "/";
Then you can append the file name in the music folder:
String file = path + "ThatOneSong.mp3";
And then play it as normal. (Or you could do this in one long line but that's kind of cluttered.)
Related
I have a weird problem, I am playing a video file from local storage, if the video name is "test#.mp4" it does not work and shows "media not found" toast, if it's "test.mp4", it works fine, no idea where is the problem.
basically if the name has "#" anywhere, the video does not play.
Here is my code
String item = names.get(itemPosition); // file name eg. test#.mp4
Uri uri = Uri.parse(context.getExternalFilesDir(null).getAbsolutePath() + "/MyFiles/"+item); // path to file
Intent intent = new Intent(Intent.ACTION_VIEW,uri);
intent.setDataAndType(uri, "video/*");
context.startActivity(intent);
The answer is that I needed to use FileProvider, I have no idea why my earlier method was working and sometimes not.Also because the original documentation is so confusing, I used this answer, I took a look at the actual Uri and everything made sense now! android.os.FileUriExposedException: file:///storage/emulated/0/test.txt exposed beyond app through Intent.getData()
I am working on a simple music app in android and I have tried adding EnviromentalReverb and PresetReverb to mediaPlayer (wav and m4a formats) but the reverb doesn't apply. There is no change when the audio plays. I have checked whether my device supports the reverb using the below code and it does. I have looked at similar questions on stackoverflow but there isn't an answer that works.
final AudioEffect.Descriptor[] effects = AudioEffect.queryEffects();
// Determine available/supported effects
for (final AudioEffect.Descriptor effect : effects) {
Log.d("Effects", effect.name.toString() + ", type: " + effect.type.toString());
}
The code used for EnvironmentalReverb and PresetReverb is below
First try
EnvironmentalReverb eReverb = new EnvironmentalReverb(1,0);
eReverb.setReverbDelay(85);
eReverb.setEnabled(true);
mMediaPlayer.attachAuxEffect(eReverb.getId());
mMediaPlayer.setAuxEffectSendLevel(1.0f);
Second try
PresetReverb mReverb = new PresetReverb(1, 0);
mReverb.setPreset(PresetReverb.PRESET_LARGEROOM);
mReverb.setEnabled(true);
mMediaPlayer.attachAuxEffect(mReverb.getId());
mMediaPlayer.setAuxEffectSendLevel(1.0f);
Both return 0 for setEnabled(true) but neither work on the audio. Can someone please point me in the right direction? I am not sure what is wrong with the implementation.
Answering my question so it can be helpful for someone else.
I wasn't able to get the PresetReverb to work. The EnvironmentalReverb however was working but to find out whether it was working I had to add seekbars for room level and reverb level so I could alter it in real time.
EnvironmentalReverb eReverb = new EnvironmentalReverb(0,0);
mMediaPlayer.attachAuxEffect(eReverb.getId());
mMediaPlayer.setAuxEffectSendLevel(1.0f);
I enabled the reverb on click of a button and then used seek bars to change the room level and reverb level.
I'm trying to play a sound when a button is clicked or when a new view is showing up. I wrote this method to play a sound:
void play_sound(String musicFile) {
AudioClip sound = new AudioClip(new File(musicFile).toURI().toString());
sound.play();
}
and this is how I call it:
String musicFile = "src/resources/sounds/applause.mp3";
play_sound(musicFile);
I have to mention that applause.mp3 is downloaded from the web and when I play a sound from web it works. But when I want to play a sound that is recorded (for example app.mp3), it doesn't work anymore. All these files are in the same folder(sounds).
Your file path should definitely start with a / to mark it as absolute (inside of the jar file).
Then, you should'nt use the File class to load resources from inside the jar file. Use
String path = getClass().getResource("/resources/sounds/applause.mp3")
AudioClip sound = new AudioClip(path);
instead.
Cheers
I'm attempting to send an image to Hangouts from within an app I'm building.
I'm working in Xamarin for VS 2015 to do this so the code below is c# but it's not much different from the equivalent Java code so I think it's easy to follow.
What I've done is set up a button on my app which has code setting up an Intent to share an image to Hangouts. I've set the image up already in the Downloads folder on the device and hardcoded the name into the code.
Intent hangoutsShareIntent = new Intent(Intent.ActionSend);
hangoutsShareIntent.SetType("image/jpeg");
hangoutsShareIntent.SetPackage("com.google.android.talk");
string downloadsPath = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads).AbsolutePath;
string filePath = Path.Combine(downloadsPath, "shared.jpg");
hangoutsShareIntent.PutExtra(Intent.ExtraStream, filePath);
StartActivity(Intent.CreateChooser(hangoutsShareIntent, "Share with"));
When I run this, I get the option to select a chat in Hangouts that I want to send the content to. Upon selecting the chat, I get a blank message box and no image.
I've swapped the above code over to use text/plain and pass the filePath variable to the message. When I copy the file path into Chrome to check it, the image loads so I have to figure that the image is where I've said it is... right?
I get no errors (probably because the issue is in Hangouts rather than my app so I have nothing to debug there). Logcat shows nothing except an error I can't find much about on Google: ExternalAccountType﹕ Unsupported attribute readOnly
The only information I could find on that error implied some issue with permissions but I've made sure my app has runtime permissions checked for Read/Write using this code (which wraps the above):
if ((CheckSelfPermission(Permission.ReadExternalStorage) == (int)Permission.Granted) &&
(CheckSelfPermission(Permission.WriteExternalStorage) == (int)Permission.Granted))
NOTE: I'm running this on a HTC One M8 - no SD card but does have external storage on device. I've also added the above permissions to the manifest for earlier Android versions.
The documentation for this (here) isn't overly helpful either so any advice AT ALL here is welcome :)
Thanks!
If you use the file provider instead of sending just the URI on its own. This should get around the permission issues you are seeing.
There is a guide available here which might be useful.
Intent shareIntent = new Intent(Intent.ActionSend);
shareIntent.SetType("image/gif");
Java.IO.File file = new Java.IO.File(Android.OS.Environment.ExternalStorageDirectory + "/myimage.gif");
Android.Net.Uri fileUri = Android.Support.V4.Content.FileProvider.GetUriForFile(this, "com.myfileprovider", file);
shareIntent.SetPackage("com.google.android.talk");
shareIntent.AddFlags(ActivityFlags.GrantReadUriPermission);
shareIntent.PutExtra(Intent.ExtraStream, fileUri);
StartActivity(Intent.CreateChooser(shareIntent, "Share with"));
I need to play Alert.startAudio() through the loudspeaker of a Blackberry device instead of the headset.
I know that I can change the Audio path through the AudioPathControl interface, but I don't know how to get an instance of AudioPathControl.
I found a LINK on how to do it on the Blackberry Knowledge base, but it only tells me how to do it using the Player class, which I don't want to do. Is there any way to get an instance of AudioPathControl of the current Application?
I would prefer to play a tone programmatically instead of including my own sound file. I found the following code snippet for that.
Player p = javax.microedition.media.Manager.createPlayer(javax.microedition.media.Manager.TONE_DEVICE_LOCATOR);
p.realize();
ToneControl tc = (ToneControl) p.getControl("ToneControl");
AudioPathControl apc = (AudioPathControl) p
.getControl("AudioPathControl");
apc.setAudioPath(AudioPathControl.AUDIO_PATH_HANDSFREE);
tc.setSequence(mySequence);
p.start();
But the problem is that apc is null and throws an Exception. Any solution?
Check the section Where Does the Sound Go? (preview from Google Books), from Advanced BlackBerry 6 Development By Chris King.