I am using FileChooser ionic plugin for Android and FilePicker plugin for IOS. If I use the same code to build android and IOS app, it's giving me the error that FilePicker plugin cant be added to Android.
To build app on different platforms currently, I am maintaining two different branches for iOS build and android build.
I want to maintain my code on only one branch. How can I do that?
Solutions which didn't work:
Searched for the plugin which can work on both iOS and Android but it's not available
Searched if we can add plugins under the platform in config.xml
I found no way to detect the platform and add the plugins accordingly
You can add platform specific checks and use plugins accordingly.
import { Platform } from 'ionic-angular';
import { FileChooser } from '#ionic-native/file-chooser';
import { FilePath } from '#ionic-native/file-path';
import { IOSFilePicker } from '#ionic-native/file-picker';
constructor(
private fileChooser: FileChooser,
private filePicker: IOSFilePicker,
private filePath: FilePath,
private platform: Platform) {
}
chooseFile() {
if (this.platform.is('ios')) {
this.pickFileFromIOSDevice();
}
else if (this.platform.is('android')) {
this.pickFileFromAndroidDevice();
}
}
pickFileFromIOSDevice() {
this.filePicker.pickFile()
.then(
uri => {
this.fileName = uri.substring(uri.lastIndexOf("/") + 1);
}
)
.catch(error => {
this.showError(error);
});
}
pickFileFromAndroidDevice() {
this.fileChooser.open()
.then(
uri => {
this.filePath.resolveNativePath(uri)
.then(file => {
this.fileName = file.substring(file.lastIndexOf("/") + 1);
})
.catch(err => console.log(err));
}
)
.catch(error => {
this.showError(error);
});
}
Related
I haven't found anything about HttpClient in .NET MAUI.
Does anyone know if the service:
builder.Services.AddHttpClient<IMyService, MyService>();
is possible in MAUI's startup MauiProgram.cs? And then inject HttpClient to where it's going to be used. I have tried everything and it does not seem to work. Only AddSingleton of HttpClient works for me, but it doesn't seem optimal.
PS.: I had to install nuget package Microsoft.Extensions.Http in order to use the AddHttpClient service.
UPDATES:
WORKING CODE:
MauiProgram.cs
builder.Services.AddTransient<Service<Display>, DisplayService>();
builder.Services.AddTransient<Service<Video>, VideoService>();
builder.Services.AddTransient<Service<Image>, ImageService>();
builder.Services.AddTransient<Service<Log>, LogService>();
builder.Services.AddSingleton(sp => new HttpClient() { BaseAddress = new Uri("https://api.myapi.com") });
Example of VideosViewModel.cs using a service
[INotifyPropertyChanged]
public partial class VideosViewModel
{
readonly Service<Video> videoService;
[ObservableProperty]
ObservableCollection<Video> videos;
[ObservableProperty]
bool isEmpty;
[ObservableProperty]
bool isRefreshing;
public VideosViewModel(Service<Video> videoService)
{
this.videoService = videoService;
}
[ICommand]
internal async Task LoadVideosAsync()
{
#if ANDROID || IOS || tvOS || Tizen
UserDialogs.Instance.ShowLoading("Henter videoer fra databasen...");
#endif
await Task.Delay(2000);
Videos = new();
try
{
await foreach (Video video in videoService.GetAllAsync().OrderBy(x => x.Id))
{
Videos.Add(video);
}
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
finally
{
IsRefreshing = false;
#if ANDROID || IOS || tvOS
UserDialogs.Instance.HideLoading();
#endif
if (Videos.Count is 0)
{
IsEmpty = true;
}
else
{
IsEmpty = false;
}
}
}
[ICommand]
async Task UploadVideoAsync()
{
await Shell.Current.DisplayAlert("Upload en video", "Under opbygning - kommer senere!", "OK");
}
}
NOT WORKING CODE:
MauiProgram.cs
builder.Services.AddHttpClient<Service<Display>, DisplayService>(sp => sp.BaseAddress = new Uri("https://api.myapi.com"));
builder.Services.AddHttpClient<Service<Video>, VideoService>(sp => sp.BaseAddress = new Uri("https://api.myapi.com"));
builder.Services.AddHttpClient<Service<Image>, ImageService>(sp => sp.BaseAddress = new Uri("https://api.myapi.com"));
builder.Services.AddHttpClient<Service<Log>, LogService>(sp => sp.BaseAddress = new Uri("https://api.myapi.com"));
VideosViewModel.cs
Same as above working code.
What specifically doesn't work is that I get object reference exception on OrderBy(x => x.Id), specifically highlighted x.Id in ViewModel. Removing OrderBy method gives no longer exceptions, but the view shows no data except one random empty Frame.
Do not use builder.Services.AddHttpClient in MAUI.
Use one instance.
I am trying to build a prototype Ionic app which runs on Android, where I simply want to see the list of connected devices via Low Energy Bluetooth. The physical devices which I am using is a smart watch Ticwatch E which is connected to my phone via Bluetooth v4.1/BLE. When I run the app, it shows that there are o devices connected via Bluetooth v4.1/BLE. Below is the code. Can anyone help me with this?
(I am new to typescript and javascript- occasionally write a couple of lines of code, so there could also be code mistake)
import { Component } from '#angular/core';
import { NavController } from 'ionic-angular';
import { BluetoothLE, DeviceInfo } from '#ionic-native/bluetooth-le';
import { Platform } from 'ionic-angular';
import { Toast } from '#ionic-native/toast';
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
foundDevices = [];
constructor(public navCtrl: NavController, public bluetoothle: BluetoothLE, public plt: Platform,
private toast: Toast
) {
let connectedObj: DeviceInfo[] = [];
this.plt.ready().then((readySource) => {
bluetoothle.requestPermission().then(dataTemp => {
console.log('Platform ready from', readySource);
this.toast.show("Platform ready from", '5000', 'center').subscribe(
toast => {
console.log(toast);
}
);
this.bluetoothle.initialize().then(ble => {
console.log('ble', ble.status) // logs 'enabled'
this.toast.show(ble.status, '15000', 'center').subscribe(
toast => {
console.log(toast);
});
this.bluetoothle.retrieveConnected().then(connectedObj => {
this.toast.show("Length: " + connectedObj.devices.length, '25000', 'center').subscribe(
toast => {
console.log(toast);
});
});
});
});
});
}
I've written a provider to help track network connectivity using the Native Network plugin:
import { Injectable } from '#angular/core';
import { Network } from '#ionic-native/network';
import { Platform } from 'ionic-angular';
#Injectable()
export class Connectivity {
public online: boolean = false;
constructor(private network: Network) {
this.network.onDisconnect().subscribe(() => {
console.log('Network offline');
this.online = false;
});
this.network.onConnect().subscribe(() => {
this.online = true;
console.log('Network online');
});
});
}
}
I've installed the relevent plugins (package.json):
"cordova-plugin-network-information": "^2.0.1",
...
"#ionic-native/network": "^4.7.0",
And I've included my provider in my app.module.ts:
providers: [
Network,
StatusBar,
SplashScreen,
Connectivity,
{provide: ErrorHandler, useClass: IonicErrorHandler}
]
Yet, when I run the app in the browser, neither of the observables fire. If I try print: console.log(this.network.type) in the provider constructor, it just prints null.
The answer here is that the native network plugin doesn't work in the browser. Even though it has "browser" listed as a supported platform:
It is referring to the Cordova Browser which is different to a web browser. I found this out after discussion on the Ionic Slack channel.
You need to instead write a Provider that:
Detects platform
If on a native device, use the native network plugin
If in a browser, use the browser API
For others with the same problem:
Here is some clarification on why you have two different APIs available
Here is an example of a provider that uses a variety of approaches for finding location (this isn't the same as my question, but is similar in the solution as it uses a browser API as well as the Ionic Native API)
In my application I use "cordova-plugin-network-information": "^ 2.0.1"
and "#ionic-native / network": "^ 4.6.0"
I can share the same service I use. this is currently working
'# angel / core' import {Injectable};
From the '# Ionic-native / network' resource {Network};
import { Injectable } from '#angular/core';
import { Network } from '#ionic-native/network';
#Injectable()
export class NetworkProvider {
constructor(private _network: Network) { }
isConnectInternet() {
return this._network.onConnect();
}
isDisconnect() {
return this._network.onDisconnect();
}
enter code here
connectionType() {
if (this._network.type == 'none' ) {
return false;
} else {
return true;
}
}
}
I am using this service into my project which is on following environment
cli packages:
#ionic/cli-utils : 1.19.2
ionic (Ionic CLI) : 3.20.0
global packages:
cordova (Cordova CLI) : 8.0.0
this is my provider file, network.ts.
import { Functions } from './../functions';
import { HttpClient } from '#angular/common/http';
import { Injectable } from '#angular/core';
import { Network } from '#ionic-native/network';
import { Events } from 'ionic-angular';
/*
Generated class for the NetworkProvider provider.
See https://angular.io/guide/dependency-injection for more info on providers
and Angular DI.
*/
export enum ConnectionStatusEnum {
Online,
Offline
}
#Injectable()
export class NetworkProvider {
previousStatus;
constructor(public functions:Functions,
public network: Network,
public eventCtrl: Events) {
this.previousStatus = ConnectionStatusEnum.Online;
}
public initializeNetworkEvents(): void {
this.network.onDisconnect().subscribe(() => {
if (this.previousStatus === ConnectionStatusEnum.Online) {
this.eventCtrl.publish('network:offline');
}
this.previousStatus = ConnectionStatusEnum.Offline;
});
this.network.onConnect().subscribe(() => {
if (this.previousStatus === ConnectionStatusEnum.Offline) {
this.eventCtrl.publish('network:online');
}
this.previousStatus = ConnectionStatusEnum.Online;
});
}
make sure that you are running
ionic cordova run browser
not
ionic serve
I have a problem that if a user opens the app and then press the home button or switching to another apps, and when the push notification arrives, and the user clicked on that notification, my app doesn't open. I am using this plugin in ionic -> https://ionicframework.com/docs/native/push/
It seems that when app is in background, app doesn't open when he clicked the push notification. How can I resolve that problem using that plugin.
here's my app.component.ts
import { Component, enableProdMode } from '#angular/core';
import { Platform, NavController, App } from 'ionic-angular';
import { StatusBar } from '#ionic-native/status-bar';
import { Keyboard } from '#ionic-native/keyboard';
import { SplashScreen } from '#ionic-native/splash-screen';
import { HomePage } from '../pages/home/home';
import { Push, PushObject, PushOptions } from '#ionic-native/push';
import { GlobalProvider } from "./global.provider";
import { NotificationDetailsPage } from '../pages/notification-details/notification-details';
enableProdMode();
#Component({
templateUrl: 'app.html'
})
export class MyApp {
rootPage:any = HomePage;
private navCtrl: any;
constructor(
private platform: Platform,
private app:App,
private statusBar: StatusBar,
private splashScreen: SplashScreen,
private keyboard: Keyboard,
private globalVar: GlobalProvider,
private push: Push
) {
platform.ready().then(() => {
// Okay, so the platform is ready and our plugins are available.
// Here you can do any higher level native things you might need.
this.navCtrl = this.app.getActiveNav();
this.statusBar.overlaysWebView(false);
this.statusBar.backgroundColorByHexString('#000000');
setTimeout(() => {
this.splashScreen.hide();
}, 500);
this.keyboard.disableScroll(true);
this.initPushNotification();
});
}
initPushNotification() {
const options: PushOptions = {
android: {
icon: 'small-icon',
forceShow: true
},
ios: {
alert: 'true',
badge: true,
sound: 'true'
},
windows: {}
};
const pushObject: PushObject = this.push.init(options);
pushObject.on('notification').subscribe((notification: any) => {
//Notification Display Section
this.navCtrl.push(NotificationDetailsPage, {notifyId:notification.additionalData.id});
});
pushObject.on('registration').subscribe((registration: any) => {
//Register Device ID
let platformName;
if (this.platform.is('android')) {
platformName = 'android';
} else {
platformName = 'ios';
}
this.globalVar.saveDeviceId(registration.registrationId, platformName).subscribe( data => {});
});
pushObject.on('error').subscribe(error => {
console.log('Can\'t send push notification');
});
}
}
How can I handle or trigger this.navCtrl.push when the user clicks on push notification when app is in background? Please help me to resolve this problem. It is almost 3 days and I can't find any solution.
I changed the PushHandlerActivity.kt to it opens the app when click on notification. I added the forceMainActivityReload(false) to force start the app afetr message "Don't Want Main Activity".
Plugin version:
#havesource/cordova-plugin-push#3.0.0
File:
./platforms/android/app/src/main/java/com/adobe/phonegap/push/PushHandlerActivity.kt
./plugins/#havesource/cordova-plugin-push/src/android/com/adobe/phonegap/push/PushHandlerActivity.kt
./node_modules/#havesource/cordova-plugin-push/src/android/com/adobe/phonegap/push/PushHandlerActivity.kt
From:
if (!dismissed) {
Log.d(TAG, "Is Push Plugin Active: ${PushPlugin.isActive}")
if (!PushPlugin.isActive && foreground && inline) {
Log.d(TAG, "Force Main Activity Reload: Start on Background = False")
forceMainActivityReload(false)
} else if (startOnBackground) {
Log.d(TAG, "Force Main Activity Reload: Start on Background = True")
forceMainActivityReload(true)
} else {
Log.d(TAG, "Don't Want Main Activity")
}
}
To:
if (!dismissed) {
Log.d(TAG, "Is Push Plugin Active: ${PushPlugin.isActive}")
if (!PushPlugin.isActive && foreground && inline) {
Log.d(TAG, "Force Main Activity Reload: Start on Background = False")
forceMainActivityReload(false)
} else if (startOnBackground) {
Log.d(TAG, "Force Main Activity Reload: Start on Background = True")
forceMainActivityReload(true)
} else {
Log.d(TAG, "Don't Want Main Activity (force start)")
forceMainActivityReload(false)
}
}
So the app finally opens when it's closed.
I'm trying to use the following code to subscribe, but it doesn't work.
import { Platform } from 'ionic-angular';
#Page({
templateUrl: 'build/pages/test.html',
})
export class Test {
constructor(private platform: Platform) {
this.platform.pause.subscribe(() => {
console.log('paused')
});
}
}
I'm using Ionic 2 with TypeScript, Angular 2. As platform.pause is an EventEmitter provided by Ionic 2, I suppose it should be able to be subscribed. However, when I put the application to the background, console.log('pause') is not fired.
Should I add Platform to providers or something like that? Plus, this.platform is not null. this.platform.ready().then(()=>{console.log('ready')}) works perfectly.
I think you missed platform.ready() as below
constructor( private platform: Platform ) {
platform.ready().then(() => {
this.platform.pause.subscribe(() => {
console.log('[INFO] App paused');
});
this.platform.resume.subscribe(() => {
console.log('[INFO] App resumed');
});
});
}
The above code worked for me. Hope it helps you as well.