Quantcast
Channel: Ionic Forum - Latest topics
Viewing all 70904 articles
Browse latest View live

Ionic Capacitor Android app

$
0
0

I have an Ionic project that uses AR.js. The web app works as it should, the camera and all working and im trying to create an android native app. I am using InAppBrowser to do so but there is a problem where i get and error saying ''Permission denied" when it is trying to run the AR and the camera doesn’t show as intended. How can I give access to the camera? I’ve tried the plugin ‘AndroidPermissions’ as well as adding to the AndroidManifest.xml but still nothing. Thanks!

1 post - 1 participant

Read full topic


How to create release build for Android 8.1 with Capacitor 3.4.0 (error: "App not installed")

$
0
0

Hi community,

As I am relatively new to Capacitor and Android Studio I hope I am at the right place for help.

I am creating an application with Vue (2) and Capacitor 3.4.0
Default settings (variables) seems to be injected as:

  • minSdkVersion: 21
  • compileSdkVersion: 30
  • targetSdkVersion: 30

when running the debug version from Android Studio everything works fine on my Android 8.1 device.
even with compile/target level 30 (while Android 8.1 has level 27)

when creating a release build (signed and unsigned) both are compiling and creating the APK.
when opening either of those two, the staging is done, installing is done, (and with the signed APK I get an ‘are you sure’ message when ‘installing’ is almost done; “install anyway”)…
I get the (in)famous “App not installed” error.

My guess is it has to do with the Android level targeting, as Android 8.1 support only up to 27

  • compileSdkVersion: 30
  • targetSdkVersion: 30

Question 1: why is the debug version running smoothly on level 27 with compile/target version set to 30?

When changing the compile/target levels to 27 I get compile errors in the build output.

Executing tasks: [:app:assembleDebug] in project ****/product-explorer/android


> Configure project :app
AGPBI: {"kind":"warning","text":"Using flatDir should be avoided because it doesn't support any meta-data formats.","sources":[{}]}

> Configure project :capacitor-cordova-android-plugins
AGPBI: {"kind":"warning","text":"Using flatDir should be avoided because it doesn't support any meta-data formats.","sources":[{}]}

> Task :app:preBuild UP-TO-DATE
> Task :app:preDebugBuild UP-TO-DATE
> Task :capacitor-android:preBuild UP-TO-DATE
> Task :capacitor-android:preDebugBuild UP-TO-DATE
> Task :capacitor-android:compileDebugAidl NO-SOURCE
> Task :capacitor-cordova-android-plugins:preBuild UP-TO-DATE
> Task :capacitor-cordova-android-plugins:preDebugBuild UP-TO-DATE
> Task :capacitor-cordova-android-plugins:compileDebugAidl NO-SOURCE
> Task :capacitor-splash-screen:preBuild UP-TO-DATE
> Task :capacitor-splash-screen:preDebugBuild UP-TO-DATE
> Task :capacitor-splash-screen:compileDebugAidl NO-SOURCE
> Task :capacitor-status-bar:preBuild UP-TO-DATE
> Task :capacitor-status-bar:preDebugBuild UP-TO-DATE
> Task :capacitor-status-bar:compileDebugAidl NO-SOURCE
> Task :app:compileDebugAidl NO-SOURCE
> Task :capacitor-android:packageDebugRenderscript NO-SOURCE
> Task :capacitor-cordova-android-plugins:packageDebugRenderscript NO-SOURCE
> Task :capacitor-splash-screen:packageDebugRenderscript NO-SOURCE
> Task :capacitor-status-bar:packageDebugRenderscript NO-SOURCE
> Task :app:compileDebugRenderscript NO-SOURCE
> Task :app:generateDebugBuildConfig
> Task :app:javaPreCompileDebug
> Task :capacitor-android:writeDebugAarMetadata
> Task :capacitor-cordova-android-plugins:writeDebugAarMetadata
> Task :capacitor-splash-screen:writeDebugAarMetadata
> Task :capacitor-status-bar:writeDebugAarMetadata
> Task :app:generateDebugResValues
> Task :app:generateDebugResources
> Task :capacitor-android:compileDebugRenderscript NO-SOURCE
> Task :capacitor-android:generateDebugResValues
> Task :capacitor-android:generateDebugResources
> Task :capacitor-android:packageDebugResources
> Task :capacitor-cordova-android-plugins:compileDebugRenderscript NO-SOURCE
> Task :capacitor-cordova-android-plugins:generateDebugResValues
> Task :capacitor-cordova-android-plugins:generateDebugResources
> Task :capacitor-cordova-android-plugins:packageDebugResources
> Task :capacitor-splash-screen:compileDebugRenderscript NO-SOURCE
> Task :capacitor-splash-screen:generateDebugResValues
> Task :capacitor-splash-screen:generateDebugResources
> Task :capacitor-splash-screen:packageDebugResources
> Task :capacitor-status-bar:compileDebugRenderscript NO-SOURCE
> Task :capacitor-status-bar:generateDebugResValues
> Task :capacitor-status-bar:generateDebugResources
> Task :capacitor-status-bar:packageDebugResources
> Task :app:createDebugCompatibleScreenManifests
> Task :app:extractDeepLinksDebug
> Task :capacitor-android:extractDeepLinksDebug
> Task :capacitor-cordova-android-plugins:extractDeepLinksDebug
> Task :capacitor-android:processDebugManifest
> Task :capacitor-cordova-android-plugins:processDebugManifest
> Task :capacitor-splash-screen:extractDeepLinksDebug
> Task :app:checkDebugAarMetadata
> Task :capacitor-status-bar:extractDeepLinksDebug
> Task :capacitor-android:compileDebugLibraryResources
> Task :capacitor-cordova-android-plugins:compileDebugLibraryResources
> Task :capacitor-splash-screen:compileDebugLibraryResources
> Task :capacitor-status-bar:processDebugManifest
> Task :capacitor-splash-screen:parseDebugLocalResources
> Task :capacitor-status-bar:compileDebugLibraryResources
> Task :capacitor-splash-screen:processDebugManifest
> Task :capacitor-android:parseDebugLocalResources
> Task :capacitor-cordova-android-plugins:parseDebugLocalResources
> Task :capacitor-status-bar:parseDebugLocalResources
> Task :capacitor-android:generateDebugBuildConfig
> Task :capacitor-android:javaPreCompileDebug
> Task :capacitor-cordova-android-plugins:generateDebugBuildConfig
> Task :capacitor-cordova-android-plugins:javaPreCompileDebug
> Task :capacitor-splash-screen:generateDebugBuildConfig
> Task :capacitor-splash-screen:javaPreCompileDebug
> Task :capacitor-status-bar:generateDebugBuildConfig
> Task :app:mergeDebugNativeDebugMetadata NO-SOURCE
> Task :capacitor-status-bar:javaPreCompileDebug
> Task :app:mergeDebugShaders
> Task :app:compileDebugShaders NO-SOURCE
> Task :app:generateDebugAssets UP-TO-DATE
> Task :capacitor-cordova-android-plugins:generateDebugRFile
> Task :capacitor-android:mergeDebugShaders
> Task :capacitor-android:generateDebugRFile
> Task :app:processDebugMainManifest
> Task :app:processDebugManifest
> Task :app:mergeDebugResources
> Task :capacitor-cordova-android-plugins:compileDebugJavaWithJavac
> Task :capacitor-android:compileDebugShaders NO-SOURCE
> Task :capacitor-android:generateDebugAssets UP-TO-DATE
> Task :capacitor-cordova-android-plugins:bundleLibCompileToJarDebug
> Task :capacitor-android:packageDebugAssets
> Task :capacitor-cordova-android-plugins:mergeDebugShaders
> Task :capacitor-cordova-android-plugins:compileDebugShaders NO-SOURCE
> Task :capacitor-cordova-android-plugins:generateDebugAssets UP-TO-DATE
> Task :capacitor-cordova-android-plugins:packageDebugAssets
> Task :capacitor-splash-screen:mergeDebugShaders
> Task :capacitor-splash-screen:compileDebugShaders NO-SOURCE
> Task :capacitor-splash-screen:generateDebugAssets UP-TO-DATE
> Task :capacitor-splash-screen:packageDebugAssets
> Task :capacitor-status-bar:mergeDebugShaders
> Task :capacitor-status-bar:compileDebugShaders NO-SOURCE
> Task :capacitor-status-bar:generateDebugAssets UP-TO-DATE
> Task :capacitor-status-bar:packageDebugAssets
> Task :app:mergeDebugAssets
> Task :app:processDebugJavaRes NO-SOURCE
> Task :capacitor-android:processDebugJavaRes NO-SOURCE
> Task :capacitor-android:bundleLibResDebug NO-SOURCE
> Task :capacitor-cordova-android-plugins:processDebugJavaRes NO-SOURCE
> Task :capacitor-cordova-android-plugins:bundleLibResDebug NO-SOURCE
> Task :capacitor-splash-screen:processDebugJavaRes NO-SOURCE
> Task :capacitor-splash-screen:bundleLibResDebug NO-SOURCE
> Task :capacitor-status-bar:processDebugJavaRes NO-SOURCE
> Task :capacitor-status-bar:bundleLibResDebug NO-SOURCE
> Task :capacitor-splash-screen:generateDebugRFile
> Task :capacitor-status-bar:generateDebugRFile
> Task :app:mergeDebugJavaResource
> Task :app:compressDebugAssets

