HTML5 Audio: Native Controls not showing up on Android (Ionic Capacitor) - ionic-framework

I'm using HTML5 Audio in my Capacitor App to play music. On iOS, the native Audio controls are showing up, like you see in this screenshot.
Sadly, it doesn't show up on Android. Surprisingly, it shows up if I open my Ionic/Capacitor App in the browser and press play. See the Web-App: https://audio-player-sigma.vercel.app
This is my Code:
const player = new Audio();
player.src = 'https://file-examples-com.github.io/uploads/2017/11/file_example_MP3_2MG.mp3';
player.onplay = () => {
if ('mediaSession' in navigator) {
navigator.mediaSession.metadata = new MediaMetadata({
title: 'Lorem Ipsum',
artist: 'Lorem Ipsum',
album: 'Lorem Ipsum',
artwork: [
{ src: 'https://dummyimage.com/96x96', sizes: '96x96', type: 'image/png' },
{ src: 'https://dummyimage.com/128x128', sizes: '128x128', type: 'image/png' },
{ src: 'https://dummyimage.com/192x192', sizes: '192x192', type: 'image/png' },
{ src: 'https://dummyimage.com/256x256', sizes: '256x256', type: 'image/png' },
{ src: 'https://dummyimage.com/384x384', sizes: '384x384', type: 'image/png' },
{ src: 'https://dummyimage.com/512x512', sizes: '512x512', type: 'image/png' },
]
});
console.log('init mediaSession metadata');
} else {
console.log('mediaSession not available');
}
};
So it works in the system browser, but not in .apk built by capacitor. On the iOS App aren't any problems. Everything works fine.
Github repository: https://github.com/mariusbolik/capacitor-audio-player
Any ideas how to get it working on the android capacitor project?
Thanks!

Related

Smart Home Device showing small cog and no commands

I have a node.js script in AWS Lambda which is connected to my Project via API Gateway.
I've got the actions-on-google library included OK and my devices get discovered. However, depending on what I select as the device type, affects whether in Google Home the device shows with a little cog on the icon (and no commands available).
The below works absolutely fine and I can see the device and commands available:
app.onSync(async (body, headers) => {
return {
requestId: body.requestId,
payload: {
agentUserId: '123',
devices: [{
id: 'washer-123',
type: 'action.devices.types.OUTLET',
traits: [
'action.devices.traits.OnOff',
'action.devices.traits.StartStop',
'action.devices.traits.RunCycle'
],
name: {
defaultNames: ['My Washer'],
name: 'Washer',
nicknames: ['Washer']
},
deviceInfo: {
manufacturer: 'Acme Co',
model: 'acme-washer',
hwVersion: '1.0',
swVersion: '1.0.1'
},
attributes: {
pausable: true
}
}]
},
}
});
However, exactly the same but with the type changed to Door fails and all I can see in Google Home is the app settings:
app.onSync(async (body, headers) => {
return {
requestId: body.requestId,
payload: {
agentUserId: '123',
devices: [{
id: 'washer-123',
type: 'action.devices.types.DOOR',
traits: [
'action.devices.traits.OnOff',
'action.devices.traits.StartStop',
'action.devices.traits.RunCycle'
],
name: {
defaultNames: ['My Washer'],
name: 'Washer',
nicknames: ['Washer']
},
deviceInfo: {
manufacturer: 'Acme Co',
model: 'acme-washer',
hwVersion: '1.0',
swVersion: '1.0.1'
},
attributes: {
pausable: true
}
}]
},
}
});
Is there anything specific about the DOOR device type compared to the OUTLET type that might be causing this to fail?
Touch controls are supported for OUTLET, but not for DOOR.

Pick camera roll not working in ionic/cordova in iOs nothing happens

Nothing happens when I call the getPicture function with: this.camera.PictureSourceType.PHOTOLIBRARY.
Hower it does work in Android just not iOs and also this.camera.PictureSourceType.CAMERA does work in iOs.
private cameraOptions: CameraOptions = {
quality: 50,
destinationType: this.camera.DestinationType.DATA_URL,
encodingType: this.camera.EncodingType.JPEG,
mediaType: this.camera.MediaType.PICTURE,
};
public async changeProfilePicture() {
const sheet = await this.actionSheet.create({
buttons: [{
text: 'Camera',
handler: () => {
this.takePicture();
},
},
{
text: 'Foto album',
handler: () => {
this.choosePicture();
},
}
, {
text: 'Annuleren',
role: 'cancel',
handler: () => {
sheet.dismiss();
},
}],
});
sheet.present();
}
private async takePicture() {
try {
const image = await this.camera.getPicture({
...this.cameraOptions,
sourceType: this.camera.PictureSourceType.CAMERA,
});
this.userService.editProfilePicture(`data:image/jpeg;base64,${image}`).subscribe(user => {
this.user = user;
});
} catch (err) {
this.handleImageError(err);
}
}
private async choosePicture() {
try {
const image = await this.camera.getPicture({
...this.cameraOptions,
sourceType: this.camera.PictureSourceType.PHOTOLIBRARY,
});
this.userService.editProfilePicture(`data:image/jpeg;base64,${image}`).subscribe(user => {
this.user = user;
});
} catch (err) {
this.handleImageError(err);
}
}
iOS requires permissions to be configured when accessing certain native features. In your case, you need to set the NSPhotoLibraryUsageDescription key in the Info.plist file of your app. You can manually edit this file within the xcode project, but it's better to place this in the config.xml of your ionic project :
<config-file parent="NSPhotoLibraryUsageDescription" platform="ios" target="*-Info.plist">
<string>The app needs access to your library to...</string>
</config-file>

Ionic V4: ion-modal just like ion-alert

The following ion-alert would be exactly what we need if the input was replaced with a textarea; however, ion-alert doesn't support ion-textarea.
How can the exact same look and feel be implemented with an ion-modal?
We are using Ionic without Angular (Ionic core).
ion-alert code
const alert = await alertController.create({
header: 'Would you be willing to leave feedback?',
inputs: [
{
placeholder: 'enter text'
}],
buttons: [
{
text: 'Cancel',
role: 'cancel',
cssClass: 'secondary',
handler: _ => {
alert.dismiss();
console.log('cancel');
}
}, {
text: 'Submit',
handler: _ => {
alert.dismiss();
console.log('submit');
}
}
]
});
alert.present();
attempted ion-modal code
const modalController = $('ion-modal-controller')[0];
await modalController.componentOnReady();
const modalElement = await modalController.create({
showBackdrop: true,
component:
$(`<div>
<h2>Would you be willing to provide feedback?</h2>
<div>
<ion-button>Cancel</ion-button>
<ion-button>Submit</ion-button>
</div>
</div>`)[0]
});
await modalElement.present();
In the page where you call the modal:
async book() {
const modal = await this.modalController.create({
component: BookModal,
componentProps: { value: 123 },
showBackdrop: true,
backdropDismiss: true,
cssClass: ['booking-modal']
});
return await modal.present();
}
The key point is the cssClass. Then in theme/variable.scss, add the class at the end of the file like below:
.booking-modal {
--height: 50% !important;
}
** Note: this might not be the correct way to do it, but it works for me at this stage. Looking for a better solution.

How to hide / disable Ionic inapp browser top address bar?

I have implemented ionic inapp browser in my app. I want to hide the top bar from it. I am trying using the below code but it does not seem to work.
page.ts code
openWebpage(url: string) {
const browser = this.inAppBrowser.create('http://sco7.com/filemanager/sapphire/','_self','toolbar=no');
const options: InAppBrowserOptions = {
zoom: 'no',
location: 'no',
toolbar: 'no'
}
}
I have added toolbar=no but still top address bar is visible.
The code you shared is the code you use to create an inAppBrowser? If so you need to declare your options const before the creation of your inAppBrowser:
openWebpage(url: string) {
const options: InAppBrowserOptions = {
zoom: 'no',
location: 'no',
toolbar: 'no'
};
const browser = this.inAppBrowser.create('http://sco7.com/filemanager/sapphire/','_self','toolbar=no');
}
Doing so i was able to open and an browser window without the URL bar.
Also using 'toolbar=no' is wrong since toolbar is one of the options property and it needs to be a string, toolbar doesn't need to be part of the string. An alternative is using simply an object with the location property:
this.inAppBrowser.create('http://sco7.com/filemanager/sapphire/','_self',{ toolbar: 'no'});
Hope this helps.
openWebpage(url: string) {
const options: InAppBrowserOptions = {
zoom: 'no',
fullscreen: "yes",
hidenavigationbuttons: "no",
toolbar:'no',
hideurlbar: 'yes',
}
// Opening a URL and returning an InAppBrowserObject
const browser = this.inAppBrowser.create(url, '_blank',{ toolbar: 'no', hideurlbar: 'yes',
fullscreen: "yes",location:"no", options});
browser.on('loadstop').subscribe(event => {
browser.insertCSS({ code: "toolbar{display: none;" });
});
// Inject scripts, css and more with browser.X
}
like this way shall appear what you wanna hidden or control!
Either you can apply InAppBrowserOptions in in-app-browser
private openBrowser(url: string, title?: string) {
let options: InAppBrowserOptions = {
toolbarcolor: "#488aff",
hideurlbar: "yes",
closebuttoncolor: "#fff",
navigationbuttoncolor: "#fff"
};
const browser = this.iab.create(url, "_blank", options);
}
or you can use the highly customizable themeable-browser which built on top of
in-app-browser
// can add options from the original InAppBrowser in a JavaScript object form (not string)
// This options object also takes additional parameters introduced by the ThemeableBrowser plugin
// This example only shows the additional parameters for ThemeableBrowser
// Note that that `image` and `imagePressed` values refer to resources that are stored in your app
const options: ThemeableBrowserOptions = {
statusbar: {
color: '#ffffffff'
},
toolbar: {
height: 44,
color: '#f0f0f0ff'
},
title: {
color: '#003264ff',
showPageTitle: true
},
backButton: {
image: 'back',
imagePressed: 'back_pressed',
align: 'left',
event: 'backPressed'
},
forwardButton: {
image: 'forward',
imagePressed: 'forward_pressed',
align: 'left',
event: 'forwardPressed'
},
closeButton: {
image: 'close',
imagePressed: 'close_pressed',
align: 'left',
event: 'closePressed'
},
customButtons: [
{
image: 'share',
imagePressed: 'share_pressed',
align: 'right',
event: 'sharePressed'
}
],
menu: {
image: 'menu',
imagePressed: 'menu_pressed',
title: 'Test',
cancel: 'Cancel',
align: 'right',
items: [
{
event: 'helloPressed',
label: 'Hello World!'
},
{
event: 'testPressed',
label: 'Test!'
}
]
},
backButtonCanClose: true
};
const browser: ThemeableBrowserObject = this.themeableBrowser.create('https://ionic.io', '_blank', options);

