I'm using this nu-get package to stream mp3 url in a Xamarin Android project:
https://github.com/martijn00/XamarinMediaManager
I followed the instructions in the link up there... and it shows the music playing in the notification bar but it is not working (no sound and it's not even starting the song).
Code snippet:
clickButton.Click += (sender, args) =>
{
ClickButtonEvent();
};
private static async void ClickButtonEvent()
{
await CrossMediaManager.Current.Play("http://www.montemagno.com/sample.mp3");
}
I built the sample included in the link, and I got the same result from their sample. Also deployed on real device too, same result!
Image:
Am I missing something ?
Or is the library broken ?
I ran into this using Android Emulator on Hyper-v. It turns out that the network is set to internal. So the http://www.montemagno.com/sample.mp3 could not be found. My workaround:
Hyper-v -> Virtual Switch Manager, add an external network.
Hyper-v -> Virtual Machines->Settings, add new hardware->Network adapter and set to external network.
"Visual Studio Emulator for Android" desktop app, launch phone vm,
in Visual Studio, deploy and run app.
Sound should work from external source now.
Permissions maybe? In the project site it states that for Android:
You must request AccessWifiState, Internet, MediaContentControl and
WakeLock permissions
By default example use ExoPlayerAudioService.
There are issue with url escape in ExoPlayerAudioService.GetSource method
private IMediaSource GetSource(string url)
{
string escapedUrl = Uri.EscapeDataString(url);
var uri = Android.Net.Uri.Parse(escapedUrl);
var factory = URLUtil.IsHttpUrl(escapedUrl) || URLUtil.IsHttpsUrl(escapedUrl) ? GetHttpFactory() : new FileDataSourceFactory();
var extractorFactory = new DefaultExtractorsFactory();
return new ExtractorMediaSource(uri
, factory
, extractorFactory, null, this);
}
string escapedUrl = Uri.EscapeDataString(url);
I.E. http://example.com/path_to_audio.mp3 will be escaped to "http%3A%2F%2Fexample.com%2Fpath_to_audio.mp3" as result HTTP error.
To fix just skip url escape.
Related
I am testing a website on Chrome (v65) installed on Android (7.1.1 API 25).
Chromedriver version 2.37.
Appium latest desktop version (v1.5.0, shows server version 1.7.2)
I need to upload an image from the device itself.
Although on the web-browser I am able to upload an image with sendKeys, its not working on the android emulator.
This is what the image selection page in the emulator looks like:
I used UiAutomator to get the resource id: "com.android.chrome:id/bitmap_view" and the class: "android.widget.ImageView"
I have used the following line(s) of code to try and look for the element:
(a)
driver.findElement(By.xpath("//android.widget.ImageView[contains(#resource-id,'com.android.chrome:id/bitmap_view')]")).click();
(b) When I use below, I get an empty list
List<WebElement> elements = driver.findElementsByClassName("android.widget.ImageView");
(c) I got this xpath from Appium Inspector Session
MobileElement el8 = (MobileElement) driver.findElementByXPath("/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.support.v7.widget.Af/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.RelativeLayout/android.widget.FrameLayout/android.support.v7.widget.RecyclerView/android.widget.FrameLayout[3]/android.widget.FrameLayout/android.widget.ImageView");
el8.click();
I don't know what I am missing.
[Update] []2
Did you change the context to the NATIVE_APP in your test?
Since you mentioned you test chrome, it means your test is using WEBVIEW context. But as soon as you open Upload files screen it is a NATIVE_APP view and you need to switch to it before start searching:
AndroidDriver<MobileElement> driver = new AndroidDriver<>(
new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
driver.get(<your_web_site>);
// do what you need in browser, open Upload files screen
// switch to Native context to search inside it
Set<String> contexts = driver.getContextHandles();
for (String context : contexts) {
System.out.println(contexts);
if (context.equals("NATIVE_APP")) {
driver.context(context);
break;
}
}
List<MobileElement> images = driver.findElementsByClassName("android.widget.ImageView");
// click the last image in view if exist
images.stream()
.reduce((first, second) -> second)
.orElseThrow(NotFoundException::new)
.click();
i have tried running cordova media plugin in both kitkat and lollipop but it shows no response.
Not even the 3rd parameter for error's function is running.
I have also read almost every article or question about this problem and tried every way i could but nothing worked.
All i finally concluded was that this plugin is not fully supported in android versions above 4.1
I have tried:
<script>
document.body.onload="ready()";
function ready()
{
document.addEventListener("deviceready",function() {
var src;
// src's value
var med=new Media(src,
function() {
alert("success");
},
function(e)
{
alert("failed code: "+e);
});
med.play();
med.release();},false);
}
</script>
here is what i have tried replacing with //src's value
src = 'cdvfile://audio.mp3';
src = 'file:///android_asset/www/audio.mp3';
src = "cdvfile:///android_asset/www/audio.mp3";
src = "audio.mp3";
even after that stupid conclusion i wrote about up there, i still am doubtful that how it still runs on some devices with same os. So, any ideas of making audio files play in cordova app?
MORE INFO:
1>My project structure
appName
|___www
|___[+]css
|___[+]js
|___index.html
|___[+]img
|___audio.mp3
2>I am targeting 6.3.0 marshmallow 😋
Media definitely works for me on marshmallow - albeit I use wav files rather than mp3. I use
audioFail = loadAudio('sounds/no.wav'); where the file is stored in www/sounds
The media constructor is asynchronous but your code uses med immediately after issuing the call to the constructor - have you confirmed that med exists and is defined before you try to call med.play()?
I am trying to exchange files between a .Net Desktop App and a Xamarin.Forms Android app. I really had trouble getting resources and help, so I want this question to also wrap some stuff up - for other interested users (not only of Xamarin Forms)
So far I got to read files and folders in .Net C# using
Christophe Geers' Blog and Fun with MTP and because writing did not work on all of my devices Windows File Stuff by Flauschig
On Xamarin.Forms side of the wall I first stumbled over Xamarin doc and A lib to store from pcl code and also Plugin.Permissions.
With all these sources above I was able to get reading and writing on the Android (Samsung A5, Android 6.0) to work.
With this description on filestructure I thought the following Code will always get a valid path:
public string GetExternalFolder()
{
GetPermission();
var externalFolder = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.Path, "Android", "data", "com.exampledom.appname", "files");
if (!Directory.Exists(externalFolder))
CreateFolderStructure();
return externalFolder;
}
GetPermission() is taken from Plugin.Permissions and will throw exception if permission is not given.
CreateFolderStructure() is using pcl.storage - and looks like this.
private async void CreateFolderStructure()
{
try
{
IFolder rootFolder = await FileSystem.Current.GetFolderFromPathAsync(Path.Combine(Android.OS.Environment.ExternalStorageDirectory.Path));
var subpaths = new[] {"Android", "data", "com.exampledom.appname", "files"};
foreach (var dir in subpaths)
{
if (!string.IsNullOrEmpty(dir))
rootFolder = await rootFolder.CreateFolderAsync(dir, CreationCollisionOption.OpenIfExists);
}
Log("Folder structure created!");
}
catch (Exception e)
{
Log("Folder structure cannot be created!");
Console.WriteLine("Failed to log! " + e.Message);
}
}
Ok, now for the question:
The Folder that is created by this Method is only created on one device I tested on (proof of concept) - all others (eg Samsung A3, Android 6.0) nothing happens(proof of helpless developer). A reboot is not the solution.
Also on the device this works on - the permission is requested as expected. There is no permission request on the other devices.
Why is the desired folder not created during install? It seems all other apps do have such a folder 'Android/data/com.exampledom.appname/files'.
What am I missing? It seems overly hard to import/export to android.
#smack Does CreationCollisionOptions.OpenIfExists really create a folder? I don't think so. Is there not CreateIfNotExists enum?
I try to open a website in chrome and native android browser (emulated Android 5.0 and 6) to check several items.
every time i run the test, the choosen browser get started and in the url field stays 'data:,' btw the actual tab is also loaded two times.
I know there is a way to do this with selenium webdriver, but this is not the right way for me because i used the followed code for several emulated devices to test this website and on iOS/Mac osx its working.
So why not on android. My way to test this website is with capybara, appium and ruby.
on iOS there exists a
:safariInitialUrl =>'http://www.mypage.com'
cap.
but not for android.
So, my question is: how is it possible to start my website on an emulated android devices without using selenium webdriver.
code:
Capybara.register_driver :androidphone do |app|
capabilities = {
:deviceName => 'nex5_5',
:avd => 'nex5_5',
:browserName => 'Chrome',
:platformVersion => '5.0',
:platformName => 'Android',
:automationName => 'Appium',
}
url = "http://localhost:4723/wd/hub"
appium_lib_options = {
server_url: url
}
all_options = {
appium_lib: appium_lib_options,
caps: capabilities,
}
Appium::Capybara::Driver.new app, all_options
You have to add this line in your config file :
exports.config = {
directConnect:false,
}
I think you have also to add the Timeout in your configuration file, if you are using jasmine framework for example add this code :
jasmineNodeOpts: {
defaultTimeoutInterval: 30000
}
Is there a way to open one app from another app in Air? Example: I open app A which contains a button that opens app B when clicked. Suppose both A and B are separated apps that are installed in the device and that this device could be a PlayBook, an Ipad or an Android tablet.
Thanks.
You'd have to go the Air Native Extension(ANE) route. Either create one ANE solution for iOS and Android each, or one ANE that abtracts the functionality into one solution. How to launch app A from app B on Android is not the same as on iOS. See this answer in SO.
To implement it on Android, you'd wraps the native Android Java solution in a ANE. The native Java code uses the package name of app B to launch app B from app A:
Intent intent = getPackageManager().getLaunchIntentForPackage("com.yourdoman.yourapp");
startActivity(intent);
Here is a video tutorial on how to launch an Activity through an ANE which you can build on to create your ANE. You'd have to tailor the solution to launch by domain instead of Activity.
Since I really don't know the specifics of what you are trying to do, I think I should point you here: http://www.riaspace.com/2011/08/defining-custom-url-schemes-for-your-air-mobile-applications/ It is the best answer to the question that I am aware of.
private function getHostName() : void
{
if (NativeProcess.isSupported)
{
var OS : String = Capabilities.os.toLocaleLowerCase();
var file : File;
if (OS.indexOf('win') > -1)
{
// Executable in windows
file = new File('C:\\Windows\\System32\\hostname.exe');
}
else if (OS.indexOf('mac') > -1 )
{
// Executable in mac
}
else if (OS.indexOf('linux'))
{
// Executable in linux
}
var nativeProcessStartupInfo : NativeProcessStartupInfo = new NativeProcessStartupInfo();
nativeProcessStartupInfo.executable = file;
var process : NativeProcess = new NativeProcess();
process.addEventListener(NativeProcessExitEvent.EXIT, onExitError);
process.addEventListener(ProgressEvent.STANDARD_OUTPUT_DATA, onOutput);
process.start(nativeProcessStartupInfo);
process.closeInput();
}
}
private function onOutput(event : ProgressEvent) : void
{
var strHelper : StringHelper = new StringHelper();
formStationID.text = event.target.standardOutput.readUTFBytes(event.target.standardOutput.bytesAvailable);
formStationID.text = strHelper.trimBack(formStationID.text, "\n");
formStationID.text = strHelper.trimBack(formStationID.text, "\r");
}
This code gets the workstation name. I have heard this can be done on IOS and Android, but I haven't found any proof of that yet.