Buttons not working on Android 6.1


#1

Here are my platform details:
Installed platforms:
android 6.1.2
Available platforms:
amazon-fireos ~3.6.3 (deprecated)
blackberry10 ~3.8.0
browser ~4.1.0
firefoxos ~3.6.3
ios ~4.3.0
osx ~4.0.1
webos ~3.7.0

When i build a project and install the app o different phones then it works perfectly fine on Android 7.1 but few of the buttons don’t work on Android version 6.1. For example, signup gives me an error however it stores signup details at the backend. Below is the code of my AndroidManifest.xml file:

<?xml version='1.0' encoding='utf-8'?>
<manifest android:hardwareAccelerated="true" android:versionCode="1" android:versionName="0.0.1" package="com.ionicframework.mappskool349357" xmlns:android="http://schemas.android.com/apk/res/android">
    <supports-screens android:anyDensity="true" android:largeScreens="true" android:normalScreens="true" android:resizeable="true" android:smallScreens="true" android:xlargeScreens="true" />
    <uses-permission android:name="android.permission.INTERNET" />
    <application android:hardwareAccelerated="true" android:icon="@mipmap/icon" android:label="@string/app_name" android:supportsRtl="true">
        <activity android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale" android:label="@string/activity_name" android:launchMode="singleTop" android:name="MainActivity" android:theme="@android:style/Theme.DeviceDefault.NoActionBar" android:windowSoftInputMode="adjustResize">
            <intent-filter android:label="@string/launcher_name">
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:exported="true" android:launchMode="singleTop" android:name="com.gae.scaffolder.plugin.FCMPluginActivity">
            <intent-filter>
                <action android:name="FCM_PLUGIN_ACTIVITY" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
        <service android:name="com.gae.scaffolder.plugin.MyFirebaseMessagingService">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT" />
            </intent-filter>
        </service>
        <service android:name="com.gae.scaffolder.plugin.MyFirebaseInstanceIDService">
            <intent-filter>
                <action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
            </intent-filter>
        </service>
    </application>
    <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="25" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-feature android:name="android.hardware.location.gps" />
</manifest>

#2

What kind of error does it give you?

Did you remote debug the problem on the device already? Follow these instructions here to debug the problem in Chrome dev tools: https://ionic.zone/debug/remote-debug-your-app#android Look at the console and network tabs for errors.


#3

Thanks Sujan. I managed to debug the app. Here is the error message:

net::ERR_INTERNET_DISCONNECTED

Please suggest how do we address this?


#4

Please ignore my previous comment. That was because my devices internet connection. I tried looking at console log but my app is not generating console log related to the error. Its just that my button click is not happening. Here is my button code:

<ion-row>
			<ion-col width=50>
				<button full ion-button (click)=cancel()>Cancel</button>
			</ion-col>
			<ion-col width=50>
				<button full ion-button [disabled]="!userregistrationForm.valid" (click)="SaveUserDetails( user.id, user.name, user.addressLine1, user.addressLine2, user.city, user.zipcode, user.email, user.contact_no, user.about)"><span *ngIf="user.id">Update</span><span *ngIf="!user.id">Add</span></button>
			</ion-col>
		</ion-row>

#5

By any chance is this button inside a <form> element? If so, you must declare it as type="button" or else it will submit the form.


#6

No. This button is not inside . I have similar forms at other places where button is working fine. Here is the full HTML and TS code:

HTML:

<!--
  Generated template for the Registerschool page.

  See http://ionicframework.com/docs/v2/components/#navigation for more info on
  Ionic pages and navigation.
-->
<ion-header>

  <ion-navbar>
        <button ion-button menuToggle>
            <ion-icon name="menu"></ion-icon>
        </button>
        <ion-title>Register School</ion-title>
    </ion-navbar>

</ion-header>
<ion-content padding>
<form [formGroup]="schoolregistrationForm">
<ion-list>
	<ion-item>
		<ion-label floating>Name</ion-label>
		<ion-input  type="text"  [(ngModel)]="school.name" formControlName="name" [class.invalid]="!schoolregistrationForm.controls.name.valid && (schoolregistrationForm.controls.name.dirty|| submitAttempt)"></ion-input>
	</ion-item>
	<ion-item *ngIf="!schoolregistrationForm.controls.name.valid  && (schoolregistrationForm.controls.name.dirty || submitAttempt)">
    <p>Please enter a valid School Name.</p>