> Task :capacitor-android:compileDebugJavaWithJavac
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.

> Task :app:processDebugManifestForPackage
> Task :app:desugarDebugFileDependencies
> Task :app:checkDebugDuplicateClasses
> Task :capacitor-android:bundleLibCompileToJarDebug
> Task :capacitor-android:bundleLibRuntimeToDirDebug
> Task :app:mergeDebugJniLibFolders
> Task :capacitor-android:mergeDebugJniLibFolders
> Task :capacitor-android:mergeDebugNativeLibs NO-SOURCE
> Task :capacitor-cordova-android-plugins:bundleLibRuntimeToDirDebug
> Task :capacitor-android:stripDebugDebugSymbols NO-SOURCE
> Task :capacitor-android:copyDebugJniLibsProjectOnly
> Task :capacitor-cordova-android-plugins:mergeDebugJniLibFolders
> Task :capacitor-cordova-android-plugins:mergeDebugNativeLibs NO-SOURCE
> Task :capacitor-cordova-android-plugins:stripDebugDebugSymbols NO-SOURCE
> Task :capacitor-cordova-android-plugins:copyDebugJniLibsProjectOnly
> Task :capacitor-splash-screen:mergeDebugJniLibFolders
> Task :capacitor-splash-screen:mergeDebugNativeLibs NO-SOURCE
> Task :capacitor-splash-screen:stripDebugDebugSymbols NO-SOURCE
> Task :capacitor-splash-screen:copyDebugJniLibsProjectOnly
> Task :capacitor-splash-screen:compileDebugJavaWithJavac
> Task :capacitor-splash-screen:bundleLibCompileToJarDebug
> Task :capacitor-status-bar:compileDebugJavaWithJavac
> Task :capacitor-status-bar:bundleLibCompileToJarDebug
> Task :capacitor-status-bar:mergeDebugJniLibFolders
> Task :capacitor-splash-screen:bundleLibRuntimeToDirDebug
> Task :capacitor-status-bar:mergeDebugNativeLibs NO-SOURCE
> Task :capacitor-status-bar:bundleLibRuntimeToDirDebug
> Task :capacitor-status-bar:stripDebugDebugSymbols NO-SOURCE
> Task :capacitor-status-bar:copyDebugJniLibsProjectOnly
> Task :app:mergeExtDexDebug
> Task :app:validateSigningDebug
> Task :app:writeDebugAppMetadata
> Task :app:writeDebugSigningConfigVersions
> Task :app:mergeDebugNativeLibs NO-SOURCE
> Task :app:stripDebugDebugSymbols NO-SOURCE

