Android Question Activity freeze when service is working

Discussion in 'Android Questions' started by xcl, Mar 11, 2018.

  1. xcl

    xcl Member Licensed User

    Activity freeze when service is working

    Hi all...
    (sorry for my English)

    I have a some problem with user UI and service for sync.

    My project contains three module.
    - main activity module
    - starter service module
    - servece module (named "background") for sync with server via httpjob

    When activity is start i called (CallSubDelayed) sync procedure from Background.
    In sync procedure i call HttpJob.PostString
    JobDone rised in Background module and i work with data from server.
    Processing server data may take long time (5 - 100 seconds) and in this time my activity is freezed...

    The main reason for the long processing of data in my case - searching contact by phone number in user phonebook for name and photo.

    I assumed that the work of the service should not be reflected in the work of the activity
    But I can not do it work

    It is possible make it that service working do not freeze user UI?


    Simple variant of my code:

    Main:
    Code:
    #Region  Project Attributes
        
    #ApplicationLabel: syncTest
        
    #VersionCode: 1
        
    #VersionName: 1
        
    '#BridgeLogger: True
        'SupportedOrientations possible values: unspecified, landscape or portrait.
        #SupportedOrientations: portrait
        
    #CanInstallToExternalStorage: False
    #End Region

    Sub Activity_Create(FirstTime As Boolean)
       
        
    Activity.LoadLayout("main")
        
    Log("Started")
       
        CallSubDelayed(BackGround,
    "Sync")
    End Sub
    Starter
    Code:
    #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.
    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.
    End Sub

    Sub Service_Start (StartingIntent As Intent)

    End Sub

    Sub Service_TaskRemoved
        
    'This event will be raised when the user removes the app from the recent apps list.
    End Sub

    'Return true to allow the OS default exceptions handler to handle the uncaught exception.
    Sub Application_Error (Error As Exception, StackTrace As StringAs Boolean
        
    Return True
    End Sub

    Sub Service_Destroy

    End Sub

    Background:
    Code:
    #Region  Service Attributes
        
    #StartAtBoot: False
        
    '#StartCommandReturnValue: android.app.Service.START_STICKY
    #End Region

    Sub Process_Globals
        
    'These global variables will be declared once when the application starts.
        'These variables can be accessed from all modules.

    End Sub

    Sub Service_Create

    End Sub

    Sub Service_Start (StartingIntent As Intent)
        
    Log("Background service start...")
       
       
    '    Dim n As Notification
    '    n.Initialize
    '    n.Icon = "icon"
    '    n.SetInfo2("qwertyu", "gthjkl","for", Me)
    '    n.AutoCancel = True
    '    Service.StartForeground(1,n)
    '    Service.StopForeground(1)
       
    End Sub



    Sub Sync
        
    Dim job As HttpJob
        
    Dim jobPS As String
       
        job.Initialize(
    "GetPhoneList",Me)
        jobPS = job.PostString (
    "mytestserver.com/GetPhoneList, "user=user1")
    End Sub

    Sub Service_Destroy
        
    Log("Background destroy")
    End Sub

    Public Sub OnlyDigits(St As StringAs String
        St=St.Replace(
    "-","")
        St=St.Replace(
    ".","")
        St=St.Replace(
    "(","")
        St=St.Replace(
    ")","")
        St=St.Replace(
    "+","")
        St=St.Replace(
    " ","")
        
    Return St
    End Sub

    Public Sub GetContactsMap()
       
        
    Dim cu As ContactsUtils
        cu.Initialize
        
    Dim ac As List = cu.FindAllContacts(True)
       
        
    Dim Res As Map
        Res.Initialize
       
        Starter.ContactsMap.Initialize
       
        
    Dim Phones As List
        
    Dim dPh As String
        
    For Each Contact As cuContact In ac
            Phones = cu.GetPhones(
    Contact.Id)
            
    For Each Ph As cuPhone In Phones
                dPh = OnlyDigits(Ph.Number)
               
                Res.Put(
    "Name"Contact.DisplayName)
                
    Private Photo As Bitmap = cu.GetPhoto(Contact.id)
                
    If Photo.IsInitialized Then
                    Res.Put(
    "Photo", Photo)
                
    Else
                    Res.Put(
    "Photo"Null)
                
    End If
               
                Starter.ContactsMap.Put(dPh, Res)          
            
    Next
        
    Next                      
    End Sub

    Public Sub GetContactByPhone(Phone As StringAs Map
        
    Phone = OnlyDigits(Phone)
        
    Dim Res As Map
        Res.Initialize
       

        
    Dim cu As ContactsUtils
        cu.Initialize
        
    Dim ac As List = cu.FindAllContacts(True)
       
       
        
    Dim Phones As List
        
    Dim dPh As String
        
    For Each Contact As cuContact In ac
            Phones = cu.GetPhones(
    Contact.Id)
            
    For Each Ph As cuPhone In Phones
                dPh = OnlyDigits(Ph.Number)
                
    If dPh=Phone Then
                   
                    Res.Put(
    "Name"Contact.DisplayName)
                   
                    
    Private Photo As Bitmap = cu.GetPhoto(Contact.id)
                    
    If Photo.IsInitialized Then
                        Res.Put(
    "Photo", SaveImage(Photo))
                    
    End If
                
    End If
            
    Next
        
    Next
        
    Return Res
                           
    End Sub

    Sub JobDone (Job As HttpJob)
        
    Log("JobName = " & Job.JobName & ", Success = " & Job.Success)
        
    If Job.Success = True Then
            Job.GetString2(
    "utf-8")
            
    Log("Info:"&Job.GetString)
            
    Dim Answ As Map = GetMapFromString(Job.GetString,"#")
       
            
    For each PhoneNumber as String in Answ
                
    Contact = GetContactByPhone(PhoneNumber)
                                       
                
    If Contact.ContainsKey("Name"Then
                    
    Log(Contact.Get("Name"))
                
    End If
                
    If Contact.ContainsKey("Photo"Then
                    
    Log("Photo present...")
                
    End If
            
    Next  

        
    End if  
       
    End Sub

    The most time-consuming line: Phones = cu.GetPhones(Contact.Id)
    My phonebook contains more then 1200 contacts...
    But that's not the question.

    The question is: can the service and interface work in parallel?
    Or am I doing something wrong?


    Thanks...
     
    Last edited: Mar 11, 2018
  2. Erel

    Erel Administrator Staff Member Licensed User

    Service code runs on the main thread.

    Your code is extremely inefficient.

    You should use FindContactsByPhone. If you do need to get all contacts then do it once. Getting the information from the contacts store is a heavy operation.
     
  3. DonManfred

    DonManfred Expert Licensed User

    So for each number you are requestion a list of all contacts and then search the results for the number.
    With the next number you again requests a list of all contacts to do a search here. Does not sound efficient.

    Load the List of contacts once and then only iterate trough all of them in the search.

    Something like

    Code:
    Sub Process_Globals
        
    'These global variables will be declared once when the application starts.
        'These variables can be accessed from all modules.
        Private allcontacts As List
    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.
    End Sub
    Sub Service_Start (StartingIntent As Intent)
        allcontacts.Initialize
        InitContactslist
    End Sub

    Sub Service_Destroy

    End Sub
    Public Sub InitContactslist
        
    Log($"InitContactslist()"$)
        
    Dim cu As ContactsUtils
        cu.Initialize
        allcontacts = cu.FindAllContacts(
    True)
        
    Log($"Found Contacts: ${allcontacts.Size}"$)   
    End Sub
    And then, in your
    GetContactByPhone you do not read a new list. Just use the available list.
    also in your GetContactsMap you should use the list already available.
     
  4. xcl

    xcl Member Licensed User

    Thanks!

    That answer for my question...


    Yes, i known it, that made for example.
    In my real code i get contact map one time. But it still long operation...
    FindContactsByPhone - don't work with different phone format (+0(123)123-456, +123123456...),

    Thanks, but It's still long as my example, but is not a question :)

    I known how to optimize that code.

    But i want to make that background service will work in another thread and do not freeze UI.
    As I understand it - it's not possible in this way
     
  5. Erel

    Erel Administrator Staff Member Licensed User

    You can modify ContactsUtils and use QueryAsync instead of Query.
     
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice