Autor-Archiv Tobias Stephan

VonTobias Stephan

Cam Viewer for Flashforge 3D Printer

Deinen Flashforge 3D Drucker einfach mit dem Cam Viewer von eXODA überwachen.

…die App wird für IOS in Kürze verfügbar sein.

Monitor your Flashforge 3D printer easily with the Cam Viewer from eXODA.

…the app will be available for IOS soon.

https://youtu.be/x3sA6GcLZLY

VonTobias Stephan

Flashforge Adventurer 3 Camera Setup Streaming

Hier der Link für den Cam Stream. Den kannst Du nach abgeschlossener Konfiguration einfach in Deinem Browser eingeben

http://192.168.1.40:8080/?action=stream

Die IP Adresse 192.168.1.40 solltest Du natürlich durch die eigene ersetzen.
So bereitest Du Deinen Flashforge vor und ermittelst die richtige IP

VonTobias Stephan

Amazon trotz Kontensperre Kontakt zum Verkäuferservice

Hier der Link zum Formular

Wenn man sich als Verkäufer nicht mehr anmelden kann, hat ,am als Verkäufer bei Amazon ein echtes Problem. Auch mir ist das schon passiert, bei mir war es eine neue Kreditkarte – ein Klicken auf den Verkäuferservice war nicht möglich und die Eingabe der neuen Kreditkartennummer war nicht erfolgreiche. “Da schaut man dumm aus der Wäsche!” – Soeben habe ich im Sellercentral mehr zufällig einen frischen Link entdeckt und hoffe Kollegen damit helfen zu können. Es ist zwar keine Telefonnummer, aber immerhin ein Formular, mit dem man Kontakt aufnehmen kann. Selber

Kontakt zum Amazon Verkäuferservice, wenn sonst mal nichts mehr geht
VonTobias Stephan

SwiftUI Menue Button example Hamburger Menü

Bitteschön. Hier hast Du ein fertiges Sample für ein Swift UI Hamburger Menü. Das Menü lässt sich bequem mit per Slide ausblenden oder durch Tap auf das Hamburger Symbol einblenden. Lege einfach ein neues SwiftUI Projekt als Single App mit den Standardeinstellungen an. Übernimm alles einfach per Copy Paste und spiele am Projekt rum.

//
//  ContentView.swift
//  SlideMenuSwiftSample
//
//  Created by T. Stephan on 03.05.20.
//  Copyright © 2020 eCommerce - Tobias Stephan. All rights reserved.
//

import SwiftUI

struct ContentView: View {
    @State var showHamburgerMenu = false
    
    
    var body: some View {
        
        
        let drag = DragGesture()
            .onEnded {
                if $0.translation.width < -100 {
                    withAnimation {
                        self.showHamburgerMenu = false
                    }
                }
        }
        
        return NavigationView {
            GeometryReader { geometry in
                ZStack(alignment: .leading) {
                    MainView(showHamburgerMenu: self.$showHamburgerMenu)
                        .frame(width: geometry.size.width, height: geometry.size.height)
                        .offset(x: self.showHamburgerMenu ? geometry.size.width/2 : 0)
                        .disabled(self.showHamburgerMenu ? true : false)
                    
                    if self.showHamburgerMenu {
                        MenuView()
                            .frame(width: geometry.size.width/2)
                            .transition(.move(edge: .leading))
                    }
                }
                .gesture(drag)
                
            }
            .navigationBarTitle("Side Menu", displayMode: .inline)
            .navigationBarItems(leading: (
                Button(action: {
                    withAnimation {
                        self.showHamburgerMenu.toggle()
                    }
                }) {
                    Image(systemName: "line.horizontal.3")
                        .imageScale(.large)
                }
            ))
        }
        
    }
}

struct MainView: View {
    @Binding var showHamburgerMenu: Bool
    
    var body: some View {
        Button(action: {
            withAnimation {
                self.showHamburgerMenu = true
            }
        }) {
            Text("Show Menu")
        }
    }
}