> Task :app:processDebugResources FAILED
AGPBI: {"kind":"error","text":"Android resource linking failed","sources":[{"file":"/Users/Remco/.gradle/caches/transforms-3/d0765aaf7ad2db850fe88cd4a9d96261/transformed/appcompat-1.2.0/res/values-v28/values-v28.xml","position":{"startLine":4,"startColumn":4,"startOffset":217,"endLine":7,"endColumn":12,"endOffset":442}}],"original":"ERROR:/Users/Remco/.gradle/caches/transforms-3/d0765aaf7ad2db850fe88cd4a9d96261/transformed/appcompat-1.2.0/res/values-v28/values-v28.xml:5:5-8:13: AAPT: error: resource android:attr/dialogCornerRadius not found.\n    ","tool":"AAPT"}
AGPBI: {"kind":"error","text":"Android resource linking failed","sources":[{"file":"/Users/Remco/.gradle/caches/transforms-3/d0765aaf7ad2db850fe88cd4a9d96261/transformed/appcompat-1.2.0/res/values-v28/values-v28.xml","position":{"startLine":8,"startColumn":4,"startOffset":447,"endLine":11,"endColumn":12,"endOffset":684}}],"original":"ERROR:/Users/Remco/.gradle/caches/transforms-3/d0765aaf7ad2db850fe88cd4a9d96261/transformed/appcompat-1.2.0/res/values-v28/values-v28.xml:9:5-12:13: AAPT: error: resource android:attr/dialogCornerRadius not found.\n    ","tool":"AAPT"}
AGPBI: {"kind":"error","text":"Android resource linking failed","sources":[{"file":"/Users/Remco/.gradle/caches/transforms-3/bb38d725adac671245a565f7873da5cd/transformed/core-1.3.2/res/values/values.xml","position":{"startLine":141,"startColumn":4,"startOffset":8808,"endLine":172,"endColumn":24,"endOffset":10868}}],"original":"ERROR:/Users/Remco/.gradle/caches/transforms-3/bb38d725adac671245a565f7873da5cd/transformed/core-1.3.2/res/values/values.xml:142:5-173:25: AAPT: error: resource android:attr/fontVariationSettings not found.\n    ","tool":"AAPT"}
AGPBI: {"kind":"error","text":"Android resource linking failed","sources":[{"file":"/Users/Remco/.gradle/caches/transforms-3/bb38d725adac671245a565f7873da5cd/transformed/core-1.3.2/res/values/values.xml","position":{"startLine":141,"startColumn":4,"startOffset":8808,"endLine":172,"endColumn":24,"endOffset":10868}}],"original":"ERROR:/Users/Remco/.gradle/caches/transforms-3/bb38d725adac671245a565f7873da5cd/transformed/core-1.3.2/res/values/values.xml:142:5-173:25: AAPT: error: resource android:attr/ttcIndex not found.\n    ","tool":"AAPT"}
AGPBI: {"kind":"error","text":"Android resource linking failed","sources":[{"file":"/Users/Remco/.gradle/caches/transforms-3/d0765aaf7ad2db850fe88cd4a9d96261/transformed/appcompat-1.2.0/res/values/values.xml","position":{"startLine":2770,"startColumn":4,"startOffset":173200,"endLine":2793,"endColumn":24,"endOffset":174397}}],"original":"ERROR:/Users/Remco/.gradle/caches/transforms-3/d0765aaf7ad2db850fe88cd4a9d96261/transformed/appcompat-1.2.0/res/values/values.xml:2771:5-2794:25: AAPT: error: resource android:attr/textFontWeight not found.\n    ","tool":"AAPT"}

> Task :app:mergeLibDexDebug

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:processDebugResources'.
> A failure occurred while executing com.android.build.gradle.internal.res.LinkApplicationAndroidResourcesTask$TaskAction
   > Android resource linking failed
     ERROR:/Users/Remco/.gradle/caches/transforms-3/d0765aaf7ad2db850fe88cd4a9d96261/transformed/appcompat-1.2.0/res/values-v28/values-v28.xml:5:5-8:13: AAPT: error: resource android:attr/dialogCornerRadius not found.
         
     ERROR:/Users/Remco/.gradle/caches/transforms-3/d0765aaf7ad2db850fe88cd4a9d96261/transformed/appcompat-1.2.0/res/values-v28/values-v28.xml:9:5-12:13: AAPT: error: resource android:attr/dialogCornerRadius not found.
         
     ERROR:/Users/Remco/.gradle/caches/transforms-3/bb38d725adac671245a565f7873da5cd/transformed/core-1.3.2/res/values/values.xml:142:5-173:25: AAPT: error: resource android:attr/fontVariationSettings not found.
         
     ERROR:/Users/Remco/.gradle/caches/transforms-3/bb38d725adac671245a565f7873da5cd/transformed/core-1.3.2/res/values/values.xml:142:5-173:25: AAPT: error: resource android:attr/ttcIndex not found.
         
     ERROR:/Users/Remco/.gradle/caches/transforms-3/d0765aaf7ad2db850fe88cd4a9d96261/transformed/appcompat-1.2.0/res/values/values.xml:2771:5-2794:25: AAPT: error: resource android:attr/textFontWeight not found.
         

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

Deprecated Gradle features were used in this build, making it incompatible with Gradle 8.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/7.0.2/userguide/command_line_interface.html#sec:command_line_warnings

BUILD FAILED in 19s
91 actionable tasks: 91 executed

Other settings/variables in “project structure”:

  • androidxActivityVersion : 1.2.0
  • androidxAppCompatVersion : 1.2.0
  • androidxCoordinatorLayoutVersion : 1.1.0
  • androidxCoreVersion : 1.3.2
  • androidxFragmentVersion : 1.3.0
  • junitVersion : 4.13.1
  • androidxJunitVersion : 1.1.2
  • androidxEspressoCoreVersion : 3.3.0
  • cordovaAndroidVersion : 7.0.0

ALso get 25 suggestions for “updates” in the project structure window
I tried them all one by one, but some causes extra/other errors as well;
so I removed the ./android directory and started over multiple times.