</ion-item>
	<ion-item>
		<ion-label floating>Address Line 1</ion-label>
		<ion-input type="text" [(ngModel)]="school.addressLine1" formControlName="addressLine1" [class.invalid]="!schoolregistrationForm.controls.addressLine1.valid && (schoolregistrationForm.controls.addressLine1.dirty|| submitAttempt)"></ion-input>
	</ion-item>
	<ion-item *ngIf="!schoolregistrationForm.controls.addressLine1.valid  && (schoolregistrationForm.controls.addressLine1.dirty || submitAttempt)">
    <p>Please enter a valid Address.</p>
</ion-item>
	<ion-item>
		<ion-label floating>Address Line 2</ion-label>
		<ion-input type="text" [(ngModel)]="school.addressLine2" formControlName="addressLine2" [class.invalid]="!schoolregistrationForm.controls.addressLine2.valid && (schoolregistrationForm.controls.addressLine2.dirty|| submitAttempt)"></ion-input>
	</ion-item>
	<ion-item *ngIf="!schoolregistrationForm.controls.addressLine2.valid  && (schoolregistrationForm.controls.addressLine2.dirty || submitAttempt)">
    <p>Please enter a valid Address.</p>
</ion-item>
	<ion-item>
		<ion-label floating>City</ion-label>
		<ion-input type="text" [(ngModel)]="school.city" formControlName="city" [class.invalid]="!schoolregistrationForm.controls.city.valid && (schoolregistrationForm.controls.city.dirty|| submitAttempt)"></ion-input>
	</ion-item>
	<ion-item *ngIf="!schoolregistrationForm.controls.city.valid  && (schoolregistrationForm.controls.city.dirty || submitAttempt)">
    <p>Please enter a valid City Name.</p>
</ion-item>
	<ion-item>
		<ion-label floating>Zipcode</ion-label>
		<ion-input type="text" [(ngModel)]="school.zipcode" formControlName="zipcode" [class.invalid]="!schoolregistrationForm.controls.zipcode.valid && (schoolregistrationForm.controls.zipcode.dirty|| submitAttempt)"></ion-input>
	</ion-item>
	<ion-item *ngIf="!schoolregistrationForm.controls.zipcode.valid  && (schoolregistrationForm.controls.zipcode.dirty || submitAttempt)">
    <p>Please enter a valid Zipcode.</p>
</ion-item>
	<ion-item>
		<ion-label floating>Email ID</ion-label>
		<ion-input type="email" [(ngModel)]="school.email" formControlName="email" [class.invalid]="!schoolregistrationForm.controls.email.valid && (schoolregistrationForm.controls.email.dirty|| submitAttempt)"></ion-input>
	</ion-item>
	<ion-item *ngIf="!schoolregistrationForm.controls.email.valid  && (schoolregistrationForm.controls.email.dirty || submitAttempt)">
    <p>Please enter a valid Email ID.</p>
</ion-item>
	<ion-item>
		<ion-label floating>Contact Number</ion-label>
		<ion-input type="number" [(ngModel)]="school.contact_no" formControlName="contact_no" [class.invalid]="!schoolregistrationForm.controls.contact_no.valid && (schoolregistrationForm.controls.contact_no.dirty|| submitAttempt)"></ion-input>
	</ion-item>
	<ion-item *ngIf="!schoolregistrationForm.controls.contact_no.valid  && (schoolregistrationForm.controls.contact_no.dirty || submitAttempt)">
    <p>Please enter a valid Contact Number.</p>
</ion-item>
<ion-item>
<ion-label floating>About School</ion-label>
		<ion-input type="text" [(ngModel)]="school.about" formControlName="about" [class.invalid]="!schoolregistrationForm.controls.about.valid && (schoolregistrationForm.controls.about.dirty|| submitAttempt)"></ion-input>
	</ion-item>
<ion-item *ngIf="!schoolregistrationForm.controls.about.valid  && (schoolregistrationForm.controls.about.dirty || submitAttempt)">
    <p>Please enter a valid text.</p>
</ion-item>
	</ion-list>
</form>
		<ion-row>
			<ion-col width=50>
				<button full ion-button (click)=cancel()>Cancel</button>
			</ion-col>
			<ion-col width=50>
				<button full ion-button [disabled]="!schoolregistrationForm.valid" (click)="SaveSchoolDetails( school.id, school.name, school.addressLine1, school.addressLine2, school.city, school.zipcode, school.email, school.contact_no, school.about)"><span *ngIf="school.id">Update</span><span *ngIf="!school.id">Add</span></button>
			</ion-col>
		</ion-row>
