I'm trying to play YouTube video in Video-view Android. It is giving can't play this video. What I have tried is like below..
MainActivity.java
public class MainActivity extends AppCompatActivity {
// Widgets
private VideoView vv_youtube;
// Variables
private String base_url = "https://www.youtube.com/watch?v=K8lppDEOkcM";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
vv_youtube = (VideoView) findViewById(R.id.vv_youtube);
Uri video = Uri.parse(base_url);
MediaController mediaController = new MediaController(this);
mediaController.setAnchorView(vv_youtube);
vv_youtube.requestFocus();
vv_youtube.setMediaController(mediaController);
vv_youtube.setVideoURI(video);
vv_youtube.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer arg0) {
vv_youtube.start();
}
});
vv_youtube.setOnErrorListener(new MediaPlayer.OnErrorListener() {
#Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Log.e("Error is: ", String.valueOf(extra));
return false;
}
});
vv_youtube.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
Log.e("Complete is: ", mp.toString());
}
});
}
}
LogCat
11-19 02:21:45.741 21929-21961/com.example.inbridge08.videoviewyoutube I/OpenGLRenderer: Initialized EGL, version 1.4 11-19 02:21:45.772 21929-21961/com.example.inbridge08.videoviewyoutube D/OpenGLRenderer: Enabling debug mode 0 11-19 02:21:45.799 21929-21961/com.example.inbridge08.videoviewyoutube W/EGL_emulation: eglSurfaceAttrib not implemented 11-19 02:21:45.799 21929-21961/com.example.inbridge08.videoviewyoutube W/OpenGLRenderer: Failed to set EGL_SWAP_BEHAVIOR on surface 0xe2b19220, error=EGL_SUCCESS 11-19 02:21:45.898 21929-21929/com.example.inbridge08.videoviewyoutube D/MediaPlayer: Couldn't open file on client side, trying server side 11-19 02:21:46.421 21929-21947/com.example.inbridge08.videoviewyoutube E/MediaPlayer: error (1, -2147483648) 11-19 02:21:46.421 21929-21929/com.example.inbridge08.videoviewyoutube E/MediaPlayer: Error (1,-2147483648) 11-19 02:21:46.421 21929-21929/com.example.inbridge08.videoviewyoutube D/VideoView: Error: 1,-2147483648 11-19 02:21:46.421 21929-21929/com.example.inbridge08.videoviewyoutube E/Error is:: -2147483648
[ 11-19 02:21:46.513 82: 82 D/] Socket deconnection
I searched on google for two days and I reached on decision that I have to use YouTube Android Player API to play YouTube videos in Video-view. If I replace URL with other(Not YouTube video URL) It is working fine.
I tried on both Emulator and device. Not working on both.
Thanks in Advance!
Try using the MediaPlayer class for using playing videos in VideoView. Here's a snippet taken from Using MediaPlayer guide to play videos from URIs:
Playing from a remote URL via HTTP streaming looks like this:
String url = "http://........"; // your URL here
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setDataSource(url);
mediaPlayer.prepare(); // might take long! (for buffering, etc)
mediaPlayer.start();
Note: If you're passing a URL to stream an online media file, the file
must be capable of progressive download.
You may also check this SO thread for additional reference.
Related
I am working on a music player in react native and have been using the package react-native-track-player. I have so far not had a problem with the package in android. but when I try to run it on ios I get the error
You attempted to set the key0with the value
{"id":"0",
"url":{"uri":"https://urltosong.mp3"},
"artwork":"https://url_to_artwork.jpg",
"artist":"author",
"title":"song titile"
}
on an object that is meant to be immutable and has been frozen.
The code that generate the error is
async function togglePlayback() {
const currentTrack = await TrackPlayer.getCurrentTrack();
if (currentTrack == null) {
await TrackPlayer.reset();
await TrackPlayer.add(playlist); //this was never adding and die silently
await TrackPlayer.play();
} else {
await TrackPlayer.add(playlist); //adding this line the error above appeared
await TrackPlayer.play();
//console.warn(TrackPlayer.getCurrentTrack())
}
}
I am using this version of the package "react-native-track-player": "^2.0.0-rc13",
I don't know if there is something I am missing. I will appreciate your help in fixing this.
Change your track to this:
{"id":"0",
"url":"https://urltosong.mp3",
"artwork":"https://url_to_artwork.jpg",
"artist":"author",
"title":"song titile"
}
Urls should be either a string or a Resource Object
I'm trying to incorporate video and audio file attachment to forum posts in an app, and the playback isn't working on iOS. On Android it works fine. The code looks like this (for audio, and similar for video):
String localAudiofilePath = FileSystemStorage.getInstance().getAppHomePath() + (String) fileInfo.get("path");
InputStream is = null;
Media m = null;
try{
is = FileSystemStorage.getInstance().openInputStream(localAudiofilePath);
m = MediaManager.createMedia(is, "audio/" + extractFileExtension((String) fileInfo.get("path")));
}catch(Exception ex){
ex.printStackTrace();
}
m.play();
final Media mm = m;
Display.getInstance().scheduleBackgroundTask(new Runnable() {
#Override
public void run() {
while(mm.isPlaying()){
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
}
}
mm.cleanup();
}
});
I don't see any errors in the console, and when debugging I see the catch block is not entered. However, no sound comes out of the device when I try to play the audio, and the video player remains blank, giving me this message in the console:
2018-01-18 04:22:20.213822 MyApplication[24425:2262915] [Playback] ❗️Playback failed with error: Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo={NSUnderlyingError=0x61000024c2d0 {Error Domain=NSOSStatusErrorDomain Code=-12893 "(null)"}, NSLocalizedFailureReason=An unknown error occurred (-12893), NSLocalizedDescription=The operation could not be completed}, not resolving (canResolve: YES, errorResolver: (null))
What am I missing?
You are using the audio recording mime type to playback a video. I guess Android ignores it which is fine. The iOS port sees an audio format for the stream data and assumes this is an audio file. You need to specify the mime file type of the video you are playing.
The problem was not at all media playback. The file wasn't actually present on the device, even though no exception was reported by iOS nor was the catch clause ever entered. My incorrect assumptions were 1. that I could use try/catch around the input stream instantiation as a means of checking if the file exists (it worked on Android but not iOS), and 2. that the operating system would necessarily throw an exception if the file wasn't present (not the same as 1., but tied into it).
My new, working code looks like this:
String localAudiofilePath = FileSystemStorage.getInstance().getAppHomePath() + MyApplication.DIRECTORY_APP_DOWNLOADS + "/" + (String) fileInfo.get("path");
if(!FileSystemStorage.getInstance().exists(localAudiofilePath)){
Cn1FileUtils.downloadRemoteFile("https://medonline.co.il/uploads/" + (String) fileInfo.get("path"), (String) fileInfo.get("path"), true);
}
InputStream is = null;
media = null;
try{
is = FileSystemStorage.getInstance().openInputStream(localAudiofilePath);
media = MediaManager.createMedia(is, "audio/" + Cn1FileUtils.extractFileExtension((String) fileInfo.get("path")));
}catch(Exception ex){
ex.printStackTrace();
ToastBar.showErrorMessage(MyApplication.getInstance().getString("error_loading_file"));
return;
}
media.play();
I have an Ionic 2 app that works fine on Android.
Now I need to build the IOS version. The app can stream and download audios from SoundCloud.
When the users click to download an audio, the audio is stored in the app's data directory provided by Cordova file plugin.
The logic I use to store and retrieve data does not matter because in Android it works. The problem is that I want to recover and play the audio in IOS.
This is the part of code where I create a MediaObject and later play, pause it:
var pathalone: string = '';
if (this.platform.is('ios')) {
pathalone = this.audio.filePath.replace(/^file:\/\//, '');
console.log("Pathalone: " + pathalone);
this.mediaPlayer = this.media.create(pathalone, onStatusUpdate, onSuccess, onError);
} else {
pathalone = this.audio.filePath.substring(8);
this.mediaPlayer = this.media.create(pathalone, onStatusUpdate, onSuccess, onError);
}
setTimeout(() => {
if (this.mediaPlayer) {
this.togglePlayPause();
this.updateTrackTime();
}
}, 1000);
In the Media plugin docs says if still having problems on IOS, first create the file. So I tried, but I still having the same problem:
this.file.createFile(cordova.file.dataDirectory, this.audio.fileName, true).then(() => {
pathalone = this.audio.filePath.replace(/^file:\/\//, '');
console.log("Pathalone: " + pathalone);
this.mediaPlayer = this.media.create(pathalone, onStatusUpdate, onSuccess, onError);
});
In console I get these logs:
console.log: Pathalone:
/Users/ivan/Library/Developer/CoreSimulator/Devices/0D75C1A9-591A-4112-BBE4-AB901953A38F/data/Containers/Data/Application/509D1136-86F6-4C9B-84B5-8E0D0D203DAC/Library/NoCloud/311409823.mp3
[14:07:48] console.log: Cannot use audio file from resource
'/Users/ivan/Library/Developer/CoreSimulator/Devices/0D75C1A9-591A-4112-BBE4-AB901953A38F/data/Containers/Data/Application/509D1136-86F6-4C9B-84B5-8E0D0D203DAC/Library/NoCloud/311409823.mp3'
Maybe It's happening on Emulator but will not happen on a real device? I can't test on iPhone because I haven't got one :/
PD:
A curious fact is that the SoundCloud api returns a redirect when making a GET to its api to download an audio.
The response has a status of 301, so I use the response.headers.Location to handle the redirect and there, I can perform the download.
And I'm noticing that in IOS it never performs the redirect, it goes directly on the 'positive' way and the console says 'downloaded'. Maybe it's never really downloaded...
You need indeed to create a file before creating the recorder media object. Recordings are possible even with the emulator on iOS and Android. The following illustrate how this is done with Ionic2+
First you need to import the following
import { NavController, Platform } from 'ionic-angular';
import { Media, MediaObject } from '#ionic-native/media';
import { File } from '#ionic-native/file';
Make sure that you injected the imports in your constructor as follows
constructor(public navCtrl: NavController, private media: Media, private file: File, public platform: Platform) {
// some more code here
}
Declare the required variables before the constructor as follows
filePath: string;
fileName: string;
audio: MediaObject;
The code for starting the recording in as follows
startRecord() {
if (this.platform.is('ios')) {
this.fileName = 'record' + new Date().getDate() + new Date().getMonth() + new Date().getFullYear() + new Date().getHours() + new Date().getMinutes() + new Date().getSeconds() + '.3gp';
this.filePath = this.file.dataDirectory;
this.file.createFile(this.filePath, this.fileName, true).then(() => {
this.audio = this.media.create(this.filePath.replace(/^file:\/\//, '') + this.fileName);
this.audio.startRecord();
});
} else if (this.platform.is('android')) {
this.fileName = 'record' + new Date().getDate() + new Date().getMonth() + new Date().getFullYear() + new Date().getHours() + new Date().getMinutes() + new Date().getSeconds() + '.3gp';
this.filePath = this.file.externalDataDirectory;
this.file.createFile(this.filePath, this.fileName, true).then(() => {
this.audio = this.media.create(this.filePath.replace(/^file:\/\//, '') + this.fileName);
this.audio.startRecord();
});
}
}
Notice the differences between using the path name "this.filePath" in createFile and media.create.
The code for stopping the recording is as follows
stopRecord() {
this.audio.stopRecord();
}
So, my problem is that I'm trying to stream audio on Xamarin.iOS with the AudioFileStream and OutputAudioQueue classes. I have added handlers for the PacketDecoded and PropertyFound events, but they are not being triggered. What's wrong? My code is below...
class AudioStreamer : IAudioStreamer // this is my dependency service interface
{
bool outputStarted;
AudioFileStream afs;
OutputAudioQueue oaq;
public void StartStreaming(string url)
{
afs = new AudioFileStream(AudioFileType.MP3);
// event handlers, these are never triggered
afs.PacketDecoded += OnPacketDecoded;
afs.PropertyFound += OnPropertyFound;
GetAudio(url);
}
void GetAudio(string url)
{
// HTTP
NSUrlSession session = NSUrlSession.FromConfiguration(
NSUrlSessionConfiguration.DefaultSessionConfiguration,
new SessionDelegate(afs),
NSOperationQueue.MainQueue);
var dataTask = session.CreateDataTask(new NSUrl(url));
dataTask.Resume();
}
// event handler - never executed
void OnPropertyFound(object sender, PropertyFoundEventArgs e)
{
if(e.Property == AudioFileStreamProperty.ReadyToProducePackets)
{
oaq = new OutputAudioQueue(afs.StreamBasicDescription);
oaq.BufferCompleted += OnBufferCompleted;
}
}
// another event handler never executed
void OnPacketDecoded(object sender, PacketReceivedEventArgs e)
{
IntPtr outBuffer;
oaq.AllocateBuffer(e.Bytes, out outBuffer);
AudioQueue.FillAudioData(outBuffer, 0, e.InputData, 0, e.Bytes);
oaq.EnqueueBuffer(outBuffer, e.Bytes, e.PacketDescriptions);
// start playing if not already
if(!outputStarted)
{
var status = oaq.Start();
if (status != AudioQueueStatus.Ok)
System.Diagnostics.Debug.WriteLine("Could not start audio queue");
outputStarted = true;
}
}
void OnBufferCompleted(object sender, BufferCompletedEventArgs e)
{
oaq.FreeBuffer(e.IntPtrBuffer);
}
}
// instantiated in GetAudio()
class SessionDelegate : NSUrlSessionDataDelegate
{
readonly AudioFileStream afs;
public SessionDelegate(AudioFileStream afs)
{
this.afs = afs;
}
// this is, too, never executed
public override void DidReceiveData(NSUrlSession session, NSUrlSessionDataTask dataTask, NSData data)
{
afs.ParseBytes((int)data.Length, data.Bytes, false);
}
}
Btw, I mostly copied the code from this screencast.
Your code looks correct...
1) I see the "http://" comment in your source. Are your streaming from a http:// source without adding an ATS exception? If so, the dataTask.Resume(); is a "silent code failure" and thus none of your delegates/events will be called, BUT iOS will log it.
Check output log for something like:
StreamingAudio[13602:591658] App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can be configured via your app's Info.plist file.
Use https:// sources, but if you have to turn ATS off completely for testing:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key><true/>
</dict>
Note: Search iOS ATS for more info or details in order to only allow non-secure http:// from the server(s) that you would be streaming from, but the iOS' future is https:// only so start preparing... ;-)
2) If the URL source provided to NSUrlSession produces a Connection refused, that is a silent failure, AND there is no logging about it and of course none of your delegates/events are called... Pre-test that your streaming web services are active, try using curl, wget, etc.. to test the stream...
3) I see your streaming MP3s, so you should be OK, but remember there are hundreds of variations to the format and iOS does not stream/play them all so try a different mp3 encoded via a different toolset just to double-check...
I have done a lot of searching online and I'm not sure what I'm doing wrong. The idea is that I want to launch my iOS app with the following location in a simulator. This works fine when I manually go to debug>location>custom location and set the longitude and latitude....however I need to do it programatically so that my app launches /picks up this location when I click enable locations. Here is my code
public class SampleTest extends SampleBaseTest {
private IOSDriver driver;
private String sessionId;
static UserData sampleUser = null;
#Test(priority = 0)
public void setUp() throws MalformedURLException {
DesiredCapabilities caps = DesiredCapabilities.iphone();
caps.setCapability("appiumVersion", "1.4.16");
caps.setCapability("deviceName","iPhone 6");
caps.setCapability("deviceOrientation", "portrait");
caps.setCapability("platformVersion","9.1");
caps.setCapability("platformName", "iOS");
caps.setCapability("browserName", "");
caps.setCapability("app","sauce-storage:sampleAppe.zip");
URL sauceUrl = new URL("http://" + "sauceUserName" + ":"+ "sauceUserKey" + "#ondemand.saucelabs.com:80/wd/hub");
driver = new IOSDriver(sauceUrl, caps);
Location location = new Location(-8.78319, -114.509, 0.0);
driver.setLocation(location);
sessionId = driver.getSessionId().toString();
#Test(priority = 1)
public void navigateToPayAhead()
throws Exception {
try{
// test logic here
}
catch(Exception e){
e.printStackTrace();
}
}
}
}
Unfortunately, there is a current issue with setting a location on the Sauce iOS simulators. From a support ticket on a similar issue, I was told that it is a known issue, and that it will be addressed (at some point).
I can verify that setting a location does work when using the Android emulators via Sauce Labs.
So, I guess the good news is that you aren't doing anything wrong!
Try adding
caps.setCapability("locationServicesEnabled", true);
caps.setCapability("locationServicesAuthorized", true);
caps.setCapability("bundleId", "YOUR_BUNDLE_ID_HERE");
To get your bundle id, see How to obtain Bundle ID for an IOS App when I have a '.ipa' file for the app installed on my iPAD