When I tap physical Android Button I've got the next error:
Unhandled exception java.lang.IndexOutOfBoundsException: setSpan
(2..2) ends beyound length 0
Here is my app.routing.ts
import { LoginComponent } from "./pages/login/login.component";
import { CarwashComponent } from "./pages/carwash/carwash.component";
import { NewOrderComponent } from "./pages/new_order/new-order.component";
import { ProfileComponent } from "./pages/profile/profile.component";
import { OrderDetailComponent } from "./pages/order/order-detail/order-detail.component";
export const routes = [
{ path: "", component: LoginComponent },
{ path: "profile", component: ProfileComponent},
{ path: "carwash", component: CarwashComponent },
{ path: "order-detail/:order_id", component: OrderDetailComponent },
{ path: "new_order", component: NewOrderComponent}
];
export const navigatableComponents = [
LoginComponent,
CarwashComponent,
ProfileComponent,
OrderDetailComponent,
NewOrderComponent
];
Example of the page:
import { Component, ElementRef, OnInit, ViewChild, OnChanges } from "#angular/core";
import { CarwashService } from "../../../shared/carwash/carwash.service";
import { OrderService } from "../../../shared/order/order.service";
import { Page } from "ui/page";
import { Color } from "color";
import { Router, ActivatedRoute, Params } from "#angular/router";
import { TimePicker } from "ui/time-picker";
import { DatePicker } from "ui/date-picker";
import { StoredData } from "../../../shared/config"
import * as application from "application";
#Component({
selector: "order-detail",
providers: [CarwashService, OrderService],
templateUrl: "pages/order/order-detail/order-detail.html",
styleUrls: ["pages/order/order-detail/order-detail-common.css", "pages/order/order-detail/order-detail.css"]
})
export class OrderDetailComponent implements OnInit {
constructor(
private page: Page,
private router: Router,
private carwashService: CarwashService,
private orderService: OrderService,
private route: ActivatedRoute){}
ngOnInit() {... }
checkStatus(){...}
addOrderTotalName(){...}
changeStatus(status){...}
closeOrder(){...}
cancelOrder(){...}
}
What's wrong?enter image description here
Normally the physical back button will behave as going back to previous page, but I don't know why this happens to you. You can try to define again the function for the back button like this:
var application = require("application")
var topmost = require("ui/frame").topmost;
var activity = application.android.startActivity ||
application.android.foregroundActivity ||
frameModule.topmost().android.currentActivity ||
frameModule.topmost().android.activity;
var lastPress;
activity.onBackPressed = function() {
topmost().goBack;
}
Related
I have a problem testing my ionic app on my phone and android studio, when i press the hardware back button the application inmediatly exits, i've tried many solutions, but it simply won't work and won't listen to whatever i code into it.
Here is my attempt
import { Component, Renderer2, ViewChild } from '#angular/core';
import { IonRouterOutlet, Platform } from '#ionic/angular';
import { SplashScreen } from '#ionic-native/splash-screen/ngx';
import { StatusBar } from '#ionic-native/status-bar/ngx';
import { TranslateService } from '#ngx-translate/core';
import { Location } from '#angular/common';
#Component({
selector: 'app-root',
templateUrl: 'app.component.html',
styleUrls: ['app.component.scss']
})
export class AppComponent {
#ViewChild(IonRouterOutlet, {static: true}) routerOutlet: IonRouterOutlet
constructor(
private platform: Platform,
private splashScreen: SplashScreen,
private statusBar: StatusBar,
private renderer: Renderer2,
private translate: TranslateService,
private location: Location
) {
this.initializeApp();
}
initializeApp() {
this.translate.setDefaultLang( localStorage.getItem('default-language') ? localStorage.getItem('default-language') : navigator.language.slice(0, 2) )
this.platform.ready().then(() => {
this.statusBar.styleDefault();
this.splashScreen.hide();
this.backButtonEvent();
if (localStorage.getItem('color-theme')) {
this.renderer.setAttribute(document.body, 'color-theme', localStorage.getItem('color-theme'))
} else {
if(window.matchMedia && window.matchMedia('(prefers-color-scheme: light)').matches === true)
this.renderer.setAttribute(document.body, 'color-theme', 'light')
else
this.renderer.setAttribute(document.body, 'color-theme', 'dark')
}
});
}
backButtonEvent() {
this.platform.backButton.subscribeWithPriority(0, async () => {
if(!this.routerOutlet.canGoBack())
navigator["app"].exitApp()
else
this.location.back()
});
}
}
Try it this way using the #capacitor/app package:
import { App } from '#capacitor/app';
App.addListener('backButton', ({ canGoBack }) => {
if(canGoBack){
window.history.back();
} else {
App.exitApp();
}
});
i send login data to service, after get response in login.ts toast is not difined, how to resolve this ?
i try my toast function in another function withot condition in service its work
this my function for load service login.ts:
import { Component, OnInit } from '#angular/core';
import { NavController, MenuController, PopoverController } from "ionic-angular";
import { TabsInfluencerComponent } from '../../influencer/tabs/tabs';
import { RegisterComponent } from '../register/register';
import { ResetComponent } from '../reset/reset';
import { OfferComponent } from '../../advertiser/offer/offer';
import { ngForm } from '#angular/forms';
import { AuthService } from '../../../services/auth';
import { ToastController } from 'ionic-angular';
#Component({
templateUrl: 'login.component.html',
})
export class LoginComponent implements OnInit {
constructor(
public nav:NavController,
public menu:MenuController,
public popover: PopoverController,
private AuthService : AuthService,
private toastCtrl: ToastController) {
}
responseData : any;
public isChoose: boolean = false;
public isshowP: boolean = false;
//login and get data in service
login(form: ngForm){
this.AuthService.login(form.value.email, form.value.password)
.then(function(data) {
if(data.success == true){
localStorage.setItem('userToken',data.token);
localStorage.setItem('userData',JSON.stringify(data.user));
}else{
let toast = this.toastCtrl.create({
message: data.error,
duration: 3000
});
toast.present();
}
})
.catch(function(error) {
console.log(error);
})
}
}
this my service auth.ts:
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders } from '#angular/common/http';
import { map } from 'rxjs/operators'
#Injectable()
export class AuthService {
private loginUrl : string = 'http://localhost:8000/api/login';
data : any;
constructor(private http: HttpClient){}
//function for login
login(email : string, password :string){
const body = {email : email, password : password};
return new Promise(resolve => {
this.http.post(this.loginUrl, body)
.subscribe(data => {
this.data = data;
resolve(this.data);
});
});
}
register(email : string, password :string){
}
}
after run i have error like this :
TypeError: Cannot read property 'toastCtrl' of undefined
In this case it is a problem with your this reference in your login.ts.
.then(function(data) {
...
let toast = this.toastCtrl.create({
message: data.error,
duration: 3000
});
...
})
The this is referring the anonymous function in your then block, but you want to refer back to your LoginComponent class.
How to solve this?
You could use arrow functions, that are really popular right now.
.then((data) => {
...
let toast = this.toastCtrl.create({
message: data.error,
duration: 3000
});
...
})
I’m using local notifications native plugin on my ionic 3 project (latest version), but when I click on notification and my app is closed the click event is not triggered.
It works when app is in background or foreground.
I use local notifications inside a provider and my on click code is inside its constructor but when app is closed it's not working.
I’ve tried to write code inside platform ready in app/app.component.ts but this approach does not work.
This is my code:
app/app.component.ts
export class MyApp {
#ViewChild(Nav) nav: Nav;
rootPage: any;
constructor(
public platform: Platform,
public menu: MenuController,
public statusBar: StatusBar,
public splashScreen: SplashScreen,
public BeaconServiceProvider: BeaconServiceProvider, /* my provider with local notifications*/
public RemoteServiceProvider: RemoteServiceProvider,
public translate: TranslateService,
public globalization: Globalization,
private oneSignal: OneSignal,
public ga: GoogleAnalytics
) {
......
}
}
My provider
import { HttpClient } from '#angular/common/http';
import { Injectable } from '#angular/core';
import { Storage } from '#ionic/storage';
import { IBeacon } from '#ionic-native/ibeacon';
import { LocalNotifications } from '#ionic-native/local-notifications';
import { RemoteServiceProvider } from '../remote-service/remote-service';
import { StorageProvider } from '../storage/storage';
import { TranslateService } from '#ngx-translate/core';
import { AlertController } from 'ionic-angular';
import { NavController, App} from "ionic-angular/index";
import { GoogleAnalytics } from '#ionic-native/google-analytics';
#Injectable()
export class BeaconServiceProvider {
remoteBeacons: Array<{major: string, minor: string}> = [];
localBeacons: Array<{major: string, minor: string, date: any}> = [];
bluetoothInit: boolean = false;
private navCtrl: NavController;
constructor(
public http: HttpClient,
public alertCtrl: AlertController,
public storage: Storage,
public ibeacon: IBeacon,
public translate: TranslateService,
public localNotifications: LocalNotifications,
public RemoteServiceProvider: RemoteServiceProvider,
public StorageProvider: StorageProvider,
public ga: GoogleAnalytics,
private app: App
) {
console.log('Hello BeaconProvider Provider');
this.localBeacons = this.StorageProvider.localBeacons;
this.navCtrl = this.app.getActiveNav();
let thiz_app = this.app;
let remote = this.RemoteServiceProvider;
this.localNotifications.on("click", function(notification, state){
this.ga.trackEvent(
"Notifiche Beacon (" + remote.version_code + ")",
"Apertura notifica",
"Click sulla notifica beacon " + " {" + notification.message + "}",
1
);
let nav = thiz_app.getActiveNav();
let data = JSON.parse(notification.data);
let page_id = data.page_id;
page_id = page_id.toString();
switch(page_id)
{
case "" :
case "0" :
break;
case "-1" : //Contact Page
if (nav == null)
nav.push('ContactPage');
else if (nav.getActive().component.name != 'ContactPage')
nav.push('ContactPage');
break;
default :
remote.isPageListNew(page_id).subscribe(result => {
let page = result.has_subpages ? 'List2Page' : 'ItemDetailsPage';
if (nav == null)
nav.push(page, { item: result });
else
{
if( nav.getActive().component.name != page)
nav.push(page, { item: result });
else
{
let item_id = nav.getActive().data.item.id;
if (item_id != result.id)
nav.push(page, { item: result });
}
}
});
}
});
}
Any ideas why my code does not work?
Thanks
So I'm actually loosing my mind. I'm new to Angular 2 and I'm trying to understand how to let sibling child components comunicate between each other.
I have n child components that can play an Audio file.
The goal is to stop playing component if someone is started.
E.G. : component 1 is played, I play start on component 2, component 1 is stopped, component 2 is played.
I tried with shared service with no luck and also trying with EventEmitter comunicating from child to parent but it is not working.
I cannot figure out how to notify all components at once.
RegistrationComponent ( child )
import {Component, Input, Output, EventEmitter} from '#angular/core';
import {Path} from "./data-model";
import {MediaPlugin} from '#ionic-native/media';
import {Platform} from 'ionic-angular';
import {SocialSharing} from '#ionic-native/social-sharing';
import {RegistrationService} from './registration.service';
#Component({
selector: 'registration',
template: `
<div class="reg__name">{{ url.name }}</div>
<button ion-button color="secondary" item-right clear large (click)="toggle(url.path);">
<ion-icon [name]="playing ? 'md-square' : 'md-play'"></ion-icon>
</button>`,
providers: [
MediaPlugin,
SocialSharing,
RegistrationService
]
})
export class RegistrationComponent {
#Input() url: Path;
#Input() someonePlaying: boolean = false;
#Output() onPlayed = new EventEmitter<boolean>();
playing: boolean = false;
mediaContainer: any;
path: string;
constructor(private media: MediaPlugin,
private platform: Platform,
private socialSharing: SocialSharing,
private service: RegistrationService) {
this.path = "assets/audio";
// service.playing.subscribe(val => this.onSomeonePlaying(val));
}
ngOnChanges() {
console.log(this.someonePlaying);
}
toggle(filename) {
this.playing
? this.stop()
: this.play(filename)
}
play(fileName) {
const mp3URL = this.getMediaURL(`${this.path}/${fileName}`);
this.mediaContainer = this.media.create(mp3URL);
this.mediaContainer.play();
this.playing = true;
this.onPlayed.emit(true);
}
stop() {
this.mediaContainer.stop();
this.playing = false;
// this.service.stop();
}
share() {
this.socialSharing.shareViaWhatsApp("Condividi su Whatsapp", "", "");
}
onSomeonePlaying(val: boolean) {
console.log(val);
}
getMediaURL(s) {
let isAndroid = this.platform.is("android");
return isAndroid ? `/android_asset/www/${s}` : s;
}
}
Portion of home.html that prints the components
<ion-item *ngFor="let url of currentUrls">
<registration (onPlayed)="onPlayed($event)"
[(someonePlaying)] = "globalPlaying"
[url]="url"></registration>
</ion-item>
*home.ts**
import {Component} from '#angular/core';
import {NavController} from 'ionic-angular';
import {Registrations, Registration} from './data-model';
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
path: string;
urls: Array<any>;
currentUrls: Array<{name: string, path: string}>;
globalPlaying: boolean = false;
constructor(public navCtrl: NavController) {
this.path = "assets/audio";
this.urls = Registrations;
this.currentUrls = [];
for (let i = 0; i < this.urls.length; i++) {
this.currentUrls = this.currentUrls.concat(this.urls[i]["paths"]);
}
}
onChange(key) {
this.currentUrls = this.filter(key);
}
onPlayed(val){
console.log("global playing", val);
this.globalPlaying = true;
}
filter(key) {
if (!key || key === "all")
return this.findAll(this.urls);
return this.findWhere(this.urls, key)["paths"];
}
findAll(collection) {
let array = [];
for (let i = 0; i < collection.length; i++) {
array = array.concat(collection[i]["paths"]);
}
return array;
}
findWhere(collection, key) {
for (let i = 0; i < collection.length; i++) {
if (collection[i]["id"] === key)
return collection[i];
}
}
}
You should subscribe to EventEmitter to catch the events. You need a service with an EventEmitter:
#Injectable()
export class MyService
{
myEventEmiter:EventEmitter<void> = new EventEmitter<void>();
}
Then inject service into your component and subscribe to it to catch the events:
contsruct(protected myService:MyService){}
ngOnInit()
{
this.myService.subscribe(
() => { //An event occurs }
);
}
At the other hand in another component you should emit the EventEmitter to create new event:
this.myService.emit();
I used an event to notify other instances to hide, of my date-picker component.
Please follow
event-broadcasting-in-angular-2
You have to create a broadcaster and messageEvent.
I'm new at Ionic2.I am developing a test application on ionic 2,There are many features in it(SMS,Call Number,Chart,MySql,Push ...)I just followed the steps for push notification.push notification link.But I get an error and I do not get the cause.Where do i make mistakes
app.component.ts
import { Component } from '#angular/core';
import { Platform } from 'ionic-angular';
import { StatusBar } from '#ionic-native/status-bar';
import { SplashScreen } from '#ionic-native/splash-screen';
import {
Push,
PushToken
} from '#ionic/cloud-angular';
import { HomePage } from '../pages/home/home';
#Component({
templateUrl: 'app.html',
providers: [Push]
})
export class MyApp {
rootPage:any = HomePage;
constructor(platform: Platform, statusBar: StatusBar, splashScreen:
SplashScreen,public 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.
statusBar.styleDefault();
splashScreen.hide();
});
this.push.register().then((t: PushToken) => {
return this.push.saveToken(t);
}).then((t: PushToken) => {
console.log('Token saved:', t.token);
});
this.push.rx.notification()
.subscribe((msg) => {
alert(msg.title + ': ' + msg.text);
});
}
}
app.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { ErrorHandler, NgModule } from '#angular/core';
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';
import { SplashScreen } from '#ionic-native/splash-screen';
import { StatusBar } from '#ionic-native/status-bar';
import {CallNumber} from '#ionic-native/call-number';
import { SMS } from '#ionic-native/sms';
import {ChartPage} from '../pages/chart/chart';
import {CallNumberPage} from '../pages/call-number/call-number';
import { SQLite, SQLiteObject } from '#ionic-native/sqlite';
import { Toast } from '#ionic-native/toast';
import { HttpModule } from '#angular/http';
import {CloudSettings,CloudModule} from '#ionic/cloud-angular';
import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';
import {CanvasPage} from '../pages/canvas/canvas';
import {SqlitePage} from '../pages/sqlite/sqlite';
import {MysqlPage} from '../pages/mysql/mysql';
import {ServiceProvider} from '../providers/datamember';
import {ListPage} from '../pages/list/list';
const cloudSettings: CloudSettings = {
'core': {
'app_id': 'xxxxxxx',
},
'push': {
'sender_id': 'xxxxxxxxx',
'pluginConfig': {
'ios': {
'badge': true,
'sound': true
},
'android': {
'iconColor': '#343434'
}
}
}
};
#NgModule({
declarations: [
MyApp,
HomePage,
ChartPage,
CallNumberPage,
CanvasPage,
SqlitePage,
MysqlPage,
ListPage
],
imports: [
BrowserModule,
HttpModule,
IonicModule.forRoot(MyApp)
],
bootstrap: [IonicApp],
entryComponents: [
MyApp,
HomePage,
ChartPage,
CallNumberPage,
CanvasPage,
SqlitePage,
MysqlPage,
ListPage
],
providers: [
StatusBar,
SplashScreen,
CallNumber,
SMS,
SQLite,
Toast,
ServiceProvider,
HttpModule,
{provide: ErrorHandler, useClass: IonicErrorHandler}
]
})
export class AppModule {}
You need to have the cloud client setup to use Push . Check here
Add CloudModule to imports.
imports: [
BrowserModule,
HttpModule,
CloudModule.forRoot(cloudSettings), //here
IonicModule.forRoot(MyApp)
],