</ion-content>

TS File:

import { Component } from '@angular/core';
import { NavController, NavParams } from 'ionic-angular';
import { AngularFire, FirebaseListObservable } from 'angularfire2';
import { SchoolPage } from '../../../pages/school/school/school';
import { UserData } from '../../../providers/user-data';
import { SchoolwelcomePage } from '../../../pages/school/schoolwelcome/schoolwelcome';
import { ClassListPage } from '../../../pages/class/class-list/class-list';
import { DefaultdashboardPage } from '../../../pages/defaultdashboard/defaultdashboard';
import { FormBuilder, FormGroup, Validators, ReactiveFormsModule } from '@angular/forms';
import { Geolocation } from '@ionic-native/geolocation';

/*
  Generated class for the Registerschool page.

  See http://ionicframework.com/docs/v2/components/#navigation for more info on
  Ionic pages and navigation.
*/
@Component({
  selector: 'page-registerschool',
  templateUrl: 'registerschool.html'
})
export class RegisterschoolPage {
	schooldetails: FirebaseListObservable<any[]>;
	linkingdetails: FirebaseListObservable<any[]>;
  roledetails: FirebaseListObservable<any[]>;
  submitAttempt: boolean = false;
  
  schoolregistrationForm: FormGroup;

  role: any;
  lat: any;
  long: any;
  school = {
    id:'',
    name:'',
    addressLine1: '',
    addressLine2: '',
    city: '',
    zipcode:'',
    email:'',
    contact_no: '',
    about: ''
  };

  constructor(public navCtrl: NavController, public navParams: NavParams, public af: AngularFire, public userData: UserData, public formBuilder:FormBuilder, public geolocation: Geolocation) {
  	this.schooldetails = this.af.database.list('/schools');
  	this.linkingdetails = this.af.database.list('/linking');
    
    this.school.id = this.navParams.get('key');
    this.school.name = this.navParams.get('name');
    this.school.addressLine1 = this.navParams.get('addressLine1');
    this.school.addressLine2 = this.navParams.get('addressLine2');
    this.school.city = this.navParams.get('city');
    this.school.zipcode = this.navParams.get('zipcode');
    this.school.email = this.navParams.get('email');
    this.school.contact_no = this.navParams.get('contact_no');
    console.log("About School==>"+this.school.contact_no);
    this.school.about = this.navParams.get('about');
    console.log("About School==>"+this.school.about);
    

    this.schoolregistrationForm = formBuilder.group({
    id: [''],
    name:['', Validators.compose([Validators.maxLength(30), Validators.pattern('[a-zA-Z ]*'), Validators.required])],
    addressLine1: ['' , Validators.compose([Validators.maxLength(30), Validators.pattern('[0-9a-zA-Z, ]*'), Validators.required])],
    addressLine2: ['', Validators.compose([Validators.maxLength(30), Validators.pattern('[0-9a-zA-Z, ]*')])],
    city: ['', Validators.compose([Validators.maxLength(30), Validators.pattern('[a-zA-Z ]*'), Validators.required])],
    zipcode:['', Validators.compose([Validators.maxLength(30), Validators.pattern('[0-9]*'), Validators.required])],
    email:['', Validators.compose([Validators.pattern('^[a-z0-9]+(\.[_a-z0-9]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,15})$'), Validators.required])],
    contact_no: ['', Validators.compose([Validators.maxLength(30), Validators.pattern('[0-9]*'), Validators.required])],
    about: ['', Validators.compose([Validators.maxLength(300), Validators.pattern('^[ A-Za-z0-9_@./#&+-=/$()]*'), Validators.required])]
    })

this.geolocation.getCurrentPosition().then((resp) => {
 this.lat = resp.coords.latitude;
 this.long = resp.coords.longitude;
 console.log("Lattitude==>" +this.lat);
 console.log("Longitude==>" +this.long);
}).catch((error) => {
  console.log('Error getting location', error);
});

  }
  	SaveSchoolDetails( id, name, addressLine1, addressLine2, city, zipcode, email, contact_no, about) {
       this.submitAttempt = true;
      var newSchool = {
  			name: name,
  			addressLine1: addressLine1,
  			addressLine2: addressLine2,
  			city: city,
  			zipcode: zipcode,
  			email: email,
  			contact_no: contact_no,
        lat: this.lat,
        long: this.long,
        about: about,
        picture: "assets/img/school.png"

  		}
  		if(id) { this.schooldetails.update(id, newSchool).then( data => {
        this.navCtrl.pop(this);
      }, error => {
        console.log(error);
      });

      }
      else { this.schooldetails.push(newSchool).then( data => {
  			this.linkingdetails.push(
  			{
  				role: "admin",
  				schoolid: data.key,
          emailid: (firebase.auth().currentUser.email),
          uid: (firebase.auth().currentUser.uid)
  				});
  			this.userData.setUserRole().then( () => {
          this.navCtrl.push(ClassListPage);
        });
      //   .catch((error) => {
      //     this.navCtrl.setRoot(DefaultdashboardPage, {}, {animate: true, direction: 'forward'});
      // });
  		}, error => {
  			console.log(error);
  		});
    }
  	}