struct MenuView: View {
    var body: some View {
        VStack(alignment: .leading) {
            HStack {
                Image(systemName: "person")
                    .foregroundColor(.gray)
                    .imageScale(.large)
                NavigationLink(destination: ProfileView()) {
                    Text("Profile")
                        .foregroundColor(.gray)
                        .font(.headline)
                }
            }
            .padding(.top, 100)
            HStack {
                Image(systemName: "envelope")
                    .foregroundColor(.gray)
                    .imageScale(.large)
                NavigationLink(destination: MessagesView()) {
                    Text("Messages")
                        .foregroundColor(.gray)
                        .font(.headline)
                }
            }
            .padding(.top, 30)
            HStack {
                Image(systemName: "gear")
                    .foregroundColor(.gray)
                    .imageScale(.large)
                NavigationLink(destination: SettingsView()) {
                    Text("Settings")
                        .foregroundColor(.gray)
                        .font(.headline)
                }
            }
            .padding(.top, 30)
            Spacer()
        }
        .padding()
        .frame(maxWidth: .infinity, alignment: .leading)
        .background(Color(red: 32/255, green: 32/255, blue: 32/255))
        .edgesIgnoringSafeArea(.all)
    }
}

struct SettingsView: View {
    var body: some View {
        VStack{
            Text("Settings Subview")
        }
    }
}
struct MessagesView: View {
    var body: some View {
        VStack{
            Text("Messages Subview")
        }
    }
}
struct ProfileView: View {
    var body: some View {
        VStack{
            Text("Profile Subview")
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

VonTobias Stephan

In App Käufe unter IOS realisieren

Dieser Beitrag gilt nur den kleinen Fallstricken. Apple prüft sehr genau und das ist ja auch sinnvoll. Die App selber muss zur Prüfung mit dem In App Kauf eingereicht werden. Du legst also vor einen In App Kauf fest. Der Zugriff auf die Daten des In App Kaufs ist erst nach Freigabe durch Apple möglich. Deshalb ist es sinnvoll die Prüfvorgang leicht und eindeutig für Apple zu gestalten.

Hier die Reihenfolge, in der ich vorgehe.
Wir gehen davon aus, dass die App bereits existiert und nun durch In-Kauf-Möglichkeiten ergänzt wird.

  • zuerst definiere ich die eigenen Termins of Use in den App Informationen (mehr dazu weiter unten)
  • dann Anlegen des ersten In-App-Kaufs
  • Lokalisierung bei der Abo-Gruppe nicht vergessen, sonst erscheint immer “Fehlende Metadaten”

Unter Features kannst Du einen neuen In-App-Kauf anlegen.

Beim Anlegen eines In-App-Kaufs sollte die Produkt-ID wie folgt aussehen.
com.eXODAIOSLIB.stephan.com.Listory.autoRenewSixmonth

also im Format:
com.eXODAIOSLIB.stephan.com.<Group>.<YourChoice>

Die Abo-Laufzeit nicht vergessen! In meinem Beispiel beträgt sie 6 Monate.

Danach muss eine Lokalisierung erstellt werden. Da ich meine Apps üblicherweise international anbiete, ist meine Standardsprache englisch. Dafür wähle ich dann English (USA). Lokalisierungen für weitere Länder erstelle ich erst später, wenn alles erfolgreich durch die Prüfung gelaufen ist.

Ebenso ist eine Lokalisierung für die Abo-Gruppe erforderlich. In eine Abo Gruppe kann man beispielsweise mehrere Autorenewable Angebote legen.

Das Promotional Image muss die Auflösung 1024 x 1024 Pixel haben und sollte kein Screenshot sein sowie die Information über den Kauf enthalten.
Bei dem Screenshot für die Prüfinformation erwartet Apple einen Screenshot, auf dem der Kaufvorgang zu erkennen ist. Das Prüfbild muss die Auflösung 640×920 haben! Es wird im App-Store nicht angezeigt.

Auto-Renewable Subscriptions sind eine besondere Herausforderung. Hier die Regeln mit Bespielen von Apple.

  • Unter Features den In-App Kauf anlegen
  • Dann alle Metadaten für den In-Kauf festlegen
  • Diesen In-App-Kauf in die Prüfung geben!
  • Dann eine neue Binärdatei hochladen.
  • abwarten, bis der In-App Kauf “Warten auf Prüfung”
  • im Status “Warten auf Prüfung” ist der In-App-Kauf für die Sandbox verfügbar
Übermitteln des In-App Kaufs
Beispiel Erfassungsansicht bearbeiten eines In-App Kaufs
Übermitteln des In-App-Kaufs mit einer neuen Version

Fallstricke:

Das folgende promotional Bild wurde abgelehnt, weil der Text schlecht lesbar ist.

Abgelehntes Bild wegen der schlechten Lesbarkeit

Das nun folgende Bild war dann erfolgreich.

Bei der Prüfung von Apple aktzeptiert

Apple fordert in der App auch einen Link für Terms & Conditions sowie die Privacy Policy. Hier ein Generator für beides.

In Deiner App muss auf die Terms of use und die Privacy Policy verlinkt werden. Zusätlich muss der Standard Apple Vertrag durch die eigenen Terms of use ersetzt werden.

Folgendes Feedback habe ich dazu von Apple bekommen. Das erhält man, wenn man es nicht richtig macht 😉

Guideline 3.1.2 – Business – Payments – Subscriptions

We noticed that your app did not fully meet the terms and conditions for auto-renewing subscriptions, as specified in Schedule 2, section 3.8(b) of the Paid Applications agreement.

When the user initiates an in-app purchase on the App Store, they are taken into your app to continue the transaction. 

However, information about the subscription must be displayed to the user prior to the purchase: 
• Title of publication or service
• Length of subscription (time period and content or services provided during each subscription period)
Price of subscription, and price per unit if appropriate

Your app must include links to your privacy policy and Terms of Use, and users should be able to access these links at any time.

Next Steps

To resolve this issue, please revise your app to include the missing information prior to initiating any auto-renewing subscription purchases within your app.

If you have no future plans on promoting this in-app purchase product, you can visit App Store Connect to delete the associated promotional image. 

To delete the promoted image: 

– Log in to App Store Connect
– Click on “My Apps”
– Select this app
– Click “Features,” then “App Store Promotions” to view your promoted in-app purchases 
– Click the in-app purchase reference name that you no longer want to promote 
– Select the associated promotional image and delete it 
– Click Save

Resources

To learn more about auto-renewing subscription requirements, please review Schedule 2, section 3.8(b) of the Paid Applications agreement in App Store Connect.

Hello Tobias,

We are writing to let you know the appeal results for your app, Listory Lister Shopping App.

The App Review Board evaluated your app and determined that the original rejection feedback is valid.

We continue to find that your app description to be displayed on the App Store does not currently include a link to your app’s terms of use. 

To resolve this issue, please revise your app description to include a link to your service’s terms of use. 

We encourage you to review the previous rejection correspondence for this app, make the necessary changes to bring it into compliance with the App Store Review Guidelines, and resubmit it for review.

Best regards,

Jan
App Review Board

Das Testen von In-App-Käufen geht durch Anlegen eines Sandbox User-Accounts. Wenn eine Autorenewable Subscription gekauft wird, gelten für die Sandbox folgene verkürzte Laufzeiten:

Actual DurationTest Duration
1 week3 minutes
1 month5 minutes
2 months10 minutes
3 months15 minutes
6 months30 minutes
1 year1 hour
Laufzeiten für die Sandbox-Käufe
VonTobias Stephan

Rebeloperstore 5 Kurzanleitung

Rebeloperstore ist eine fertige Bilbliothek für In-App-Käufe. Hier eine Kurzanleitung als Ergänzung zu den umfassenden Videos von Rebeloperstore.com

Den Ordner Rebeloperstore 5 dem Projekt hinzufügen.

Im Bereich In-App-Käufer unter App-Store muss der Kauf der jeweiligen App zugeordnet werden.

In der AppDelegate.swift den Eintrag RebeloperStore.start() vornehmen

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -&gt; Bool {
        // Override point for customization after application launch.
        RebeloperStore.start()
        return true
    }

Im File RebelopersotreSetup.swift die Anpassungen vornehmen.
Vor allem den App spezifischen Secret Key nicht vergessen.

//
//  RebeloperStoreSetup.swift
//  RebeloperStore5
//
//  Created by Alex Nagy on 31/07/2019.
//  Copyright © 2019 Alex Nagy. All rights reserved.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

import Foundation

extension RebeloperStore {
    
    // -----------------------------------------------------------------------------
    // First save your in-app purchase ids in App Store Connect like:
    //
    // com.yourCompany.yourApp.sufix
    //
    // ex: com.Rebeloper.RebeloperStore5Example.nonConsumable
    //     ^- Bundle Identifier                 ^- sufix
    //
    // IMPORTANT: in the Rebeloper Store code the "com.yourCompany.yourApp" part
    // is fetched from your Info.plist file Bundle Identifier.
    // To create a "RegisteredPurchase" you have to add only the sufix.
    //
    // Notes:
    // 1. In RegisteredPurchase "consumable" and "non-consumable" in-app purchases
    // are added as ".regular"
    //
    // 2. Image urls are optional. They can be:
    //  a). none -&gt; enter an emty String: ""
    //  b). in an asset catalog -&gt; enter the name / path of the image
    //  c). a url -&gt; enter the url of the image; has to be https!
    //
    // Now add your purchases below usig your in-app purchase sufixes.
    
    /*static let nonConsumable = RegisteredPurchase(imageUrl: "Icon-1024", sufix: "nonConsumable", purchaseType: .regular)
    static let consumable = RegisteredPurchase(imageUrl: "Icon-1024", sufix: "consumable", purchaseType: .regular)
    static let nonRenewing = RegisteredPurchase(imageUrl: "Icon-1024", sufix: "nonRenewing", purchaseType: .nonRenewing)
    static let autoRenewableWeekly = RegisteredPurchase(imageUrl: "Icon-1024", sufix: "autoRenewableWeekly", purchaseType: .autoRenewable)
    static let autoRenewableMonthly = RegisteredPurchase(imageUrl: "Icon-1024", sufix: "autoRenewableMonthly", purchaseType: .autoRenewable)*/
    static let WW1Year10Sites = RegisteredPurchase(imageUrl: "Icon-1024", sufix: "WW1Year10Sites", purchaseType: .autoRenewable)
    
    // -----------------------------------------------------------------------------
    // Create a list of your purchases if needed.
    // This can be useful if you're displaying them in a list.
    
    static var registeredPurchases: [RegisteredPurchase] = [
     /*   nonConsumable,
        consumable,
        nonRenewing,
        autoRenewableWeekly,
        autoRenewableMonthly,*/
        WW1Year10Sites

    ]
    
    // -----------------------------------------------------------------------------
    // If you're having auto-renewable in-app purchases
    // you must provide your app specific shared secret form App Store Connect.
    
    static let inAppPurchasesSharedSecret = "hier den Secret Key eintragen"
    
    // -----------------------------------------------------------------------------
    // When set to "true" you will find detailed logs in your console
    // when you're testing your in-app purchases.
    // Very usefull for debugging! Set it to "false" to turn it off.
    
    static let shouldLogRebeloperStore = true
}

Jeder In-App-Kauf muss angelegt werden. Der erste In-App-Kauf muss zur Prüfung übermittelt werden. Später können weitere ergänzt werden.

Wenn die In-App-Kauf den Status “Warten auf Prüfung” erhält, dann gilt es halt abzuwarten. Die Prüfung des In-App-Kaufs geschieht unabhängig von der Prüfung der App. Mein Vorgehen ist das veröffentlichen der App ohne weitere In-App-Käufe. Danach definiere ich diese und warte die Prüfung ab. Dann werden die einzelnen in der RebelopestoreSetup eingetragen. Im Status Bereit zur Übermittlung sind die ProductIDs auch schon aus dem XCode Projekt abrufbar.

    static var registeredPurchases: [RegisteredPurchase] = [
        autoRenewableYearly,
        autoRenewSixmonth
    ]

Diese Methode Lädt die In App Purchases in eine eigene Liste, die wiederum mit dem List SwiftUI gelistet werden kann.

   func loadinapppurchases(){
        // MARK:- Populate with in-app purchases
        self.ListOfInAppPurchases.removeAll()
        
        RebeloperStore.inAppPurchases.observeNext { (inAppPurchases) in
            
            //            self.ListOfInAppPurchases.append(contentsOf: inAppPurchases)
            
            
        }
        .dispose(in: RebeloperStore.inAppPurchases.bag)
        
        var iIndex = -1
        for obj in RebeloperStore.registeredPurchases {
            RebeloperStore.getInfo(obj.sufix) { (product) in
                guard let product = product,
                    let _ = product.localizedPrice else { return }
                iIndex += 1
                let oInAppPurchase = InAppPurchase(id: product.productIdentifier, imageUrl: obj.imageUrl, registeredPurchase: RebeloperStore.registeredPurchases[iIndex] , title: product.localizedTitle, description: product.localizedDescription, price: product.localizedPrice!)
                self.ListOfInAppPurchases.append(oInAppPurchase)
            }
            
        }
    }
VonTobias Stephan

XCode Podfile erstellen

Um ein Podfile zu erstellen öffnen wir zuerst ein Terminal Fenster.

Man befindet sich ohnehin nach dem Öffnen des Terminalfensters im persönlichen User Verzeichnis. Wechsele nun in den Projektordner Deines XCode Projects. Das kannst Du auch ganz einfach bewerkstelligen, indem Du zu allererst im Terminalfenster mit dem Befehl CD beginnst und dann in XCode auf den Projektnamen klickst, und per Drag & Drop den Namen in das Terminalfenster ziehst.

…nun den Befehl:

pod init

eingeben und mit Return abschliessen.

Das war es, Dein Podfile ist nun angelegt. Wenn Du Dich nicht im richtigen Verzeichnis befunden hast, erhältst Du eine entsprechende Fehlermeldung, dann solltest Du den Pfad überprüfen.

Wenn das erfolgreich war, führe den Befehl

pod install

im selben Ordner aus.

Nach ebenfalls erfolgreichem Installationsverlauf, wurde eine Workspace-Datei erstellt.

Wir erhalten den Hinweis das Projekt künftig über die Appname.xcworkspace Datei zu öffnen.

Das wars!

Um ein Podfile zu bearbeiten, gib in Deinem Terminalfenster folgenden Befehl ein:

open -a TextEdit Podfile
VonTobias Stephan

Dremel Bosch Service Deutschland

Manchmal ist es ja schwierig die richtigen Kontaktinformationen herauszufinden. Der Service funktioniert grundsätzlich bei Dremel recht gut, es kann aber manchmal auch etwas dauern.

Telefon:
0800 8590216


Wenn das Gerät bereits in der Reparatur ist, gilt folgende Rufnummer:
071140040400
bei der Bandsage die 2 drücken

Mailadresse:
Dremel Service dremel.service@de.bosch.com

Wie man an der Mailadresse erkennt, steckt Bosch dahinter, also wundere Dich nicht. Da ich selber mehrere Drucker von Dremel einsetze und das sehr intensiv, stosse auch ich immer wieder an Grenzen. Wenn ich selber nicht reparieren kann, rufe ich nicht an, sondern schreibe eine Mail. Innerhalb von 1 – 3 Tagen gibt es eine Antwort. Bosch schickt bei Bedarf auch vorab das benötigte Verpackungsmaterial, GLS holt den Drucker dann nach Terminvereinbarung ab.

Einsendeadresse:
Robert Bosch GmbH
Max-Lang-Str. 40-46 
70771 Leinfelden-Echterdingen 

VonTobias Stephan

Kabelshop App für Leckerstecker Kabel

Der Leckerstecker Shop hat jetzt auch eine Kabel App!

Die Kabelshop App haben wir extra entwickelt, um unseren Kunden das Auffinden des passenden Kabels zu erleichtern. Alle Kabel im Leckerstecker Kabelshop sind fertig vorkonfektioniert und deshalb schnell lieferbar.