Again, as I am new to this I am not sure what other information to provide. Currently I have read many posts and tried out lots of different things people recommended, without any luck so far.

Any help is appreciated a lot

Remco

1 post - 1 participant

Read full topic

Capacitor mode

$
0
0

Hi,

is there a possibility to tell in capacitor app that is should use styles for iOS or android globally by setting mode as in cordova app?

Thanks

1 post - 1 participant

Read full topic

Ionic android app is not getting data

$
0
0

Hi guys, I need some advice, we are going to build android application with Ionic, we built our app, it worked well on web, but after building Android app we faced some issues.

In our android app we couldn’t get data.

This is store service code, components get data from store services behavior subjects .

import {EventEmitter, Injectable, NgZone} from '@angular/core';
import {ApiService} from './api.service';
import {BehaviorSubject} from 'rxjs';
import {Device} from './models/device';
import {GHReadingsCollection} from './models/gh-reading';
import {MeteoReadingsCollection} from './models/meteostation-reading';
import {Settings} from './models/settings';
import {GasIndicators} from './models/gas-indicators';

@Injectable({
  providedIn: 'root'
})
export class StoreService {
  public devices = new BehaviorSubject<Device[]>([]);
  public isGasOn = new BehaviorSubject<boolean>(false);
  public period = new BehaviorSubject<string>('-24h');
  public ghReadings = new BehaviorSubject<GHReadingsCollection>({});
  public meteoReadings = new BehaviorSubject<MeteoReadingsCollection>({});
  public settings = new BehaviorSubject<Settings>(null);
  public masterDevice = new BehaviorSubject<Device>(null);
  public gasIndicators = new BehaviorSubject<GasIndicators>(null);
  public mapGhReadings = new BehaviorSubject<GHReadingsCollection>({});

  public reloadStarted = new EventEmitter();
  public reloadEnded = new EventEmitter();
  public reloadCalled = new EventEmitter();

  constructor(private apiSvc: ApiService, private zone: NgZone) {
  }

  public async reload(period: string): Promise<void> {
    try {
      this.reloadStarted.emit();

      const devices = await this.apiSvc.getDevices();
      const ghReadings: GHReadingsCollection = await this.apiSvc.getGHReadingCollection(devices, period);
      const meteoReadings: MeteoReadingsCollection = await this.apiSvc.getMeteoReadingCollection(devices, period);
      const gasReading: GasIndicators = await this.apiSvc.getGasReading(period, 'now()');

      this.devices.next(devices);
      this.ghReadings.next(ghReadings);
      this.meteoReadings.next(meteoReadings);
      this.gasIndicators.next(gasReading);
      this.period.next(period);

      await this.reloadMapData(devices);
    } catch (e) {
      console.error(e);
    } finally {
      this.reloadEnded.emit();
    }
  }

  public async reloadSettings(): Promise<void> {
    const devices = await this.apiSvc.getDevices();
    for (const d of devices) {
      const setts: Settings = JSON.parse(d.settings);
      if (setts && setts.isMaster) {
        this.settings.next(setts);
        this.masterDevice.next(d);
        break;
      }
    }
  }

  public async reloadMapData(devices) {
    const mapGhReadings: GHReadingsCollection = await this.apiSvc.getGHReadingCollection(devices, '-15m');
    const mapMeteoReadings: MeteoReadingsCollection = await this.apiSvc.getMeteoReadingCollection(devices, '-15m');
    const isGasOn: boolean = this.apiSvc.getIsGasOn(mapMeteoReadings);

    this.mapGhReadings.next(mapGhReadings);
    this.isGasOn.next(isGasOn);
  }


}

After some research I found out we have to get data from Promise via .then() method in Ionic.
After implementing this idea I got devices data in Android app but not ghReadings, meteoReadings and gasIndicators.

This is our api service code, we get ghReadings, meteoReadings and gasIndicators with post methods.

import {Injectable} from '@angular/core';
import {HttpClient, HttpHeaders} from '@angular/common/http';
import {Device} from './models/device';
import {GHReading, GHReadingRequest, GHReadingsCollection} from './models/gh-reading';
import {MeteoReading, MeteoReadingRequest, MeteoReadingsCollection} from './models/meteostation-reading';
import {environment} from '../environments/environment';
import {ApiResponse} from './models/api-response';
import {GasIndicators, GasIndicatorsRequest} from './models/gas-indicators';

@Injectable({
  providedIn: 'root'
})
export class ApiService {
  public constructor(private http: HttpClient) {
  }

  public async getDevices(): Promise<Device[]> {
    const resp = await this.http.get<ApiResponse<Device[]>>(environment.buildUrl('user/devices')).toPromise();
    return resp.data;
  }

  public async getGHReadingCollection(devices: Device[], period): Promise<GHReadingsCollection> {
    const ghReadings: GHReadingsCollection = {};
    const interval = this.getIntervalByPeriod(period);
    for (const d of devices) {
      if (d.device_type === 'GH station') {
        ghReadings[d.serial_number] = await this.getGHReadings(d.serial_number, period, 'now()', interval);
      }
    }
    return ghReadings;
  }

  public async getMeteoReadingCollection(devices: Device[], period): Promise<MeteoReadingsCollection> {
    const meteoReadings: MeteoReadingsCollection = {};
    const interval = this.getIntervalByPeriod(period);
    for (const d of devices) {
      if (d.device_type === 'Meteostation') {
        meteoReadings[d.serial_number] = await this.getMeteoReadings(d.serial_number, period, 'now()', interval);
      }
    }
    return meteoReadings;
  }

  public getIsGasOn(readings: MeteoReadingsCollection): boolean {
    for (const d in readings) {
      const last = readings[d].length - 1;
      if (last > 0 && 'Gas' in readings[d][last]) {
        return readings[d][last].Gas === 1;
      }
    }
    return false;
  }