    cancel(){
      console.log("Cancel Clicked");
      this.navCtrl.pop(ClassListPage);
    }
}

#7

You have a lot of naked attributes that I don’t think are valid HTML. Wrap them all in quotes and see if that makes a difference.


#8

Sure. Can you please give an example.


#9

(click)="cancel()", not (click)=cancel().


#10

ok. Let me make these changes. Will update you in 5 mins. Thanks.


#11

No luck. Strangely this form works fine on one device and on other device it throws error. Similar issue is being seen on signup page as well. Here is the code of signup form:

HTML File:

<ion-header>
    <ion-navbar>
        <button ion-button menuToggle>
            <ion-icon name="menu"></ion-icon>
        </button>
        <ion-title>Signup</ion-title>
    </ion-navbar>
</ion-header>
<ion-content class="signupScreen">
    <div id="divHeading">
        <ion-icon name="ios-checkmark-circle-outline"></ion-icon>
    </div>
    <form [formGroup]="signupForm">
        <ion-list>
            <ion-item>
                <ion-label floating> Full Name </ion-label>
                <ion-input [(ngModel)]="signup.fullname" type="text" formControlName="fullname" [class.invalid]="!signupForm.controls.fullname.valid && (signupForm.controls.fullname.dirty|| submitAttempt)"></ion-input>
            </ion-item>
            <ion-item *ngIf="!signupForm.controls.fullname.valid  && (signupForm.controls.fullname.dirty || submitAttempt)">
                <p>Please enter a valid Name.</p>
            </ion-item>
            <ion-item>
                <ion-label floating> Email ID </ion-label>
                <ion-input [(ngModel)]="signup.email" type="email" formControlName="email" [class.invalid]="!signupForm.controls.email.valid && (signupForm.controls.email.dirty|| submitAttempt)"></ion-input>
            </ion-item>
            <ion-item *ngIf="!signupForm.controls.email.valid  && (signupForm.controls.email.dirty || submitAttempt)">
                <p>Please enter a valid Email ID.</p>
            </ion-item>
            <ion-item>
                <ion-label floating>Gender</ion-label>
                <ion-select [(ngModel)]="signup.gender" type="text" formControlName="gender" [class.invalid]="!signupForm.controls.gender.valid && (signupForm.controls.gender.dirty|| submitAttempt)">
                    <ion-option value="female">Female</ion-option>
                    <ion-option value="male">Male</ion-option>
                </ion-select>
            </ion-item>
            <ion-item *ngIf="!signupForm.controls.gender.valid  && (signupForm.controls.gender.dirty || submitAttempt)">
                <p>Please enter a valid Gender.</p>
            </ion-item>
            <ion-item>
                <ion-label floating> Password </ion-label>
                <ion-input [(ngModel)]="signup.password" type="password" formControlName="password" [class.invalid]="!signupForm.controls.password.valid && (signupForm.controls.password.dirty|| submitAttempt)"></ion-input>
            </ion-item>
            <ion-item *ngIf="!signupForm.controls.password.valid  && (signupForm.controls.password.dirty || submitAttempt)">
                <p>Please enter a valid Password.</p>
            </ion-item>
            <ion-item>
                <button ion-button (click)="onSignup(signupForm)" type="submit" block>
                <ion-icon name="ios-arrow-forward"></ion-icon>
            </button>
            </ion-item>
        </ion-list>
    </form>
</ion-content>

TS File:

import { Component } from '@angular/core';
import { NavController, AlertController, LoadingController } from 'ionic-angular';
import { Geolocation } from '@ionic-native/geolocation';

// app pages
import { SchoolListPage } from '../../school/school-list/school-list';

