Search code examples
javascriptandroidjsonnativescript

I can not get http request to work on android 10 api 29 or api 30. It does work with lower apis though


I'm writing an Android shopping app using the Telerik NativeScript platform. I need to get the client details for orders and deliveries, so I get them to register on the initial startup. The app works on APIs 17 up to API 28, I don't know what is stopping it from working on API 29 and API 30. If I can't get this to work, I will not get the sending of orders back to the web application to work either. The code:-

const Observable = require("tns-core-modules/data/observable").Observable;
const fs = require("tns-core-modules/file-system");
const formObject = require("tns-core-modules/data/observable").fromObject;
const http = require("tns-core-modules/http/");
const Toast = require("nativescript-toast");

const dirPath = fs.knownFolders.documents();
const folder = dirPath.getFolder('sot');

const m = {
 name: "",
 email: "",
 password: "",
 phone: "",
 address: ""
};

const bindingContext = formObject(m);

exports.onLoad = args => {
 const p = args.object;
 p.bindingContext = bindingContext;

 let txtfile = fs.path.join(dirPath.path, 'sot', 'sot.txt');
 let basketFile = fs.path.join(dirPath.path, 'sot', 'basket.txt');
 let exists = fs.File.exists(txtfile);

 if (exists === true) {
  exists = fs.File.exists(basketFile);
  if (exists === true) {
   p.page.frame.navigate('/store/store');
  }
 }

};

exports.tapped = args => {
 const p = args.object;
 const button = args.object;
 const page = button.page;

 let na = p.bindingContext.get('name');
 if (na === "") {
  alert("Please fill in your name");
  return;
 }

 let em = p.bindingContext.get('email');
 if (em === "") {
  alert("Please fill in your email address");
  return;
 }

 let pw = p.bindingContext.get('password');
 if (pw === "") {
  alert("Please supply a password");
  return;
 }

 let ph = p.bindingContext.get('phone');
 if (ph === "") {
  alert("Please fill in your phone number");
  return;
 }

 let ad = p.bindingContext.get('address');
 if (ph === "") {
  alert("Please fill in your address / suberb");
  return;
 }

 let jsonFragment = {
  "na": na,
  "em": em,
  "pw": pw,
  "ph": ph,
  "ad": ad
 };

  console.log('It stops here....');
  console.log(JSON.stringify(jsonFragment));

 http.request({
  url: "http://soapontap.co.za/php/insertMember.php",
  method: "POST",
  headers: {
   "Content-Type": "application/json"
  },

  content: JSON.stringify(jsonFragment)

 }).then(function (response) {

  console.log("done the database thing....");

  setTimeout(function () {
   let file = folder.getFile('sot.txt');
   let dataToWrite = JSON.stringify(jsonFragment);

   file.writeText(dataToWrite).
    then(function () {

     file = folder.getFile('basket.txt');
     file.writeText("")
      .then(() => {
       let toast = Toast.makeText("Welcome");
       toast.show();
       page.frame.navigate('/store/store');
      }, function (error) {
       console.log("Could not write to basket.txt");
      });

    }, function (error) {
     alert({
      title: "Error",
      message: 'Could not record the user on this local device.',
      okButtonText: "Close"
     });
    });

  }, function (e) {
   let toast = Toast.makeText("Error occurred " + e);
   toast.show();
  });
 }, 3000);

};

I have set permissions, here is the manifest:-

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="__PACKAGE__" android:versionCode="6" android:versionName="1.0.220720.1916">
 <supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true"/>
 <uses-permission android:name="android.permission.INTERNET"/>
 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
 <application android:name="com.tns.NativeScriptApplication" android:allowBackup="true" android:icon="@drawable/icon" android:label="@string/app_name" android:theme="@style/AppTheme">
  <activity android:name="com.tns.NativeScriptActivity" android:label="@string/title_activity_kimera" android:configChanges="keyboard|keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout|locale|uiMode" android:theme="@style/LaunchScreenTheme" android:screenOrientation="unspecified">
   <meta-data android:name="SET_THEME_ON_LAUNCH" android:resource="@style/AppTheme"/>
   <intent-filter>
    <action android:name="android.intent.action.MAIN"/>
    <category android:name="android.intent.category.LAUNCHER"/>
   </intent-filter>
  </activity>
  <activity android:name="com.tns.ErrorReportActivity"/>
 </application>
</manifest>

I have given the app permissions on the devices. Any help would be appreciated. Thanks.


Solution

  • The issue is with your URL of API.

    It is http://. Android 10 doesn't allow you to access external URLs which is not secured with https://.

    Now you have 2 solutions to overcome this issue:

    1. Install SSL on your web server domain to make it https:// (recommended)
    2. Add android:usesCleartextTraffic="true" in your manifest inside <application> tag

    NOTE: If you go for 2nd option and upload your signed APK to the play store it may get rejected due to security issues.