  public async getGHReadings(id: string, start: string, end: string, interval: string): Promise<GHReading[]> {
    const req: GHReadingRequest = {
      stationId: id,
      start,
      end,
      interval
    };

    const httpOptions = {
      headers: new HttpHeaders({
        // eslint-disable-next-line @typescript-eslint/naming-convention
        'Content-Type': 'application/json',
      })
    };
    const resp = await this.http.post<ApiResponse<GHReading[]>>(environment.buildUrl('influx/greenhouse'), req, httpOptions).toPromise();
    return resp.data;
  }

  public async getMeteoReadings(id: string, start: string, end: string, interval: string): Promise<MeteoReading[]> {
    const req: MeteoReadingRequest = {
      stationId: id,
      start,
      end,
      interval
    };

    const httpOptions = {
      headers: new HttpHeaders({
        // eslint-disable-next-line @typescript-eslint/naming-convention
        'Content-Type': 'application/json',
      })
    };
    // eslint-disable-next-line max-len
    const resp = await this.http.post<ApiResponse<MeteoReading[]>>(environment.buildUrl('influx/meteostation'), req, httpOptions).toPromise();
    return resp.data;
  }

  public async getGasReading(start: string, end: string): Promise<GasIndicators> {
    const req: GasIndicatorsRequest = {
      start: this.convertRelativeDateToAbsolute(start),
      end: this.convertRelativeDateToAbsolute(end)
    };

    const httpOptions = {
      headers: new HttpHeaders({
        // eslint-disable-next-line @typescript-eslint/naming-convention
        'Content-Type': 'application/json',
      })
    };
    const resp = await this.http.post<ApiResponse<GasIndicators>>(environment.buildUrl('influx/gas'), req, httpOptions).toPromise();
    return resp.data;
  }


  public async saveDeviceSettings(serialNumber: string, settings: string): Promise<{ success: boolean }> {
    const req = {
      // eslint-disable-next-line @typescript-eslint/naming-convention
      serial_number: serialNumber,
      settings
    };
    const httpOptions = {
      headers: new HttpHeaders({
        // eslint-disable-next-line @typescript-eslint/naming-convention
        'Content-Type': 'application/json',
      })
    };
    const resp = await this.http.post<{ success: boolean }>(environment.buildUrl('user/updateDeviceSettings'), req, httpOptions).toPromise();
    return resp;
  }

  private convertRelativeDateToAbsolute(d: string): string {
    let curDate = new Date();
    switch (d) {
      case '-3d':
        curDate = new Date((new Date()).getTime() - 1000 * 60 * 60 * 24 * 3);
        break;
      case '-24h':
        curDate = new Date((new Date()).getTime() - 1000 * 60 * 60 * 24);
        break;
      case '-12h':
        curDate = new Date((new Date()).getTime() - 1000 * 60 * 60 * 12);
        break;
      case '-6h':
        curDate = new Date((new Date()).getTime() - 1000 * 60 * 60 * 6);
        break;
      case '-3h':
        curDate = new Date((new Date()).getTime() - 1000 * 60 * 60 * 3);
        break;
    }

    return curDate.toISOString();
  }

  private getIntervalByPeriod(period: string): string {
    const intervalByPeriod = {
      '-3h': '15m',
      '-6h': '15m',
      '-12h': '30m',
      '-24h': '30m',
      '-3d': '1h'
    };

    return intervalByPeriod[period];
  }

}

Questions:

  1. Is getting and returning data as Promise good idea ? Or should we use Observables ? Does this have any effect on the performance of the android app ?
  2. What could be the reason of not getting data(ghReadings, meteoReadings and gasIndicators) on android app and how to fix it ?
  3. I found Ionic have its own http library , will using this library solve our issue ? do we have to use this library for our http requests to work well?

1 post - 1 participant

Read full topic

New project with capacitor wont sync

$
0
0

I created a fresh new project from the ionic cli. I added capacitor ios platform. When i run npx cap sync i get an error. I install cocoapods via brew on my m1 mac. I have tried to remove the ios platform and re add and i still get this issue. how can i fix this?

I also found this but it’s not working either.

1 post - 1 participant

Read full topic

Getting Firebase Analytics in Cordova for iOS

$
0
0

I’ve had a terrible time getting Firebase Analytics working in iOS, but I finally managed to get it to work on my Ionic v6 Angular App. I’m sure there are other people having these same issues so I’m going to explain the various issues I encountered and how I addressed them.

There are multiple modules that implement Firebase Analytics from the Ionic Community plugins. The main ones are Analytics-Firebase and Firebase-Analytics.

These two modules correspond to cordova-plugin-analytics and cordova-plugin-firebase-analytics. I tried both and could not get past running Capacitor sync with either one in a fresh Ionic Angular project that only had the standard Capacitor starter packages plus one of these two Firebase Analytics packages.

NOTE: When there is a dash in the name of Firebase-Analytics and Analytics-Firebase I’m referring to the module of that name and not to the name of the “Firebase Analytics” service itself. Yeah, this is horrible naming.

When pod install is run, you will see this error:

The ‘Pods-App’ target has transitive dependencies that include statically linked binaries: (/ios/App/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.xcframework)

To get around this, you need to edit the Podfile in the ios/App folder that is generated when you added ios as a Capacitor platform.

In that Podfile, change use_frameworks! to this:

use_frameworks! :linkage => :static

If you see the following error when you build your project in XCode there may be one more step.

Command CompileSwiftSources failed with a nonzero exit code

If you see this, also add this to your Podfile where it says # Add your Pods here

pod ‘Firebase/Analytics’

After this run:

ionic build
ionic cap sync

Then build your project in XCode. The build should complete if you’re using Firebase-Analytics. If you’re using Analytics-Firebase, there will be additional errors to resolve. You may find the following solutions helpful in this case.

https://github.com/appfeel/analytics-google/issues/21#issuecomment-530480604
https://github.com/apache/cordova-plugin-file-transfer/issues/258
https://stackoverflow.com/questions/63168114/firebase-analytics-setscreenname-deprecated

If the build completes, but Firebase Analytics still isn’t working or your app crashes immediately after loading, check your error messages. If you see something about it not being able to find GoogleService-Info.plist, see this solution:
https://stackoverflow.com/questions/45317777/could-not-find-a-valid-googleservice-info-plist-in-your-project