Sencha Touch: Problems with ext.List inside a Tabpanel?

Learning Sencha Touch, and already love it. Much better then JQTouch in my opinion. Just working on some app idea I had, and I need to have 2 tabs where the first tab will hold a ext.List with some data. I've come this far, but have one problem I can't figure out.
Problem: The detailpanel won't show when I touch a name from the list. When it wasn't in a tab panel, I had no problems at all. Tried the forums, can't find the solution.
This is my entire code (based upon many examples):
ShotjesApp = new Ext.Application({
name: "Shotjes",
launch: function() {
ShotjesApp.detailPanel = new Ext.Panel({
id: 'detailpanel',
tpl: 'Omschrijving: {Naam} <br> <br> {Inhoud}',
dockedItems: [
{
xtype: 'toolbar',
items: [{
text: 'terug',
ui: 'back',
handler: function() {
ShotjesApp.Viewport.setActiveItem('listwrapper', {type:'slide', direction:'right'});
}
}]
}
]
});
ShotjesApp.listPanel = new Ext.List({
id: 'disclosurelist',
store: ListStore,
itemTpl: '<div class="contact">{Naam} {Basis}</div>',
grouped: true,
onItemDisclosure: function(record, btn, index) {
var naam = record.data.Naam;
ShotjesApp.detailPanel.update(record.data);
ShotjesApp.Viewport.setActiveItem('detailpanel') //THIS WON'T WORK?
ShotjesApp.detailPanel.dockedItems.items[0].setTitle(naam);
}
});
ShotjesApp.listWrapper = new Ext.Panel ({
id: 'listwrapper',
layout: 'fit',
items: [ShotjesApp.listPanel],
dockedItems: [
{
dock : 'top',
xtype: 'toolbar',
title: 'Shotjes'
}],
});
this.mainView = new Ext.TabPanel({
tabBar: {
dock: 'bottom',
ui: 'dark',
layout: { pack: 'center' }
},
cardSwitchAnimation: {
type: 'fade',
cover: true
},
items:[{
title: 'Shotjes',
cls: 'card 1',
id: 'card 1',
items: [ShotjesApp.listWrapper, ShotjesApp.detailPanel] ,
iconCls: 'home',
layout: 'card',
}, {
title: 'About',
cls: 'card 2',
id: 'card 2',
html: 'about',
iconCls: 'calendar',
layout: 'card',
}
],
tabBarDock: 'bottom',
fullscreen: true,
layout: 'fit'
});
this.Viewport = this.mainView;
}
});
try this
ShotjesApp.Viewport.setActiveItem(ShotjesApp.detailPanel);
Also in your code the semicolon is missing.
Cool, thanks. I also added this, otherwise the slide would open as a new tab:
ShotjesApp.Viewport = new Ext.Panel ({
fullscreen: true,
layout: 'card',
cardSwitchAnimation: 'slide',
items: [ShotjesApp.listWrapper, ShotjesApp.detailPanel]
});
Combined with your change, it works perfectly..
One huge problem though. Because the Viewport is Fullscreen, The second tab won't show when I press it. When I set the second tab to Fullscreen: true, I see the animation, but first tab is still on top of it.
When I change fullscreen: false in the Viewport, the old problem comes back and the details pane won't show.