iOS Question Database encryption and Background service questions

Alex_197

Well-Known Member
Licensed User
Longtime User
Hi all.

For Android we are using SQLCipher. But what about iOS? Do we have something?
How to encrypt a SQLite database in b4i?

For Android we can use Starter to use background services, like a timer that works behind and checks if all activities are paused and if so - does something, for example redirects user to the login screen.

Can we do it in B4i?

Thanks.
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
There is no similar library in B4i however you can encrypt specific fields and store them as blobs.

For Android we can use Starter to use background services, like a timer that works behind and checks if all activities are paused and if so - does something, for example redirects user to the login screen.

Can we do it in B4i?
1. The specific case you describe is managed with Application_Background event.
2. iOS only allows very specific tasks to run in the background. For example: https://www.b4x.com/android/forum/threads/50246/#content
 
Upvote 0

Semen Matusovskiy

Well-Known Member
Licensed User
For Android we can use Starter to use background services, like a timer that works behind and checks if all activities are paused and if so - does something, for example redirects user to the login screen.

Background mode in IOS is very limited. Android 8+ seriously restricts background services also.

But, probably, you talk about some service operations which you want to execute in 'background', when app is activated.
When user simply types something, CPU usage is enough low. According my experiments on old iPhone 6s Plus, when I typed in TextView CPU usage was 25% maximum. When I stopped typing, CPU usage was about 1%.

To detect idle regime is enough simple, for example, - (void) doEvents { [self performSelector: @selector (_mysub) withObject: nil afterDelay: 0.0]; }
 
Upvote 0

Alex_197

Well-Known Member
Licensed User
Longtime User
Background mode in IOS is very limited. Android 8+ seriously restricts background services also.

But, probably, you talk about some service operations which you want to execute in 'background', when app is activated.
When user simply types something, CPU usage is enough low. According my experiments on old iPhone 6s Plus, when I typed in TextView CPU usage was 25% maximum. When I stopped typing, CPU usage was about 1%.

To detect idle regime is enough simple, for example, - (void) doEvents { [self performSelector: @selector (_mysub) withObject: nil afterDelay: 0.0]; }
What I'm talking about is a timer that works in background and calls the procedure that checks if all activities are paused.
And if so - starts a counter and when a counter riches 10 minutes (let say timer ticks every minute) redirects user to the login screen.

This is a code example from B4A

Timer:
#Region  Service Attributes
    #StartAtBoot: False
    #ExcludeFromLibrary: True 
#End Region

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
    Private Timer As Timer
    Private Counter As Int
    Public rp As RuntimePermissions
    Public PhoneEvent1 As PhoneEvents
End Sub

Sub Service_Create
    'This is the program entry point.
    'This is a good place to load resources that are not specific to a single activity.
  
    Dim jo As JavaObject
    jo.InitializeStatic("java.util.Locale").RunMethod("setDefault", Array(jo.GetField("US")))
  
    Timer.Initialize("Timer1",60000) 
    'PhoneEvent1.Initialize("PhoneEvent")
End Sub

Sub Service_Start (StartingIntent As Intent)
  
    Try
        Log("Service_Start")
        Service.StopAutomaticForeground 'Starter service can start in the foreground state in some edge cases.
        Timer.Enabled=True
      
    Catch
        Log("Service_Start " & LastException)
    End Try
  
End Sub

Sub Service_TaskRemoved
    'This event will be raised when the user removes the app from the recent apps list.
  
    Try
        Log("Service_TaskRemoved")
    Catch
        Log("Service_TaskRemoved " & LastException)
    End Try
  
End Sub

'Return true to allow the OS default exceptions handler to handle the uncaught exception.
Sub Application_Error (Error As Exception, StackTrace As String) As Boolean
    Log("Error=" & Error & " StackTrace=" & StackTrace )
    Return True
End Sub

Sub Service_Destroy
    Try     
        Timer.Enabled=False
        Log("Timer Stopped")
    Catch
        Log("Service_Destroy " & LastException)
    End Try


End Sub

private Sub RunCounter
  
    Try
      
        Dim IsP_Main As Boolean
        Dim IsP_ClientList As Boolean
        Dim IsP_ClockOut As Boolean
        Dim IsP_DashBoard As Boolean
        Dim IsP_Facility As Boolean
        Dim IsP_ModRegistration As Boolean
        Dim IsP_NurseNotesNew As Boolean
        Dim IsP_PA As Boolean
        'Dim IsP_NursesVoiceMessages As Boolean
        Dim IsP_PatiantDetails As Boolean
        Dim IsP_PlacementTaskNotes As Boolean
        Dim IsP_PlacementTasks As Boolean
        Dim IsP_SelectedClient As Boolean
        Dim IsP_VisitDetails As Boolean
        Dim IsP_Visits As Boolean
        'Dim IsP_VoiceMessage As Boolean
        Dim IsP_UnscheduledShifts As Boolean
        Dim IsP_UnscheduledClockIn As Boolean
        Dim IsP_NoteEdit As Boolean
        Dim IsP_HHANote As Boolean
        Dim IsP_UseCamera As Boolean
        Dim IsP_ViewPhoto As Boolean
        Dim IsP_EmeregencyMemo As Boolean
        Dim IsP_SendAll As Boolean
        Dim IsP_Legal As Boolean
        Dim IsP_TOS_Privacy As Boolean
      
        IsP_Main=IsPaused(Main)
        IsP_ClientList=IsPaused(ClientsList)
        IsP_ClockOut=IsPaused(ClockOut)
        IsP_DashBoard=IsPaused(DashBoard)
        IsP_Facility=IsPaused(Facility)
        IsP_ModRegistration=IsPaused(modRegistration)
        IsP_PatiantDetails=IsPaused(PatientDetails)
        IsP_PlacementTaskNotes=IsPaused(PlacementTaskNotes)
        IsP_PlacementTasks=IsPaused(HHATasks)
        IsP_SelectedClient=IsPaused(SelectedClient)
        IsP_VisitDetails=IsPaused(VisitDetails)
        IsP_Visits=IsPaused(Visits)
        IsP_NurseNotesNew=IsPaused(NurseNotesNew)
        IsP_PA=IsPaused(PA)
        IsP_UnscheduledShifts=IsPaused(UnscheduledShift)
        IsP_UnscheduledClockIn=IsPaused(UnscheduledClockIn)
        IsP_NoteEdit=IsPaused(NoteEdit)
        IsP_HHANote=IsPaused(HHANote)
        'IsP_UseCamera=IsPaused(UseCamera)
        IsP_UseCamera=IsPaused(SimpleCamera)
        IsP_ViewPhoto=IsPaused(ViewPhoto)     
        IsP_EmeregencyMemo=IsPaused(EmergencyMemo)
        IsP_SendAll=IsPaused(SendAll)
        IsP_Legal=IsPaused(Legal)
        IsP_TOS_Privacy=IsPaused(TOS_Privacy)
      
        If IsP_ClientList And IsP_ClockOut And IsP_DashBoard And IsP_Facility And IsP_Main And _
            IsP_ModRegistration And IsP_PatiantDetails And IsP_PlacementTaskNotes And IsP_PlacementTasks And _
            IsP_SelectedClient And IsP_NurseNotesNew And  IsP_VisitDetails And IsP_Visits _
            And IsP_UnscheduledShifts And IsP_PA And IsP_UnscheduledClockIn And IsP_NoteEdit And _
            IsP_HHANote And IsP_UseCamera And IsP_ViewPhoto And IsP_EmeregencyMemo And IsP_SendAll And _
            IsP_Legal And IsP_TOS_Privacy Then
          
            Counter = Counter + 1
          
            If Counter = 10 Then             
              
                Timer.Enabled=False
              
                Main.IsLogOut=True
              
                StartActivity(Main)
            End If
          
        Else
            Counter = 0
        End If
  
    Catch
        Log("RunCounter " & LastException)
    End Try
  
End Sub

Sub timer1_tick
  
    Try
        RunCounter
        Log("Counter=" & Counter)
    Catch
        Log("timer1_tick " & LastException)
    End Try
  
  
End Sub

So I want to know if it's b4i limitation we will try Xamarin or Swift but if it's iOs limitation - there is no reason to even get started.
This app has to be certified by the US Department of Health and if it's doesn't logged out user on inactivity it will never be certified.
 
Upvote 0

Semen Matusovskiy

Well-Known Member
Licensed User
If I understand correctly, you want do something like screen saver. You want to ask login/password
1) when app starts 2) when user switched to another app and activates your app again 3) when User does nothing in your app during for example 10 minutes. If so, to do this is very simple
 
Upvote 0

Alex_197

Well-Known Member
Licensed User
Longtime User
If I understand correctly, you want do something like screen saver. You want to ask login/password
1) when app starts 2) when user switched to another app and activates your app again 3) when User does nothing in your app during for example 10 minutes. If so, to do this is very simple
Yes, that's what I need.
 
Upvote 0

Semen Matusovskiy

Well-Known Member
Licensed User
A main part of your task is to detect idle time.
If to look stackoverflow, typically offer to calculate time since last screen touch (to subclass UIApplication and to override the sendEvent: method).
I like this idea in general, but:
1) I can't imagine how to subclass UIApplication inside B4i app.
2) Apple doesn't recommend to subclass UIApplication.

So, I used alternative idea in attached sample - to detect user's activity using events (such as Button_Click, TextField_BeginEdit etc).

The sample reacts, when user does nothing during 5 seconds. You can increase the interval (afterDelay) in [self performSelector: @selector (_loginagain) withObject: nil afterDelay: 5.0];
 

Attachments

  • Test.zip
    5.7 KB · Views: 205
Upvote 0

Semen Matusovskiy

Well-Known Member
Licensed User
Erel -
If you about 'resetIdleTimer' subroutine, I have no idea how to cancel previous request for Timer.
Meanwhile (as I understand) performSelector: ... afterDelay is the same timer.

My code is terrible, because better to 'subclass' in one place, not in events. Do you have alternative ideas how to detect idle mode ?
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
The OP talked in the first post about something different. He wanted to know when all "activities" are paused. The solution is simple and was provided multiple time. Use Application_Background.

For any other question, a new thread should be started.

Meanwhile (as I understand) performSelector: ... afterDelay is the same timer.
It is not the same timer and there is no reason to use such code instead of a timer. This is not helpful.
 
Upvote 0
Top