Error when trying to play audio file from URI - java

So I'm completely new to Android programming and I'm starting off by trying to make an app that allows users to edit audio files. Here is my code so far, which makes a user upload an audio file and play it:
public class MainActivity extends Activity {
final int ACTIVITY_CHOOSE_FILE = 1;
public String filePath;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) this.findViewById(R.id.uploadbutton);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent chooseFile;
Intent intent;
chooseFile = new Intent(Intent.ACTION_GET_CONTENT);
chooseFile.setType("audio/mpeg");
intent = Intent.createChooser(chooseFile, "Choose a file");
startActivityForResult(intent, ACTIVITY_CHOOSE_FILE);
}
});
Button playButton = (Button)findViewById(R.id.playbutton);
playButton.setOnClickListener(new Button.OnClickListener() {
#Override
public void onClick(View v) {
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
mp.setDataSource(getApplicationContext(), Uri.parse(filePath));
} catch (IOException e) {
e.printStackTrace();
}
try {
mp.prepare();
} catch (IOException e) {
e.printStackTrace();
}
mp.start();
}
});
}
});
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case ACTIVITY_CHOOSE_FILE: {
if (resultCode == RESULT_OK) {
Uri uri = data.getData();
filePath = uri.getPath();
getFilePath(filePath);
TextView URI_Text = (TextView)findViewById(R.id.file_URI);
URI_Text.setText(filePath);
}
}
}
}
public String getFilePath (String filePath) {
return filePath;
}
}
However, I'm getting the error code E/Surface: getSlotFromBufferLocked: unknown buffer: 0xab756e00
What am I doing wrong?

That error is not related to any of your code from your question. However, you are going wrong in other places.
getPath() is useless. The Uri should be treated as an opaque handle. Calling getPath() on a Uri, and expecting a file to be at that path, is akin to expecting there to be a /questions/33843271/error-when-trying-to-play-audio-file-from-uri path on your computer's hard drive, just because your browser happens to be showing a URL with that path.
Also, your access to the data represented by that Uri is short-lived. This is reminiscent of Web development, where you might be able to stream data from some URL for a while, but eventually your session times out. Saving the Uri is pointless. Either consume the data now (via a ContentResolver and openInputStream()), or don't bother with the data at all.

Related

How to pass a file from a file picker to a function?

I have an app that opens up a file picker and it outputs the path of that file in a Toast Message.
But I would like to change it such that the file that I pick is passed as a parameter to a function.
My activity looks like this:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.btn_picker);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("*/*");
startActivityForResult(intent, 7);
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
switch (requestCode) {
case 7:
if (resultCode == RESULT_OK) {
String PathHolder = data.getData().getPath();
Toast.makeText(MainActivity.this, "The Files path is: "+ PathHolder, Toast.LENGTH_LONG).show();
}
break;
}
}
}
And it does what it is supposed to do but instead of outputting the file path, I would like to call the function
importToFile()
From the manage class.
I would like to do something like this:
manage.importToFile(File1)
Where File1 is the file I selected from the file picker.
How can I do that.
Thanks in advance.
You can use File class in android to work with files. Create an instance of File using the path of the selected file and pass it to that method of yours. Something like this:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
switch (requestCode) {
case 7:
if (resultCode == RESULT_OK) {
// as #Taseer Ahmad said its not a good way to get path of the file.
//String PathHolder = data.getData().getPath();
String PathHolder = getPath(this, data.getData());
if (!TextUtils.isEmpty(PathHolder)) {
File file = new File(PathHolder);
manager.importToFile(file);
Toast.makeText(MainActivity.this, "The Files path is: "+ PathHolder, Toast.LENGTH_LONG).show();
}
}
break;
}
}
EDIT
As #Taseer Ahmad said, data.getData().getPath() is not a safe way to get path of the selected file. This code is copied from here.
public static String getPath(Context context, Uri uri) throws URISyntaxException {
if ("content".equalsIgnoreCase(uri.getScheme())) {
String[] projection = { "_data" };
Cursor cursor = null;
try {
cursor = context.getContentResolver().query(uri, projection, null, null, null);
int column_index = cursor.getColumnIndexOrThrow("_data");
if (cursor.moveToFirst()) {
return cursor.getString(column_index);
}
} catch (Exception e) {
// Eat it
}
} else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
return null;
}

