Jump to content

Leaderboard


Popular Content

Showing content with the highest reputation since 08/19/2019 in all areas

  1. 4 points
    lynkfs

    HTML programming

    A bit of a weird topic name for a product which elevates Object Pascal using javascript. I could have named it 'Web Components' (as I did a while ago) or maybe better 'Api Programming'. There are a number of organisations which look after the web api's. W3C is the most known one, but there are others looking after specific parts (WhatWG, Khronos etc.). What they have in common is that they publish the web api's they're looking after in a specific formal format (WebIDL). Smart has transformed these specifications in corresponding pascal classes, contained in the APIs directory in the RTL. These classes basically map directly onto functions and data available in the browser itself, and using them is sort of similar to for instance incorporating Microsoft Office functions in a Delphi program (although technically very different from using COM). The RTL uses some of these api's under the hood, this post is about a mini-rtl if you like consisting of just 1 component. I use this approach a lot for non-form based projects, single-page-apps (or multiple) and websites. Demo of a semi-static SPA The inheritance chain of the DOM looks like - EventTarget - Node - Element - HTMLElement with all the various html elements underneath : HTMLDivElement for a <div>, HTMLAnchorElement for a <a> etc. The code below wraps the HTMLElement, but allows its constructor to create any of the specialised sub-elements. unit JElement; interface uses W3C.HTML5, W3C.DOM, W3C.CSS; type THTMLElement = class private FHTMLElement: JHTMLElement; public constructor Create(element: String; parent: THTMLElement; className: String; innerHTML : String); end; implementation { THTMLElement } constructor THTMLElement.Create(element: String; parent: THTMLElement; className: String; innerHTML : String); begin // cache element and set innerHTML and className FHTMLElement := JHTMLElement(Document.createElement(element)); FHTMLElement.innerHTML := innerHTML; FHTMLElement.className := ClassName; If parent = nil then document.body.appendChild(FHTMLElement) else parent.FHTMLElement.appendchild(FHTMLElement); end; HTMLElements have as specifiers 'attributes' and 'properties'. Properties are any of the values in the 'style' attribute : in the html expression style="left=10px; color=white;" href="#" both 'left' and 'color' are properties, and both 'style' and 'href' are attributes. So we need to add the setters for these parameters : Procedure THTMLElement.SetProperty(s1: String; S2: String); begin var FElementStyle := JElementCSSInlineStyle(FHTMLElement).style; FElementStyle.setProperty(S1, S2); end; Procedure THTMLElement.SetAttribute(S1: String; S2: String); begin FHTMLElement.setAttribute(S1, S2); end; The first part of the demo app is an image, which fills the complete viewport on any device and orientation, a slightly darker tinted bar on top, and a button in the bar linking to an email form further down. This header can be constructed as per below : unit JHeader; interface uses JHTMLElement, smartcl.system; type THeader = class(THTMLElement) public constructor Create(props: Variant); end; implementation { THeader } constructor THeader.Create(props: Variant); begin //hero image var hdr0 := THTMLElement.Create('div', nil, 'div'); hdr0.setProperty('width', '100%'); hdr0.setProperty('height', '100%'); hdr0.setProperty('min-height', '100vh'); hdr0.setProperty('background-image','url('+props['header-img']+')'); hdr0.setProperty('background-size','cover'); //top bar 100px var hdr11 := THTMLElement.Create('div', hdr0, 'div'); hdr11.setProperty('width', '100%'); hdr11.setProperty('height', '100px'); hdr11.setProperty('background-color','rgb(21,21,21,0.2)'); //contact button var hdr21 := THTMLElement.Create('a', hdr11, 'div', 'Contact'); hdr21.SetBounds(20,30,75,35); hdr21.setProperty('color', 'white'); hdr21.SetAttribute('type', 'button'); hdr21.setAttribute('href', '#contact'); hdr21.SetProperty('background-color', 'rgb(21,21,21,0.2)'); which can be instantiated as in (with a variable for the image) //THeader props['header-img'] := 'assets/img/blueprint.jpg'; THeader.Create(props); and which on execution time resolves in <div class="div" style="width: 100%; height: 100%; min-height: 100vh; background-image: url(http://127.0.0.1:8090/assets/img/blueprint.jpg); background-size: cover;"> <div class="div" style="width: 100%; height: 100px;"> <a class="div" type="button" href="#contact" style="visibility: visible; display: inline-block; position: absolute; overflow: auto; left: 20px; top: 30px; width: 75px; height: 35px; color: white;"> Contact </a> </div> </div> Hence the title of this post : HTML programming. The advantage of this approach is that once there are a number of these multi-purpose constructs like THeader available, making up another webpage is as easy as providing values for constructor parameters and stringing them together. At some stage I created the constructs listed here They need to be updated and streamlined a bit.
  2. 3 points
    jarto

    Development updates

    New update available in the development-channel: RTL: Improvements to TW3ScrollBox: AutoUpdate-property. If true, the scrollbox monitors changes in child components and updates itself automatically. ForceParent-property. If true, child components are automatically moved to the Content-component. Bug fixes to ToggleSwitch: Did not work properly on Firefox Value of Checked-property changed only after the animation was completed Parent can now be changed, so components can be moved to different parents just like in Delphi Align: If multiple components have same alignment, decide order based on component coordinates Change w3_getPropertyAsInt to return 0 if value is NaN as NaN messes up any calculations using that value SmartCL.Effects: Animations like fxMove did not work in Firefox The changes to TW3ScrollBox lets you now use the ScrollBox also in the Visual Designer.
  3. 3 points
    jarto

    Creating a mobile app for Android and iOS

    Took some time, but I was able to create a test apk and install it on my phone. First of all, set up your folders the way I did in https://forums.smartmobilestudio.com/topic/4524-creating-a-mobile-app-for-android-and-ios/?do=findComment&comment=22461 That will let you have one folder for all the Phonegap-related stuff and another folder for your SMS app. Here's my config.xml, which should be in the phonegap-project's folder: <?xml version='1.0' encoding='utf-8'?> <widget id="com.smartmobilestudio.phonegaptest" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:gap="http://phonegap.com/ns/1.0"> <name>PhonegapTest</name> <description> Push sample application that receives push notifications. </description> <author email="youremail@example.com" href="https://www.smartmobilestudio.com"> Smart Mobile Studio </author> <preference name="phonegap-version" value="cli-9.0.0" /> <preference name="android-minSdkVersion" value="19" /> <preference name="android-targetSdkVersion" value="28" /> <content src="index.html" /> <preference name="DisallowOverscroll" value="true" /> <preference name="StatusBarOverlaysWebView" value="false" /> <preference name="StatusBarBackgroundColor" value="#ee6e73" /> <preference name="StatusBarStyle" value="blacktranslucent" /> <plugin name="com.ourcodeworld.plugins.Filebrowser" spec="https://github.com/ourcodeworld/cordova-ourcodeworld-filebrowser.git" /> <plugin name="cordova-plugin-geolocation" /> <plugin name="cordova-plugin-device" /> <plugin name="cordova-plugin-vibration" /> <plugin name="cordova-plugin-file" /> <plugin name="cordova-plugin-statusbar" source="npm" /> <plugin name="phonegap-plugin-push" source="npm" spec="~2.2.3" /> <plugin name="cordova-plugin-console" source="npm" /> <plugin name="cordova-plugin-dialogs" source="npm" /> <plugin name="cordova-plugin-whitelist" source="npm" /> <platform name="android"> <resource-file src="google-services.json" target="app/google-services.json" /> </platform> <platform name="android"> <icon density="ldpi" src="www/res/icon/android/drawable-ldpi-icon.png" /> <icon density="mdpi" src="www/res/icon/android/drawable-mdpi-icon.png" /> <icon density="hdpi" src="www/res/icon/android/drawable-hdpi-icon.png" /> <icon density="xhdpi" src="www/res/icon/android/drawable-xhdpi-icon.png" /> <icon density="xxhdpi" src="www/res/icon/android/drawable-xxhdpi-icon.png" /> <icon density="xxxhdpi" src="www/res/icon/android/drawable-xxxhdpi-icon.png" /> <splash density="land-ldpi" src="www/res/screen/android/drawable-land-ldpi-screen.png" /> <splash density="land-mdpi" src="www/res/screen/android/drawable-land-mdpi-screen.png" /> <splash density="land-hdpi" src="www/res/screen/android/drawable-land-hdpi-screen.png" /> <splash density="land-xhdpi" src="www/res/screen/android/drawable-land-xhdpi-screen.png" /> <splash density="land-xxhdpi" src="www/res/screen/android/drawable-land-xxhdpi-screen.png" /> <splash density="land-xxxhdpi" src="www/res/screen/android/drawable-land-xxxhdpi-screen.png" /> <splash density="port-ldpi" src="www/res/screen/android/drawable-port-ldpi-screen.png" /> <splash density="port-mdpi" src="www/res/screen/android/drawable-port-mdpi-screen.png" /> <splash density="port-hdpi" src="www/res/screen/android/drawable-port-hdpi-screen.png" /> <splash density="port-xhdpi" src="www/res/screen/android/drawable-port-xhdpi-screen.png" /> <splash density="port-xxhdpi" src="www/res/screen/android/drawable-port-xxhdpi-screen.png" /> <splash density="port-xxxhdpi" src="www/res/screen/android/drawable-port-xxxhdpi-screen.png" /> </platform> <platform name="ios"> <icon height="57" platform="ios" src="www/res/icon/ios/icon.png" width="57" /> <icon height="114" platform="ios" src="www/res/icon/ios/icon@2x.png" width="114" /> <icon height="40" platform="ios" src="www/res/icon/ios/icon-40.png" width="40" /> <icon height="80" platform="ios" src="www/res/icon/ios/icon-40@2x.png" width="80" /> <icon height="50" platform="ios" src="www/res/icon/ios/icon-50.png" width="50" /> <icon height="100" platform="ios" src="www/res/icon/ios/icon-50@2x.png" width="100" /> <icon height="60" platform="ios" src="www/res/icon/ios/icon-60.png" width="60" /> <icon height="120" platform="ios" src="www/res/icon/ios/icon-60@2x.png" width="120" /> <icon height="180" platform="ios" src="www/res/icon/ios/icon-60@3x.png" width="180" /> <icon height="72" platform="ios" src="www/res/icon/ios/icon-72.png" width="72" /> <icon height="144" platform="ios" src="www/res/icon/ios/icon-72@2x.png" width="144" /> <icon height="76" platform="ios" src="www/res/icon/ios/icon-76.png" width="76" /> <icon height="152" platform="ios" src="www/res/icon/ios/icon-76@2x.png" width="152" /> <icon height="29" platform="ios" src="www/res/icon/ios/icon-small.png" width="29" /> <icon height="58" platform="ios" src="www/res/icon/ios/icon-small@2x.png" width="58" /> <icon height="87" platform="ios" src="www/res/icon/ios/icon-small@3x.png" width="87" /> <splash height="1136" platform="ios" src="www/res/screen/ios/Default-568h@2x~iphone.png" width="640" /> <splash height="1334" platform="ios" src="www/res/screen/ios/Default-667h.png" width="750" /> <splash height="2208" platform="ios" src="www/res/screen/ios/Default-736h.png" width="1242" /> <splash height="1242" platform="ios" src="www/res/screen/ios/Default-Landscape-736h.png" width="2208" /> <splash height="1536" platform="ios" src="www/res/screen/ios/Default-Landscape@2x~ipad.png" width="2048" /> <splash height="768" platform="ios" src="www/res/screen/ios/Default-Landscape~ipad.png" width="1024" /> <splash height="2048" platform="ios" src="www/res/screen/ios/Default-Portrait@2x~ipad.png" width="1536" /> <splash height="1024" platform="ios" src="www/res/screen/ios/Default-Portrait~ipad.png" width="768" /> <splash height="960" platform="ios" src="www/res/screen/ios/Default@2x~iphone.png" width="640" /> <splash height="480" platform="ios" src="www/res/screen/ios/Default~iphone.png" width="320" /> </platform> <platform name="wp8"> <icon height="99" platform="wp8" src="www/res/icon/wp8/ApplicationIcon.png" width="99" /> <icon height="159" platform="wp8" src="www/res/icon/wp8/Background.png" width="159" /> <splash height="1280" platform="wp8" src="www/res/screen/wp8/screen-portrait.jpg" width="768" /> </platform> <platform name="windows"> <icon height="150" platform="windows" src="www/res/icon/windows/Square150x150Logo.scale-100.png" width="150" /> <icon height="30" platform="windows" src="www/res/icon/windows/Square30x30Logo.scale-100.png" width="30" /> <icon height="50" platform="windows" src="www/res/icon/windows/StoreLogo.scale-100.png" width="50" /> <splash height="300" platform="windows" src="www/res/screen/windows/SplashScreen.scale-100.png" width="620" /> <icon height="120" platform="windows" src="www/res/icon/windows/StoreLogo.scale-240.png" width="120" /> <icon height="44" platform="windows" src="www/res/icon/windows/Square44x44Logo.scale-100.png" width="44" /> <icon height="106" platform="windows" src="www/res/icon/windows/Square44x44Logo.scale-240.png" width="106" /> <icon height="70" platform="windows" src="www/res/icon/windows/Square70x70Logo.scale-100.png" width="70" /> <icon height="71" platform="windows" src="www/res/icon/windows/Square71x71Logo.scale-100.png" width="71" /> <icon height="170" platform="windows" src="www/res/icon/windows/Square71x71Logo.scale-240.png" width="170" /> <icon height="360" platform="windows" src="www/res/icon/windows/Square150x150Logo.scale-240.png" width="360" /> <icon height="310" platform="windows" src="www/res/icon/windows/Square310x310Logo.scale-100.png" width="310" /> <icon height="150" platform="windows" src="www/res/icon/windows/Wide310x150Logo.scale-100.png" width="310" /> <icon height="360" platform="windows" src="www/res/icon/windows/Wide310x150Logo.scale-240.png" width="744" /> <splash height="1920" platform="windows" src="www/res/screen/windows/SplashScreenPhone.scale-240.png" width="1152" /> </platform> <access origin="*" /> <allow-intent href="http://*/*" /> <allow-intent href="https://*/*" /> <allow-intent href="tel:*" /> <allow-intent href="sms:*" /> <allow-intent href="mailto:*" /> <allow-intent href="geo:*" /> <platform name="android"> <allow-intent href="market:*" /> </platform> <platform name="ios"> <allow-intent href="itms:*" /> <allow-intent href="itms-apps:*" /> </platform> </widget> You also have to register your app with FCM using the advice in the link that @lynkfsjust provided. Then download the google-services.json file and save it in the folder where your config.xml is. Lastly, when you are installing the apk on your phone, you may need to disable Play Protect in the Play Store. Here's the source code I'm currently using for testing. Note, that the parts that use the file dialogs is not pretty at all. You can simply ignore those parts and the FileBrowser-plugin when you make your own implementation. unit Form1; interface uses System.Types, System.Types.Convert, System.Objects, System.Time, System.json, SmartCL.System, SmartCL.Time, SmartCL.Graphics, SmartCL.Components, SmartCL.FileUtils, SmartCL.Forms, SmartCL.Fonts, SmartCL.Theme, SmartCL.Borders, SmartCL.Application, SmartCL.Controls.Button, SmartCL.Controls.Label, SmartCL.Controls.EditBox, PhoneGapApi, SmartCL.Controls.Memo, SmartCL.Controls.Image, System.Device.Storage, SmartCL.Device.Storage, System.IOUtils, System.Streams, System.Writer, SmartCL.Dialogs, SmartCL.Geolocation; type TForm1 = class(TW3Form) private {$I 'Form1:intf'} procedure AddToLog(const Value: String); procedure FileDialogError(data: Variant); procedure InitPushNotifications(Sender: TObject); procedure PhoneGapReady; procedure PushInitialized(data: Variant); procedure PushReceived(data: Variant); procedure PushError(data: Variant); procedure OpenSaveDialog(Sender: TObject); procedure SavePushToken(NewFileName: String); protected procedure InitializeForm; override; procedure InitializeObject; override; procedure Resize; override; end; implementation uses PGStripe; { TForm1 } procedure TForm1.AddToLog(const Value: String); begin LogMemo.Add(Value+#13#10); end; procedure TForm1.InitPushNotifications(Sender: TObject); begin var Id := SenderId.Text; PhoneGap.InitPushNotifications(Id, @PushInitialized, @PushReceived, @PushError); end; procedure TForm1.InitializeForm; begin inherited; AddToLog('Waiting for deviceready in PhoneGap'); SenderId.Enabled := False; InitPush.Enabled := False; SaveToken.Enabled := False; PhoneGap.OnReady(PhoneGapReady); end; procedure TForm1.InitializeObject; begin inherited; {$I 'Form1:impl'} end; procedure TForm1.PhoneGapReady; begin LogMemo.Clear; AddToLog('uuid: '+PhoneGap.Device.uuid); AddToLog('version: '+PhoneGap.Device.version); AddToLog('model: '+PhoneGap.Device.model); AddToLog('manufacturer: '+PhoneGap.Device.manufacturer); AddToLog('platform: '+PhoneGap.Device.platform); AddToLog('cordova: '+PhoneGap.Device.cordova); AddToLog('serial: '+PhoneGap.Device.serial); //Where are we? var GL:=TW3GeoLocation.Create; GL.OnPosition:=procedure (Sender: TObject; Position: TW3Position) begin AddToLog(''); AddToLog('Got position!'); AddToLog(' Time: '+FormatDateTime('dd.mm.yyyy hh:nn:ss.zzz',Position.Timestamp)); AddToLog(' Lat: '+Variant(Position.Coords.Latitude)); AddToLog(' Lng: '+Variant(Position.Coords.Longitude)); AddToLog(' Alt: '+Variant(Position.Coords.Altitude)); AddToLog(' Acc: '+Variant(Position.Coords.Accuracy)); AddToLog(' AltAcc: '+Variant(Position.Coords.AltitudeAccuracy)); AddToLog(' Head: '+Variant(Position.Coords.Heading)); AddToLog(' Speed: '+Variant(Position.Coords.Speed)); AddToLog(''); end; GL.OnPositionError:=procedure (Sender: TObject; Msg: TW3PositionError) begin AddToLog('Got an error'); AddToLog('Message: '+Msg.ErrorMessage); end; GL.QueryCurrentPosition; SenderId.Enabled := True; InitPush.Enabled := True; InitPush.OnClick := @InitPushNotifications; PhoneGap.Notification.vibrate(1000); end; procedure TForm1.PushInitialized(data: Variant); begin AddToLog('Push init ok'); AddToLog('Token: '+PhoneGap.RegistrationId); SenderId.Enabled := False; InitPush.Enabled := False; SaveToken.Enabled := True; SaveToken.OnClick := @OpenSaveDialog; end; procedure TForm1.PushReceived(data: Variant); begin AddToLog('Push: '+data.message); end; procedure TForm1.PushError(data: Variant); begin AddToLog('Push error: '+data.message); end; procedure TForm1.OpenSaveDialog(Sender: TObject); // Uses https://github.com/ourcodeworld/cordova-ourcodeworld-filebrowser procedure DoSave(data: Variant); begin SavePushToken(data); end; begin asm window.OurCodeWorld.Filebrowser.createFileDialog({ success: function(data) { @DoSave(data); }, error: function(data) { @FileDialogError(data); } }); end; end; procedure TForm1.FileDialogError(data: Variant); begin AddToLog("Error calling createFileDialog: "+data.message); end; procedure TForm1.SavePushToken(NewFileName: String); var NewFilePath: String; procedure fail(err: Variant); begin AddToLog('Error saving push notification token'); end; procedure FileWriterCreated(FileWriter: Variant); begin var TokenToWrite := PhoneGap.RegistrationId; asm FileWriter.onerror = @fail; FileWriter.write(@TokenToWrite); end; end; procedure FileCreated(fileEntry: Variant); begin AddToLog('File created'); asm fileEntry.createWriter(@FileWriterCreated); end; end; procedure onDirectorySuccess(dirEntry: Variant); begin AddToLog('Got directory access'); asm dirEntry.getFile(NewFileName, {create: true, exclusive: false}, @FileCreated, @fail); end; end; begin AddToLog('Saving push notification token'); //Split NewFileName to path and file for var a:=Length(NewFileName) downto 1 do if NewFileName[a]='/' then begin NewFilePath := copy(NewFileName,1,a); NewFileName := copy(NewFileName,a+1,Length(NewFileName)); break; end; asm window.resolveLocalFileSystemURL(@NewFilePath, @onDirectorySuccess); end; end; procedure TForm1.Resize; begin var h:=ClientHeight; if h=0 then exit; var w:=ClientWidth; SaveToken.SetBounds(0,h-40,w,40); dec(h,40); InitPush.SetBounds(0,h-40,w,40); dec(h,40); SenderId.SetBounds(0,h-32,w,32); dec(h,32); LogMemo.SetBounds(0,0,w,h); inherited; end; initialization Forms.RegisterForm({$I %FILE%}, TForm1); end.
  4. 2 points
    Hi all, as you have probably noticed, we've been a bit quiet lately. That's because we've been hard at work on exciting new changes and features to Smart Mobile Studio. I'd like to share with you, what we're doing to the Visual Designer. We're rewriting the Visual Designer from scratch. This new one is completely WYSIWYG as it's actually a Smart Mobile Studio app itself, running inside the IDE in Embedded Chrome. This lets us accurately show what components look like, instead of the dull old boxes in the old designer. You can set Align, Anchors, Angle and any other property and they are accurately reflected in the component in the Designer - like the blue panel (Align Top) or the rotated List box. The new designer also lets us support non-visual components, which will add a number of new components into our component palette. TW3Timer was the first one to be added and it already works just like in Delphi. We'll also be able to expand the concept into a full featured Multi Device Designer, so you could design forms for multiple devices, multiple screen sizes and multiple themes. The Designer also has support for Wizards and Component specific designers, so you'll be able to design popup menus in a Menu Designer and all the tabs in the Tab Control.
  5. 1 point
    It seems the good looking toggle switch component not working with the firefox desktop versions. Chrome, Opera, Brave no problem and even the Firefox Android also ok, just the desktop Firefox(32 and 64 bit version also, windows/Linux same wrong result). Probably inside the component the "checked:=not(checked)" procedure happening to fast. //anyway with this additional code the toggle switch component give a little bit better user experience procedure TForm1.W3ToggleSwitch1Click(Sender: TObject); begin W3ToggleSwitch1.checked:=not(W3ToggleSwitch1.checked) end;
  6. 1 point
    lynkfs

    Expand Combobox using code

    Basically the <select> element where the combobox is based on, is under control of the browser. And can't be manipulated from pascal/js. There is a hack (there is a hack for everything) to fake it : procedure TForm1.InitializeForm; begin inherited; // this is a good place to initialize components var W3ComboBox1 : Tw3ComboBox := TW3ComboBox.Create(self); W3ComboBox1.SetBounds(50,70,250,30); W3ComboBox1.Add('line 1'); W3ComboBox1.Add('line 2'); W3ComboBox1.Add('line 3'); W3ComboBox1.handle.style['opacity'] := 0; var W3Panel1 : TW3Panel := TW3Panel.Create(self); W3Panel1.SetBounds(50,70,250,30); W3Panel1.handle.style['z-index'] := 0; W3Panel1.handle.setAttribute('class',''); //get rid of all styling var W3Button1 : TW3Button := TW3Button.Create(W3Panel1); W3Button1.Caption := 'MyButton'; W3Button1.SetBounds(0,0,250,30); W3ComboBox1.OnChanged := procedure (Sender: TObject) begin W3Button1.Caption := W3ComboBox1.Items[W3ComboBox1.SelectedIndex]; end; end; works on Chrome and other browsers. Works on mobile too Demo Wouldn't recommend it though .... edited : as per @IElite suggestion: it would also be possible to make the combobox invisible, read its items on the click of a button and display them in a listbox or memo. Better, in my opinion and if really necessary, is to create a dedicated control which does exactly what you want, based on a listbox rather than on a <select> htmlelement
  7. 1 point
    lynkfs

    Creating a mobile app for Android and iOS

    This link is from feb 2019 (nasa related), so may work : https://www.jakenherman.com/articles/2019-02/push-notifi-cordova-firebase (there are more links as a result of googling 'cordova push notifications plugin 2019', which may be of relevance)
  8. 1 point
    jarto

    Creating a mobile app for Android and iOS

    I've been having a look at this today. Google Play changed their requirements for generated packages. Seems like Phonegap Build does not yet have an updated push notification plugin - or the old one is not compatible with Cordova 9.0.0, which is required by Google - or the way push notifications are handled in Android these days have changed. These are not specifically problems with Smart Mobile Studio itself as the same issues do happen with any html5-app. I hope I can crack this or that someone else can contribute. On the plus side, push notifications seem to work on phonegap's mobile test client, which is helpful.
  9. 1 point
    jarto

    Creating a mobile app for Android and iOS

    Yes, the push notifications are a great way for alerting users. I'll have a look to see if anything needs to be updated and upload the demo again.
  10. 1 point
    jarto

    Creating a mobile app for Android and iOS

    After writing that, I noticed that newer versions of iTunes do not install ipa-packages any more. To get around that, there are some ways: https://codeburst.io/latest-itunes-12-7-removed-the-apps-option-how-to-install-ipa-on-the-device-3c7d4a2bc788 I myself decided to use an older version of iTunes, that you can download from that page. That let me install the PhonegapTest.ipa, which I created in Phonegap build. And guess what? The app was installed in my iPad It started and initialized Phonegap properly I clicked on "Init push notifications", which registered itself properly and returned a Token What did not work: Saving the token as the plugin I had used for selecting the folder is strictly Android only However, there are many other plugins that you can use and there's no problem defining different plugins for Android and iOS in the config.xml -file. But basically, your Smart Mobile Studio app is now ready to receive push notifications on both Android and iOS.
×