Dailycode.info

Short solution for short problems

iOS: Make your app react to connectivity change (iOS6)

* iOS7 see note at the end of this post first!

When you have an enterprise app, used for production follow up or something, were being online is crucial, connectivity loss or even a short fall out can bring frustrations and loss of data.

Using web services, the app will keep on working when there is no connection, simply throws errors when trying to fetch data or save data. To make the app more responsive, I build in a simple connectivity check so only offline functionality will be available.

To check if there is a WIFI or 3G connection, you can use the Reachability class given by Apple. I attached the file to this post: 

Reachability.h (3.63 kb)

Reachability.m (9.26 kb) 

You can also find it here: https://developer.apple.com/Library/ios/samplecode/Reachability/Introduction/Intro.html

Now once you added the Reachability.h and .m file to your project, you can simply use this code to check for connectivity:

Add this variable to your view controller:

 Reachability *reachability;

Then in the view load initialise it and add a notifier to it, so your app is notified when there is a change in the connectivity:

 reachability = [ReachabilityreachabilityForInternetConnection];

 [reachabilitystartNotifier];

    

 [[NSNotificationCenterdefaultCenter] addObserver:selfselector:@selector(reachabilityDidChange:) name:kReachabilityChangedNotificationobject:reachability];

Now when the connectivity changes, the reachabilityDidChange is called:

- (void)reachabilityDidChange:(NSNotification *)notification

{

    [selfCheckInfo];

    NetworkStatus status = [reachabilitycurrentReachabilityStatus];

    

    if(status == NotReachable)

    {

        self.colVwDashBoard.backgroundColor = [UIColorredColor];

    }

    else if (status == ReachableViaWiFi || status == ReachableViaWWAN)

    {

        self.colVwDashBoard.backgroundColor = [UIColorcolorWithRed:204.0/255.0green:204.0/255.0blue:204.0/255.0alpha:1];

    }

 

}

What I'm doing, is check if there is WIFI or 3G and if not, I will make the collection view background red, you could disable all functionality that needs connection.

In fact thats all there is. Easy right?

 

After upgrading to iOS 7 on some devices, this implementation was not properly working, so I switched to AFNetworking class, I will post the easy implementation soon on this blog, I'll try to find time to work out a small and clear example.

When connection is lost, background turns red and only the camera icon will respond to clicks:

 

 

 

When connection is back, the background turns gray again:


iPad: Using a relative cheap device to power your business

As relative new iOS developer, I'm really exited about the posibilities that an iPad offers. You can power all kinds of business with this device.

I'm working now in a production environment, where the forklift drivers now use an iPad to move material. They can even control a weigh scale and weigh material from their forklift chair.

This is a little preview of the dashboard:

We use a shared .Net layer to power the back-end system, and through WCF services, I cennect the iPad to this system. Reusing almost all functionality, it only takes a short while to build the GUI in Apple's xcode environment. Incoming inspection, material location, taking pictures of material and uploading it to the server, looking up order information etc. 

I'm bursting out of ideas, just no time yet to create them all. My latest small project is called WIEZER. It's an companion app with a very popular card game. It keeps score, helps you put in score and leaving little chance for mistakes. Also rules are just 1 click away. The app is almost ready for deploying in the app store, guess when I have the time, I'll put it there for free!

Here you see the same base dashboard control coming back:

Some more childrens games etc that need some finishing touches.

I see a market in the smallest of companies up until large international companies back down to the home users.


SAP: Adobe forms document not printing!

I'm deploying new invoices for several different countries, last week Poland started with invoicing and it went smooth. 

This week, they started to test in Germany. The output types were created, the preview was shown, but the direct print was not working. You could however print from the generated PDF using the windows printer. Offcourse this was not enough, because the automatic print was not working. So I started to look, first in code, then in configuration.

Finally I found that there were errors in the spool queueu of the printer. It looked like this:

If you look in detail it shows this:

So this got me going a little further. Eventually I looked at the printer spool request. When I try to edit it, it told me the the format of the spool request was not supported by the printer.

So the problem was found, the printer didn't support the G_RAW format. Now how to solve this. 

This was the easy part, you just look for a recent driver that supports this, in my case it was the ZHPP3005 : HP LJ P3005  R4.5+ device type that did the trick.

Spool request are now succesfully processed and printed out!


SAP: calculate invoice due date

I had a lot of trouble calculating the due date of the invoice. The main reason was because the payment term text had beside the date also some extra text like discount 2,000 %.

Eg. On day 19.01.2014 discount 2,000%

The way they implemented this was like this:

ln_due_date = vbdkr-zterm_tx1. 
CONCATENATE ln_due_date+4(4) ln_due_date+2(2) ln_due_date(2)     
 INTO ls_header-vervaldag.

And the result would be something like this: 20001420 in stead of 20140119

So the procedure was casting the text to a numeric field and when the discount was there, the date got messed up. A consultant then introduced the Procedure:

  CALL FUNCTION 'SD_PRINT_TERMS_OF_PAYMENT'

    EXPORTING

*      bldat                        = vbdkr-erdat

      budat                        = vbdkr-fkdat

      language                     = nast-spras

      terms_of_payment             = vbdkr-zterm

    TABLES

      top_text                     = lt_vtopis

    EXCEPTIONS

      terms_of_payment_not_in_t052 = 1

      OTHERS                       = 2.

  LOOP AT lt_vtopis INTO ls_vtopis.

    ln_due_date = ls_vtopis-hdatum.

  ENDLOOP.

But this procedure still had problems returning the correct date, even if I passed the ERDAT. 

So at last I altered the first procedure, just reading the ztermtext character by character and taking the first 8 numeric chars as date value:

DATA: textString TYPE string,

      dueDateText TYPE string,

      index TYPE i,

      counter TYPE i,

      length TYPE i,

      char  TYPE c,

      num   TYPE i.

textString = vbdkr-zterm_tx1.

 

length = STRLEN( textString ).

counter = 0.

WHILE index < length.

  char = textString+index(1).

  TRY .

      IF counter LT 8 AND char NE ' '.

        num = char.

        CONCATENATE dueDateText char

        INTO dueDateText.

        counter = counter + 1.

      ENDIF.

    CATCH cx_sy_conversion_no_number.

 

  ENDTRY.

  ADD 1 TO index.

ENDWHILE.

 

CONCATENATE dueDateText+4(4) dueDateText+2(2) dueDateText(2)

INTO ls_header-vervaldag.

 


SAP: outputparamas for printing properties

Component Component Type Data Type Length Short Description
DEVICE FPMEDIUM CHAR 8 Output device
NODIALOG FPNODIALOG CHAR 1 Suppress User Dialog
PREVIEW FPPREVIEW CHAR 1 Preview
GETPDF FPGETPDF CHAR 1 Request PDF Return
GETPDL FPGETPDL CHAR 1 Request PDL Return
GETXML FPGETXML CHAR 1 Get-Data-XML Request
CONNECTION RFCDEST CHAR 32 Logical Destination (Specified in Function Call)
ADSTRLEVEL FPADSTRL NUMC 2 Trace Level for Adobe Document Services
JOB_PROFILE FPJOBPROFILE STRING 0 Name of Job Profile
BUMODE FPBUMODE CHAR 1 Bundle Mode
ASSEMBLE FPASSEMBLE CHAR 1 Merge into one PDF document?
PARALLEL FPBOOLEAN CHAR 1 Data Type BOOLEAN
PDFVERSION FPPDFVERSION STRING 0 PDF Version
PDFTAGGED BOOLEAN CHAR 1 Boolean Variable (X=True, -=False, Space=Unknown)
PDFCHANGESRESTRICTED FPCHANGESRESTRICTED CHAR 1 Restricted Editing Options for PDF Document
.INCLUDE SFPPRIP   0 Form Processing: Print Parameters
DEST RSPOPNAME CHAR 4 Spool: Output device
REQNEW SYPRNEW CHAR 1 New Spool Request (Print Parameters)
REQIMM SYPRIMM CHAR 1 Print Immediately (Print Parameters)
REQDEL SYPRREL CHAR 1 Delete After Printing (Print Parameters)
REQFINAL RSPOFINAL CHAR 1 Spool request completed
SPOOLID RSPOID INT4 10 Spool request number
SENDDATE SKDATE DATS 8 Requested send date
SENDTIME SKTIME TIMS 6 Requested send time
SCHEDULE SKSCHEDULE CHAR 3 Send time request
COPIES FPCOPIES NUMC 3 Number of Copies
DATASET RSPO0NAME CHAR 6 Spool request: Name
SUFFIX1 RSPO1NAME CHAR 4 Spool request: Suffix 1
SUFFIX2 RSPO2NAME CHAR 12 Spool request: Suffix 2
COVTITLE SYPRTXT CHAR 68 Text for Cover Page (Print Parameters)
COVER SYPRSAP CHAR 1 Print: SAP cover page
RECEIVER SYPRREC CHAR 12 Recipient (Print Parameters)
DIVISION SYPRABT CHAR 12 Department on Cover Page (Print Parameters)
LIFETIME SYPEXPI NUMC 1 Spool Retention Period (Print Parameters)
AUTHORITY SYPRBER CHAR 12 Print: Authorization
RQPOSNAME RSPOPRNAME CHAR 50 Spool: Long name of printers for host spooler
PDLTYPE FPPDLTYPE CHAR 30 Printer Control Language
XDCNAME FPXDCNAME CHAR 51 XDC Name
NOPDF FPNOPDF CHAR 1 No PDF generation
SPONUMIV NRNR CHAR 2 Number range number
.INCLUDE SFPOUTARC   0 Form Processing: Options for Archiving
ARCMODE SYARMOD CHAR 1 Print: Archiving mode
NOARMCH FPNOARMCH CHAR 1 No Change of Archiving Mode
.INCLUDE SFPOUTBUT   0 Form Processing: Options for Dialog
TITLE FPTITLE CHAR 50 Title in dialog box
NOPREVIEW FPNOPREVIEW CHAR 1 No print preview
NOPRINT FPNOPRINT CHAR 1 No printing from print preview
NOARCHIVE FPNOARCHIVE CHAR 1 No archiving from print preview
IMMEXIT FPIMMEXIT CHAR 1 Exit Preview Immediately After Output
NOPRIBUTT FPNOPRIB CHAR 1 No Pushbuttons
.INCLUDE SFPXFPOPT   0 Options for XFP Output
XFP FPXFPACTIVE CHAR 1 XFP Output Activated
XFPTYPE FPXFPTYPE CHAR 1 XFP Variant
XFPOUTDEV RSPOPNAME CHAR 4 Spool: Output device