// Services
import { UserData } from '../../../providers/user-data';
import { SchoolwelcomePage } from '../../../pages/school/schoolwelcome/schoolwelcome';
import { DefaultdashboardPage } from '../../../pages/defaultdashboard/defaultdashboard';
import { LoginPage } from '../../auth/login/login';
import { Validators, FormControl, FormGroup, FormBuilder } from '@angular/forms';

@Component({
  selector: 'page-signup',
  templateUrl: 'signup.html'
})
export class SignupPage {

  signup: { fullname?: string, email?: string, password?: string, gender?: string } = {};
  alertMessage: any;
  lat: any;
  long: any;
  signupForm: FormGroup;
  submitAttempt: boolean = false;

  constructor(
    public nav: NavController,
    public alertController: AlertController,
    public loadingController: LoadingController,
    public userData: UserData,
    private geolocation: Geolocation,
    public formBuilder: FormBuilder) {
    this.geolocation.getCurrentPosition().then((resp) => {
      this.lat = resp.coords.latitude;
      this.long = resp.coords.longitude;
      console.log("Lattitude==>" + this.lat);
      console.log("Longitude==>" + this.long);
    }).catch((error) => {
      console.log('Error getting location', error);
    });

    this.signupForm = formBuilder.group({
      fullname: ['', Validators.compose([Validators.maxLength(30), Validators.pattern('[a-zA-Z ]*'), Validators.required])],
      gender: ['', Validators.compose([Validators.required])],
      email: ['', Validators.compose([Validators.maxLength(30), Validators.pattern('^[a-z0-9]+(\.[_a-z0-9]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,15})$'), Validators.required])],
      password: ['', Validators.compose([Validators.required])],
    });
  }


  onSignup(form) {
    this.submitAttempt = true;
    if (form.valid) {
      let loading = this.loadingController.create({
        content: 'Please wait...'
      });
      loading.present();

      this.userData.createUser(this.signup).then(() => {
        //this.userData.saveLocalStorage(this.signup);
        //this.userData.createInitialSetup(this.signup);
        let alert = this.alertController.create({
          title: 'Thank you for signing up.',
          subTitle: 'You are being redirected to login page. Please login to continue.',
          buttons: ['Ok']
        });
        this.nav.setRoot(LoginPage, {}, { animate: true, direction: 'forward' });
        alert.present();

        loading.dismiss();
      }).catch(
        (error) => {
          this.SignUpError(error);
          loading.dismiss();
        }
        );
    }
  }

  SignUpError(error): void {
    switch (error.code) {
      case "auth/email-already-in-use":
        this.alertMessage = "The specified email is already in use!"
        break;
      case "auth/invalid-email":
        this.alertMessage = "The specified email is not valid!"
        break;
      case "auth/operation-not-allowed":
        this.alertMessage = "Your account has been disabled. Please contact support!"
        break;
      case "auth/weak-password":
        this.alertMessage = "Password should be at least 6 characters!"
        break;
    }
    let alert = this.alertController.create({
      title: 'Sign Up Failed',
      subTitle: this.alertMessage,
      buttons: ['Ok']
    });
    alert.present();
  }

}

#12

You’ve lost me. First there was an error, then the error was irrelevant and there was no error but the click handler wasn’t being called, and now there’s an error again.


#13

Apologies for causing the confusion. Let’s concentrate on first piece of code. In the first form, i am trying to push the data to firebase and here is the behaviour of same click handler:

  1. Android V 7.1: Handler works perfectly fine and i am able to push the data.
  2. Android V 6.1 (Cynogen): Click handler is not working at all. It doesn’t even throw an error on console.

#14

Ok…finally comparing the logs generated by webpage and mobile devices, i reliazed that my mobile device is not passing GeoLocation which is being fetched using Ionic Native plugin. I am updating the location on Signup as well as on Registration page because of which both of the pages were not able to push data in my DB. I checked google maps on handset and it is working fine. I also checked the build on some other devices and it worked there as well.

Now the question is, do we have some issue with Ionic Native passing geolocation on Android Version 6.1? If not then what can be the workaround to address this?

Basically i will have to add a logic which says that if device is not able to fetch the location then it should move forward without that. Can someone suggest a code snippet to address this situation:

Here is the code to get GeoLocation using Ionic Native plugin:

this.geolocation.getCurrentPosition().then((resp) => {
      this.lat = resp.coords.latitude;
      this.long = resp.coords.longitude;
      console.log("Lattitude==>" + this.lat);
      console.log("Longitude==>" + this.long);
    }).catch((error) => {
      console.log('Error getting location', error);
    });