2 posts - 1 participant

Read full topic

Seconds column not showing in time picker (ionic v6)

$
0
0

Hi!

I’m trying to display hours, minutes and seconds (HH:mm:ss) using ion-datetime time picker, but the seconds (ss) column is missing.

Here is the code, I tried in two different ways

<div class="grid-item">
    <h2>Time 1</h2>
    <ion-datetime
        locale="fi-FI"
        presentation="time"
        value="00:00:00" 
        display-format="HH:mm:ss" 
        picker-format="HH:mm:ss">
      </ion-datetime>
</div>
<div class="grid-item">
    <h2>Time 2</h2>
    <ion-datetime
        locale="fi-FI"
        presentation="time"
        value="00:00:00" 
        displayFormat="HH:mm:ss" 
        pickerFormat="HH:mm:ss">
      </ion-datetime>
</div>

Here’s what it looks like
Screenshot from 2022-01-21 19-36-37

1 post - 1 participant

Read full topic

Inexplicable Error date-time ionic6

$
0
0

Hello,
I have this html code =>

 <ion-item class="input" lines="full">
              <ion-text>{{ birthDate.value }}</ion-text>
              <ion-button id="open-modal" fill="clear">
                <ion-icon name="calendar-outline" slot="icon-only"></ion-icon>
              </ion-button>
              <ion-modal trigger="open-modal">
                <ng-template>
                  <ion-datetime presentation="date" formControlName="birth_date">
                  </ion-datetime>
                </ng-template>
              </ion-modal>
            </ion-item>

but When I click on my modal I get this error =>

TypeError: Cannot destructure property 'month' of 'parseDate(...)' as it is undefined.
    at Datetime.valueChanged (ion-datetime_3.entry.js:1487:15)
    at index-06cd27b1.js:1534:29
    at Array.map (<anonymous>)
    at setValue (index-06cd27b1.js:1531:34)
    at HostElement.set [as value] (index-06cd27b1.js:1571:25)
    at SelectValueAccessorDirective.writeValue (ionic-angular.js:44:9)
    at onChange (forms.js:1734:1)
    at forms.js:2872:1
    at Array.forEach (<anonymous>)
    at FormControl.setValue (forms.js:2872:1)

I don’t know, where parseDate and month come from…

Do you have an idea please?.

Thanks

1 post - 1 participant

Read full topic


Ability to change individual keyboard key colors with Keyboard plugin?

$
0
0

From reviewing the docs for the package, nothing stood as a documented away change colors of individual keys on the keyboard. Is there anyway to do this with this plugin (or another)?

1 post - 1 participant

Read full topic

What are the changes between Ionic 5 and Ionic 6 that increase the minimum Safari version from 11 to 13?

$
0
0

As the title says, what are the changes between Ionic 5 and Ionic 6 that increase the minimum Safari version from 11 to 13?

I am building an Ionic app and have recently upgraded to v6, because reasons.
I am trying to support Safari down to around version 11.1.
What changes have been made that require Safari 13?
Can polyfills allow lower versions?

1 post - 1 participant

Read full topic

User-select with Ionic Refresh on the page

$
0
0

We noticed a little “bug” on iOS in regards to the combination of allowing the user to select text and having the IonRefresh component enabled.

If you’re at the top of the page and select text then start to drag, it’s very easy for it to also start pulling the page to initiate the IonRefresh component and causes the select box to jump all over the place. If I scroll down to where moving my thumb down doesn’t trigger the IonRefresh, selecting text works perfectly fine.

Does anybody have ideas on what we can do to avoid that? My first thought was giving the component a v-if="!selectingText()" but I guess Ionic is also not clearing the window selection when I tap off of selected text so that would just break the Refresh component as soon as you select any text.

Any ideas on what we can do? Short of removing the refresher from the pages?

1 post - 1 participant

Read full topic

Ionic photo gallery code not working

$
0
0

I am going over the photo gallery ionic app tutorial. I am at the part in which I am able to take photos, store them and when the page is refreshed, reload them. The problem is that when refreshing the page, the photo is not loaded. The picture blinks and goes away.

Here is the basic code

photo.service.ts

import { Injectable } from '@angular/core';
import { Camera, CameraResultType, CameraSource, Photo} from '@capacitor/camera';
import { Filesystem, Directory } from '@capacitor/filesystem';
import { Storage } from '@capacitor/storage';
@Injectable({
  providedIn: 'root'
})
export class PhotoService {

  public photos: UserPhoto[] = [];
  private PHOTO_STORAGE: string = 'photo';
  constructor() { }
  
  private async savePicture(photo: Photo){
    const base64Data = await this.readAsBase64(photo);
    const fileName = new Date().getTime() + '.jpeg';
    const savedFile = await Filesystem.writeFile({
        path: fileName,
        data: base64Data,
        directory: Directory.Data
    });

    return{
      filepath: fileName,
      webviewPath: photo.webPath
    }
  }
  
  private async readAsBase64(photo: Photo){
    const response = await fetch(photo.webPath!);
    const blob = await response.blob();

    return await this.convertBlobToBase64(blob) as string;
  }

  private convertBlobToBase64 = (blob: Blob) => new Promise((resolve, reject) => {
    const reader = new FileReader;
    reader.onerror = reject;
    reader.onload = () => {
        resolve(reader.result);
    };
    reader.readAsDataURL(blob);
  });

  public async addNewToGallery(){
    const capturedPhoto = await Camera.getPhoto({
      resultType: CameraResultType.Uri,
      source: CameraSource.Camera,
      quality: 100
    });

    const savedImageFile = await this.savePicture(capturedPhoto);
    this.photos.unshift(savedImageFile);
    Storage.set({
      key: this.PHOTO_STORAGE,
      value: JSON.stringify(this.photos),
    });
  }