SAP: using PDF to print invoice uses wrong printer

I was looking at the configuration, but couldn't find any problems in NACE, SPRO or VV32.

So I took a deeper dive into the code and found this piece of code written by some guy before me:

fp_outputparams-dest          = 'LP01'.

So I changed this into this:

 IF NOT nast-ldest IS INITIAL.
    fp_outputparams-dest = nast-ldest.
  ELSE.
    fp_outputparams-dest          = 'LP01'.
  ENDIF.
Now it took the correct configured printer.
Here the complete printer code as it is now (the flag gv_e_invoice is used for sending the pdf via email, no printing!):
 
*&---------------------------------------------------------------------*
*& Get function for form processing
*&---------------------------------------------------------------------*
  SELECT SINGLE sform FROM tnapr
          INTO lv_formname
          WHERE nacha EQ nast-nacha
          AND kschl EQ nast-kschl.

  TRY.
      CALL FUNCTION 'FP_FUNCTION_MODULE_NAME'
        EXPORTING
          i_name           = lv_formname
        IMPORTING
          e_funcname       = ls_function
          e_interface_type = fp_interfacetype.
    CATCH cx_root INTO w_cx_root.
  ENDTRY.

*&---------------------------------------------------------------------*
*& Create the job with the selected output parameters
*&---------------------------------------------------------------------*

  IF gv_e_invoice EQ 'X'.
    fp_outputparams-preview       = 'X'.
    fp_outputparams-nodialog      = gv_e_invoice.

  ELSE.
    fp_outputparams-preview       = 'X'.
    fp_outputparams-nodialog      = 'X'.
    fp_outputparams-REQIMM        = 'X'.
  ENDIF.

  fp_outputparams-covtitle      = 'Invoice'.
  fp_outputparams-reqnew        = 'X'.
  fp_outputparams-reqfinal      = 'X'.

  IF NOT nast-ldest IS INITIAL.
    fp_outputparams-dest = nast-ldest.
  ELSE.
    fp_outputparams-dest          = 'LP01'.
  ENDIF.

  fp_outputparams-getpdf        = gv_e_invoice.


  CALL FUNCTION 'FP_JOB_OPEN'
    CHANGING
      ie_outputparams = fp_outputparams
    EXCEPTIONS
      cancel          = 1
      usage_error     = 2
      system_error    = 3
      internal_error  = 4
      OTHERS          = 5.
  IF sy-subrc <> 0.
    MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
    WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  ENDIF.
 

Devexpress 10: WPF GridControl - Show bound column in date time format

I took me a while to find, but at the end I got it.

The problem was when I start using Devexpress 10 (we’re in the process of buying the latest version, but not there yet) WPF GridControl, the datatime column only showed date.

Not a big deal, or so I thought. The first solution I found was to use the TextEditSettings. But that was in a differtent namespace. Therefore I had to add an assembly that I couldn’t find.