Play a success sound ONLY when Activity is complete

I have created an app that you could share images with them. I have set a notification sound when the sharing process is done. However, if I hit Cancel/Back buttons, the sound still plays.
In my code below, I have set a share button, once you click on it, you can share a bitmap of the image through the basic sharing app of android.
How can I set the sound to ONLY play when the sharing is complete.
Thanks,
Safi
Here's my code:
shareBtn = findViewById(R.id.shareButton);
shareBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
v.startAnimation(animTranslate);
shareDigitalCard();
}
});
private void shareDigitalCard() {
if (ActivityCompat.checkSelfPermission(MyMenu.this,
android.Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
try {
makeStorageRequest();
} catch (Exception e) {
e.printStackTrace();
}
}else {
Bitmap viewBmp = Bitmap.createBitmap(mPager.getWidth(),
mPager.getHeight(), Bitmap.Config.ARGB_8888);
viewBmp.setDensity(mPager.getResources().getDisplayMetrics().densityDpi);
Canvas canvas = new Canvas(viewBmp);
//mPager.layout(0, 0 , mPager.getLayoutParams().width, mPager.getLayoutParams().height);
mPager.draw(canvas);
path = String.valueOf(saveTempBitmap(viewBmp));
shareImage(path);
}
}
private void shareImage(String file) {
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
Intent share = new Intent(Intent.ACTION_SEND);
// If you want to share a png image only, you can do:
// setType("image/png"); OR for jpeg: setType("image/jpeg");
share.setType("image/*");
File imageFileToShare = new File(file);
Uri uri = Uri.fromFile(imageFileToShare);
share.putExtra(Intent.EXTRA_STREAM, uri);
try {
startActivityForResult(Intent.createChooser(share, "Share Image!"),123);
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 123){
if (isSoundEnable) {
MediaPlayer player = null;
if (player == null) {
player = MediaPlayer.create(this, R.raw.success);
final MediaPlayer finalPlayer = player;
player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
stopPlayer(finalPlayer);
}
});
}
player.start();
}
} else {
Toast.makeText(this, "An Error Has Occured !", Toast.LENGTH_SHORT).show();
}
}
You cannot get this event. The sharing procedure depends on the other App and you haven't any control or result from it. What you know is just you have send an Intent to a specific App, but what it does it's all up to it.

Android - MediaPlayer (open failed: ENOENT (No such file or directory)

I asked a question earlier play video in new activity
What I want is when (Button) findViewById(R.id.pickVid); is clicked it calls PICK_VIDEO_REQUEST, then when the video is selected the new activity should open and play the video.
The guy that helped me said that I should use this.mPlayer.setDataSource(mStringFilePath); instead of FileInputStream
PROBLEM:
I am getting a error saying setDataSource failed.: status=0x80000000 with a black screen.
MainActivity
public class MainActivity extends AppCompatActivity {
Uri mMediaUri;
String vidFile;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button pickVid = (Button) findViewById(R.id.pickVid);
//choose the video
pickVid.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent chooseVideo = new Intent(Intent.ACTION_GET_CONTENT);
chooseVideo.setType("video/*");
startActivityForResult(chooseVideo, PICK_VIDEO_REQUEST);
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == PICK_VIDEO_REQUEST) {
if (resultCode == RESULT_OK) {
mMediaUri = data.getData();
vidFile = mMediaUri.toString();
Intent playVid = new Intent(MainActivity.this, PlayVideoAct.class);
playVid.putExtra("vidFile", vidFile);
startActivity(playVid);
}
}
}
PlayVideoAct
String mStringFilePath;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_playvideo);
mStringFilePath = getIntent().getStringExtra("vidFile");
}
public void surfaceCreated(SurfaceHolder holder) {
if (this.mPlayer == null) {
this.mPlayer = new MediaPlayer();
} else {
this.mPlayer.reset();
mPlayer.start();
}
try {
this.mMediaPlayer.setDataSource(mStringFilePath);
this.mPlayer.setDisplay(this.mSurfaceHolder);
this.mPlayer.prepare();
this.mPlayer.start();
this.mPlayer.pause();
Play();
} catch (Exception e) {
LogUtil.e(e, "Error in PlayVideoAct.surfaceCreate(SurfaceHolder)");
}
}
private void Play() {
mMediaPlayer.start();
if (this.mMediaPlayer.isPlaying()) {
this.mMediaPlayer.pause();
return;
}
if (this.isStop) {
this.mMediaPlayer.seekTo(this.leftPosition);
}
this.mImageViewButtonControls.setImageResource(R.drawable.pause);
}
Check video path, if it's correct then check if you have all necessary permissions like:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
If yes, then depending on your Android version you may need to go to Settings -> Apps -> Your application -> Permissions and toggle those permissions manually.

How do I set the Camera Intent as the Main Activity

I want to launch the camera once a user opens up my application.
Right now I have this, and it works fine. When the user launches my application, it automatically opens up the camera. However, then the user hits the "back" button after taking an image, it opens up a blank activity.
How do I get it to go back to the camera?
public class MainActivity extends AppCompatActivity {
private static final int REQUEST_TAKE_PHOTO = 0;
// The URI of photo taken with camera
private Uri mUriPhotoTaken;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
takePhoto();
}
// Deal with the result of selection of the photos and faces.
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
Uri imageUri;
if (data == null || data.getData() == null) {
imageUri = mUriPhotoTaken;
} else {
imageUri = data.getData();
}
Intent intent = new Intent(MainActivity.this, Result.class);
intent.setData(imageUri);
startActivity(intent);
}
}
// Launch the camera to allow the user to take a photo
public void takePhoto(){
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if(intent.resolveActivity(getPackageManager()) != null) {
// Save the photo taken to a temporary file.
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
try {
File file = File.createTempFile("IMG_", ".jpg", storageDir);
mUriPhotoTaken = Uri.fromFile(file);
intent.putExtra(MediaStore.EXTRA_OUTPUT, mUriPhotoTaken);
startActivityForResult(intent, REQUEST_TAKE_PHOTO);
} catch (IOException e) {
Log.d("ERROR", e.getMessage());
}
}
}
}
Try to call takePhoto() method in the onStart() instead of onCreate() and then call the finish() method into the onStop().
Try it.
#Override
public void onBackPressed() {
super.onBackPressed();
Intent intent = new Intent(this, ActivityYouWantToOpen.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
finish();
}

android Media Player stream more than 1 URL

I'm using mediaPlayer in my Android application to stream an MP3 url from online. Instead of just playing the 1 url, how can I stream 5 urls to play one after the other? here's my code
Uri myUri = Uri.parse("https://db.tt/9nBgouRf");
final MediaPlayer sdrPlayer = new MediaPlayer();
try {
sdrPlayer.setDataSource(this, myUri);
sdrPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
sdrPlayer.prepare(); //don't use prepareAsync for mp3 playback
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(channelx.this,
"Please turn on WiFi and try again", Toast.LENGTH_LONG).show();
}
play.setOnClickListener( new OnClickListener() {
#Override
public void onClick(View v) {
sdrPlayer.start();
}
}
);
Just create a List to hold all of your URIs
Set up some class variables:
private int playlistPos = 0;
private List<Uri> myUris = new ArrayList<Uri>();
private MediaPlayer sdrPlayer = new MediaPlayer();
Set up a method for initialising the song:
public initSong(Uri myUri) {
try {
sdrPlayer.setDataSource(this, myUri);
sdrPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
sdrPlayer.prepare(); // don't use prepareAsync for mp3 playback
}
catch (IOException e) {
e.printStackTrace();
Toast.makeText(channelx.this,
"Please turn on WiFi and try again",
Toast.LENGTH_LONG).show();
}
}
Then in the onCreate()
myUris.add(Uri.parse("https://db.tt/9nBgouRf"));
// Add the others as well...
initSong(myUris.get(playlistPos);
sdrPlayer.setOnCompletionListener(new OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
playlistPos++;
initSong(myUris.get(playlistPos));
sdrPlayer.start(); // Start it as well if you wish
}
});
play.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
sdrPlayer.start();
}
});

Categories

Resources