  public async loadSaved(){
    const photoList = await Storage.get({key: this.PHOTO_STORAGE});
    this.photos = JSON.parse(photoList.value) || [];
    
    for(let photo of this.photos){
       const readFile = await Filesystem.readFile({
          path: photo.filepath,
          directory: Directory.Data
       }); 
       photo.webviewPath = 'data:image/jpeg;base64, ${readFile.data}';
    }
  }
}

export interface UserPhoto {
  filepath: string;
  webviewPath: string;
}

tab2.page.ts:

import { Component } from '@angular/core';
import { PhotoService } from '../services/photo.service';

@Component({
  selector: 'app-tab2',
  templateUrl: 'tab2.page.html',
  styleUrls: ['tab2.page.scss']
})
export class Tab2Page {

  constructor(public photoService: PhotoService) { }

  async ngOnInit(){
    await this.photoService.loadSaved();
  }

  addPhotoToGallery(){
    this.photoService.addNewToGallery();
  }

}

tab2.page.html:

<ion-header [translucent]="true">
  <ion-toolbar>
    <ion-title>
      Photo Gallery
    </ion-title>
  </ion-toolbar>
</ion-header>

<ion-content [fullscreen]="true">
  <ion-fab vertical="bottom" horizontal="center" slot="fixed">
    <ion-fab-button (click)="addPhotoToGallery()">
      <ion-icon name="camera"></ion-icon>
    </ion-fab-button>
  </ion-fab>
  <ion-grid>
     <ion-row>
       <ion-col size="6" *ngFor="let photo of photoService.photos; index as position">
          <ion-img [src]="photo.webviewPath"></ion-img>
       </ion-col>
     </ion-row>
  </ion-grid>
  <app-explore-container name="Tab 2 page"></app-explore-container>
</ion-content>

1 post - 1 participant

Read full topic

Conflict between ion-input "disabled" and ion-button

$
0
0

Using Ionic 6.0.1, I am trying to have an ion-item that contains both a disabled input and an enabled ion-button. However, adding the disabled flag to the input causes the button to be disabled (although its color remains as if enabled). (Removing disabled from the input, or replacing it with readonly makes the button work again.)

Here is the initial code where I discovered this effect:

      <ion-item>
        <ion-label position="floating">Email pending verification</ion-label>
        <ion-input [value]="user.email_to_be_verified" disabled></ion-input>
        <ion-button slot="end" (click)="saveAccount(true)">
          Cancel
        </ion-button>
      </ion-item>

Here is a refactor I tried, but the behavior was the same:

      <ion-item>
        <div style="display: flex; justify-content: space-between; width: 100%;">
          <div>
            <ion-label position="floating">Email pending verification</ion-label>
            <ion-input [value]="user.email_to_be_verified" disabled></ion-input>
          </div>
          <ion-button color="warning" (click)="saveAccount(true)" [disabled]="false">
            Cancel
          </ion-button>
        </div>
      </ion-item>

2 posts - 2 participants

Read full topic

Capacitor plugin Android Sunmi Pay SDK NFC

$
0
0

I need to create a custom capacitor plugin in order to connect an angular ionic app with native sdk. The app is going to run on a SUNMI P2 PRO POS, which doesn’t have support for builtin android nfc. The Sunmi uses its own SDK (Sunmi Pay SDK) to connect to the hardware, as the NFC module. I have never coded a capacitor plugin before neither an Android application in native Java code, so the logic here is all new, but I managed to get things rolling as for connection angular-plugin and connection to the PaySDK on App launch.
The problem now is to enable a “readMode” to read NFC cards (all I need at the moment is top receive the uuid of the card, so quite basic operation)
The SDK comes with some prepared functions, I followed the logic of the documentation (available on the SUNMI website) and used the checkCard() function, but the problem is that when the enableRead() of the plugin is called the checkCard function of the SDK seems to be exiting without executing anything or waiting for a card to be scanned with the sensor.
I thought that the problem could have been the capacitor call.resolve called right after the call to the sdk plugin, so I put the resolve inside the CheckCardCallback, but nothing really happens. Don’t know what to do, don’t know if it’s a problem with how Java handles async code or something different…

Below the java code (javascript code is only an async call to the plugin method, typical with Capacitor logic)

SunmiNfcPlugin.java


import com.getcapacitor.Plugin;
import com.getcapacitor.PluginCall;
import com.getcapacitor.PluginMethod;
import com.getcapacitor.annotation.CapacitorPlugin;
import com.getcapacitor.JSObject;

@CapacitorPlugin(name = "SunmiNfc")
public class SunmiNfcPlugin extends Plugin {

  private SunmiNfc implementation;

  @Override
  public void load() {
    implementation = new SunmiNfc(getActivity());
  }

  @PluginMethod()
  public void test(PluginCall call) {
    JSObject ret = new JSObject();
    String type = "Hello world!";
    ret.put("test", type);
    call.resolve(ret);
  }

  @PluginMethod()
  public void enableRFIDMode(PluginCall call) {
    JSObject ret = new JSObject();
    CardWrapper cardWrapper;
    this.implementation.checkRFIDCard(call);
    ret.put("sunminfc", "startedReadMode");
  }

  @PluginMethod()
  public void disableRFIDMode(PluginCall call) {
    this.implementation.cancelCheckRFIDCard();
    call.resolve(new JSObject());
  }

  @Override
  protected void handleOnDestroy() {
    super.handleOnDestroy();
    this.implementation.disconnectPayService();
  }
} 

SunmiNfc.java


import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

import androidx.appcompat.app.AppCompatActivity;

import com.getcapacitor.JSObject;
import com.getcapacitor.PluginCall;
import com.sunmi.pay.hardware.aidl.AidlConstants;
import com.sunmi.pay.hardware.aidlv2.AidlConstantsV2;
import com.sunmi.pay.hardware.aidlv2.emv.EMVOptV2;
import com.sunmi.pay.hardware.aidlv2.pinpad.PinPadOptV2;
import com.sunmi.pay.hardware.aidlv2.readcard.CheckCardCallbackV2;
import com.sunmi.pay.hardware.aidlv2.readcard.ReadCardOptV2;
import com.sunmi.pay.hardware.aidlv2.security.SecurityOptV2;
import com.sunmi.pay.hardware.aidlv2.system.BasicOptV2;

import plugins.SunmiNfc.utils.CheckCardCallbackV2Wrapper;
import sunmi.paylib.SunmiPayKernel;

public class SunmiNfc {
  private static final String TAG = "SunmiNfcPlugin";

  private SunmiPayKernel mSMPayKernel;
  private boolean isDisconnectService = true;

  public ReadCardOptV2 mReadCardOptV2;    // Read card module
  public EMVOptV2 mEMVOptV2;    // EMV operations API
  public PinPadOptV2 mPinPadOptV2;
  public BasicOptV2 mBasicOptV2;
  public SecurityOptV2 mSecurityOptV2;

  private AppCompatActivity activity;

  private PluginCall tmpCall;

  public SunmiNfc(AppCompatActivity activity) {
    this.activity = activity;
    connectPayService();
  }

  private void connectPayService() {
    mSMPayKernel = SunmiPayKernel.getInstance();
    mSMPayKernel.initPaySDK(activity.getApplicationContext(), mConnectCallback);
  }
  private SunmiPayKernel.ConnectCallback mConnectCallback = new SunmiPayKernel.ConnectCallback() {
    @Override
    public void onConnectPaySDK() {
      Log.d(TAG, "SUNMI Pay SDK Connected");
      try {
        mEMVOptV2 = mSMPayKernel.mEMVOptV2;
        mReadCardOptV2 = mSMPayKernel.mReadCardOptV2;
        mPinPadOptV2 = mSMPayKernel.mPinPadOptV2;
        mBasicOptV2 = mSMPayKernel.mBasicOptV2;
        mSecurityOptV2 = mSMPayKernel.mSecurityOptV2;
        isDisconnectService = false;
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
    @Override
    public void onDisconnectPaySDK() {
      Log.d(TAG, "SUNMI Pay SDK Disconnected");
      isDisconnectService = true;
    }
  };

  public void disconnectPayService() {
    this.mSMPayKernel.destroyPaySDK();
    mReadCardOptV2 = null;
    mEMVOptV2 = null;
    mPinPadOptV2 = null;
    mBasicOptV2 = null;
    mSecurityOptV2 = null;
    isDisconnectService = true;
  }

  // Control green Led function - 1 to activate, 0 to deactivate
  public void controlLed(int activate) {
    try {
      mBasicOptV2.ledStatusOnDeviceEx(1, (activate+1)&2, 1, 1);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  public void checkRFIDCard(PluginCall call) {
    try {
      int cardType = AidlConstants.CardType.NFC.getValue();
      controlLed(1);
      tmpCall = call;
      mReadCardOptV2.checkCard(cardType, mCheckCardCallback, 60);

    } catch (Exception e) {
      e.printStackTrace();
      call.reject("There was an error");
      tmpCall = null;
    }
  }

  public void cancelCheckRFIDCard() {
    try {
      mReadCardOptV2.cancelCheckCard();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  private CheckCardCallbackV2 mCheckCardCallback = new CheckCardCallbackV2Wrapper() {

    @Override
    public void findRFCard(String uuid) throws RemoteException {
      super.findRFCard(uuid);

      Log.i(TAG, "Type: NFC");
      Log.i(TAG, "findRFCard:" + uuid);

      JSObject ret = new JSObject();
      ret.put("uuid", uuid);
      tmpCall.resolve(ret);
      tmpCall = null;
    }
  };

}
 ```tion in detail and share your code, configuration, and other relevant info.

1 post - 1 participant

Read full topic

Best hair salon

$
0
0

Under the NYC skyline we are a hair salon specializing in hair weaving and hair extension services for all hair types. We offer our own patented 4 pc Hair Blending Systems which allows us to maximize time, eliminate the negative effects of extensions and keep our clients’ protective styles care needs first. Our Stylists are Designed to educate and change the way you normally choose your hair styles and products with our targeted brand formulas. We help you discover your unique hair regime with organic products based on hair texture and hair type. We are your ideal brand for our multicultural society.

1 post - 1 participant

Read full topic


Inspecting ios on linux

$
0
0

Does anyone have experience using ios webkit debug proxy for dev tools on linux (ubuntu specifically)? Or with the recent Inspect tool that replaced the old remove ios proxy for chrome? In Inspect all I see is “No debuggable apps found” even when I’m running my app. The app is a testflight build, signed with a distribution provisioning profile. Could that be the reason? Does it have to be signed with a development profile for me to be able to debug using these tools?

1 post - 1 participant

Read full topic

Interactive swipe to dismiss keyboard

Close a specific modal, is there a modal `id`?

$
0
0

Hi there,

how do we handle closing a specific modal in Ionic 5 and Vue?

I have seen some old answers mentioning a modal id property but I cannot find anything about it in the docs.

There is a dismiss() method on the modal instance but that would require having the modals globally available.

Before I implement my own solution, is the id property still available?

5 posts - 3 participants

Read full topic

IonContent shadowdom messing with codemirror 6 custom component styles

$
0
0

I am trying to insert a codemirror 6 component inside IonContent, but it completely messes with the codemirror styles because of the shadowdom used by IonContent.
Codemirror allows us to pass a root property where I can pass the IonContent shadow root, but I am not sure how I can get the ref for the parent IonContent.

<IonContent>
        <CodeMirrorEditor editorRoot={ // pass parent IonContent's shadowRoot ?? }/>
 </IonContent>

Any ideas how I can deal this this issue? thanks.

1 post - 1 participant

Read full topic

Navigation not working in aws amplify implementation

$
0
0

Create a project with ionic framework 6 + vue3. I am using Vue Router.
I deployed the application using AWS Amplify CLI, it was built well and it generated a url to access it. However the navigation does not work. Only path ‘/’ works. When entering the rest of the routes it shows me this message.

It appears to be a server routing issue. But I have no idea how to do that in aws amplify. I hope you can help me, thanks

2 posts - 2 participants

Read full topic

Viewing all 70904 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>