Eg. xmlns:dxe="clr-namespace:DevExpress.Wpf.Editors.Settings;assembly=DevExpress.Wpf.Editors.v9.1"

 

So I looked around but couldn’t find it. Too bad I thought and start looking further into the Template columns, but everywhere the binding failed. This because I work with DataSource of the grid, not the DataContext.

 Now at the end I found that I already had the assembly and it wasn’t DevExpress.Wpf. Just by adding this namespace in my xaml I could use the TextEditSettings:

xmlns:dxe="http://schemas.devexpress.com/winfx/2008/xaml/editors"

 

So now I just use this piece of code to show my desired format of the date:

<dxg:GridColumn Name="createdtest" Header="Erzellt" FieldName="Created">

<dxg:GridColumn.EditSettings>

             <dxe:TextEditSettings DisplayFormat="dd/MM/yyyy HH:MM" />

</dxg:GridColumn.EditSettings>

</dxg:GridColumn>

 

That’s al there is about it!

This is all the code for the GridControl:

<UserControl xmlns:dxg="http://schemas.devexpress.com/winfx/2008/xaml/grid" 

             xmlns:dxe="http://schemas.devexpress.com/winfx/2008/xaml/editors"

 

<dxg:GridControl DataSource="{Binding Path=SearchList}"  AutoPopulateColumns="False">

            <dxg:GridControl.Columns>

                <dxg:GridColumn Name="gridColumn1" Header="Kunde Nr." FieldName="Key2" ReadOnly="True"/>

                <dxg:GridColumn Name="gridColumn2" Header="Kunde Name" FieldName="Key3" ReadOnly="True" Width="500"/>

                <dxg:GridColumn Name="gridColumn3" Header="Mandant" FieldName="Key4" ReadOnly="True"/>

                <dxg:GridColumn Name="gridColumn4" Header="Kunde BW" FieldName="Key5" ReadOnly="True"/>

                <dxg:GridColumn Name="createdtest" Header="Erzellt" FieldName="Created">

                    <dxg:GridColumn.EditSettings>

                        <dxe:TextEditSettings DisplayFormat="dd/MM/yyyy HH:MM" />

                    </dxg:GridColumn.EditSettings>

                </dxg:GridColumn>

            </dxg:GridControl.Columns>

               

        </dxg:GridControl>

 

 

 

 


WPF - MVVM: Easy wait cursor implementation

Found a very good solution on StackOverflow.

Comes down to implementing a small class, better put it somewhere in your WPF framework or Shared library.

Call it like this:

UIHelper.SetBusyState();

The cursor will return to normal when the  application stops working.

 

Code:
using System;
using System.Windows.Input;
using System.Windows.Threading;

namespace Global.Wpf
{
    public static class UIHelper
    {
        /// <summary>
        ///   A value indicating whether the UI is currently busy
        /// </summary>
        private static bool IsBusy;

        /// <summary>
        /// Sets the busystate as busy.
        /// </summary>
        public static void SetBusyState()
        {
            SetBusyState(true);
        }

        /// <summary>
        /// Sets the busystate to busy or not busy.
        /// </summary>
        /// <param name="busy">if set to <c>true</c> the application is now busy.</param>
        private static void SetBusyState(bool busy)
        {
            if (busy != IsBusy)
            {
                IsBusy = busy;
                Mouse.OverrideCursor = busy ? Cursors.Wait : null;

                if (IsBusy)
                {
                    new DispatcherTimer(TimeSpan.FromSeconds(0), DispatcherPriority.ApplicationIdle, dispatcherTimer_Tick, System.Windows.Application.Current.Dispatcher);
                }
            }
        }

        /// <summary>
        /// Handles the Tick event of the dispatcherTimer control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private static void dispatcherTimer_Tick(object sender, EventArgs e)
        {
            var dispatcherTimer = sender as DispatcherTimer;
            if (dispatcherTimer != null)
            {
                SetBusyState(false);
                dispatcherTimer.Stop();
            }
        }
    }
}

iOS: easy using the Settings menu in your App

Here you can find a good tutorial:

http://useyourloaf.com/blog/2010/05/18/adding-a-settings-bundle-to-an-iphone-app.html

Comes down to this: Add a file -> Resource -> Settings Bundle

If you only have 1 level, add the settings to the root list. Mind the Identifier, for this is the identifier user later on in the program to get it.

The in your app you can simply address the UserDefaults with the identifier mentioned above:

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 
BOOL enabled = [defaults boolForKey:@"enableRotation"];