Android Question Persistent App

Discussion in 'Android Questions' started by ElliotHC, Aug 10, 2019.

  1. ElliotHC

    ElliotHC Active Member Licensed User

    I have an app which is using SMB and FTP which needs to carry on what it's doing in the background. Is this a simple command?

    Thanks
     
  2. Brandsum

    Brandsum Active Member Licensed User

    1. Move all your SMB and FTP code to a service
    2. Set service foreground to always (Service.AutomaticForegroundMode = Service.AUTOMATIC_FOREGROUND_ALWAYS). This will show a default style notification.
      OR
      Set service foreground to never (Service.AutomaticForegroundMode = Service.AUTOMATIC_FOREGROUND_NEVER) and create your own notification with NB6 and call Service.StartForeground
    3. Call Service.StopAutomaticForeground when you want to stop the service.
    4. You can add #StartAtBoot: True to start that service after a system reboot
     
    José J. Aguilar likes this.
  3. ElliotHC

    ElliotHC Active Member Licensed User

    :eek: I have a lot of subs in this project. It's basically some from the External Storage example, SMB and FTP.. I'm not sure exactly how I'd do that.
     
  4. Brandsum

    Brandsum Active Member Licensed User

  5. ElliotHC

    ElliotHC Active Member Licensed User

    upload_2019-8-10_18-50-34.png
    It doesn't seem to like the Listfiles sub which is also in the service I've created.
     
  6. Brandsum

    Brandsum Active Member Licensed User

    Maybe the declaration of the storage variable is incorrect that's why the IDE could not able to find ListFiles method. That you need to figure out. I have told you how you can communicate in the background and without activating the app.
     
  7. ElliotHC

    ElliotHC Active Member Licensed User

    I've literally just copied everything, perhaps there is an issue with it accessing the external storage?
     
  8. Brandsum

    Brandsum Active Member Licensed User

    show what you have copied. Upload the file.
     
  9. ElliotHC

    ElliotHC Active Member Licensed User

    Let me tidy up my project and I'll post it.
     
  10. ElliotHC

    ElliotHC Active Member Licensed User

    I'm not sure the best way about doing this..

    Basically, I need to use this project. https://www.b4x.com/android/forum/attachments/externalstorage-zip.76775/

    Select a folder.

    This is the bit that I can't seem to get to work..

    So up to now it's exactly that project above, no changes or additions. I need to have a timer running every say 1000ms which then loads the file names in to a list.. Sort the list! But I need that list built up and sorted running as a service.

    Easy to mod?
     
  11. Brandsum

    Brandsum Active Member Licensed User

    Did you try to run that project without any problem?
     
  12. Brandsum

    Brandsum Active Member Licensed User

    So basically you want to monitor a folder for file changes and if any file change detected you want to get notified?

    Then use this FileObserver Library
    https://www.b4x.com/android/forum/threads/fileobserver.16709/
     
    Last edited: Aug 10, 2019
  13. ElliotHC

    ElliotHC Active Member Licensed User

    Sorry, I don't think I explained it well. I can't seem to be able to get that example app to run a service that checks the file periodically on the external storage. I don't think it's possible.
     
  14. ElliotHC

    ElliotHC Active Member Licensed User

    I'm at first trying to move everything over in to the 'Main' as there is a separate module. After doing this I'll move the complete project in to a service and remove the listview in place of a list.

    Now that I've done that it doesn't like the storage element.

    I'm trying to upload the project but the uploader keeps telling me that the file is too large. It's 1.45Mb
     
  15. ElliotHC

    ElliotHC Active Member Licensed User

    Code:
    #Region  Project Attributes
        
    #ApplicationLabel: B4A Example External Storage Service
        
    #VersionCode: 1
        
    #VersionName:
        
    'SupportedOrientations possible values: unspecified, landscape or portrait.
        #SupportedOrientations: portrait
        
    #CanInstallToExternalStorage: False

    #End Region

    #Region  Activity Attributes
        
    #FullScreen: False
        
    #IncludeTitle: True
    #End Region

    #AdditionalJar: com.android.support:support-core-utils
    Sub Process_Globals
        
    Private Storage As ExternalStorage
        
    Private FoldersStack As List
        
    Private UpItem As ExternalFile
    End Sub

    Sub Globals
        
    'Private chkUsePreviouslySelected As CheckBox
        Private Previous As Boolean
        
    Private ListView1 As ListView ' Change this to a list
        Private ImageView1 As ImageView
        
    Private lblPath As Label
        
        
        
        
    '>>>>>>>>>>>>>>>>>>>>> Below is from Module
        Private ion As Object
        
    Private PersistantUri As String
        
    Private const FileName As String = "PersistantUri"
        
    Private ctxt As JavaObject
        
    Private mCallback As Object
        
    Private mEventName As String
        
    Public Root As ExternalFile
        
    Type ExternalFile (Name As String, Length As Long, LastModified As Long, IsFolder As Boolean, Native As JavaObject)
        
    '>>>>>>>>>>>>>>>>>>>>> Above is from Module
        
        
    End Sub

    Sub Activity_Create(FirstTime As Boolean)
        
    If FirstTime Then
            Storage.Initialize(
    "Storage")
            FoldersStack.Initialize
            UpItem.Initialize
        
    End If
        
    'Activity.LoadLayout("1")
        'chkUsePreviouslySelected.Checked = True
        Previous = True
        Storage.SelectDir(Previous)
        
    Wait For Storage_ExternalFolderAvailable
        FoldersStack.Clear
        EnterFolder(Storage.Root)
    End Sub

    '>>>>>>>>>>>>>>>>>>>>> Below is from Module
    Public Sub Initialize (Callback As Object, EventName As String)
        mCallback = Callback
        mEventName = EventName
        ctxt.InitializeContext
    End Sub
    '>>>>>>>>>>>>>>>>>>>>> Above is from Module

    Private Sub EnterFolder (folder As ExternalFile)
        FoldersStack.Add(folder)
        
    Dim sb As StringBuilder
        sb.Initialize
        
    For Each f As ExternalFile In FoldersStack
            
    If f = Storage.Root Then
                sb.Append(
    "Root")
            
    Else
                sb.Append(
    " / ").Append(f.Name)
            
    End If
        
    Next
        lblPath.Text = sb.ToString
        ListView1.Clear 
    ' Change this to a list
        
        
    If FoldersStack.Size > 1 Then
            ListView1.AddSingleLine2(
    "..", UpItem) ' Change this to a list
        End If
        
    For Each f As ExternalFile In Storage.ListFiles(folder)
            
    If f.IsFolder Then
                ListView1.AddSingleLine2(
    $"[${f.Name}]"$, f) ' Change this to a list
            Else If IsImageFile(f.Name) Then
                
    Dim cs As CSBuilder
                cs.Initialize.Append(f.Name).Append(
    " ").Color(0xFF00EEFF).Append("(click)").PopAll
                ListView1.AddSingleLine2(cs, f) 
    ' Change this to a list
            Else
                ListView1.AddSingleLine2(f.Name, f) 
    ' Change this to a list
            End If
        
    Next
    End Sub

    Private Sub ListView1_ItemClick (Position As Int, Value As Object)
        
    Dim f As ExternalFile = Value
        
    If f = UpItem Then
            
    'remove the current folder
            FoldersStack.RemoveAt(FoldersStack.Size - 1)
            
    'get the parent folder which is now the topmost folder
            Dim folder As ExternalFile = GetCurrentFolder
            
    'remove it and enter it again
            FoldersStack.RemoveAt(FoldersStack.Size - 1)
            EnterFolder(folder)
            
        
    Else
            
    'The ExternalFile returned from ListFiles cannot be used directly.
            'We need to first call FindFile.
            f = Storage.FindFile(GetCurrentFolder, f.Name)
            
    If f.IsFolder Then
                EnterFolder(f)
            
    Else If IsImageFile(f.Name) Then
                
    Dim in As InputStream = Storage.OpenInputStream(f)
                
    'We can open the image directly with Bitmap.Initialize2 however it will not allow us to use LoadBitmapResize
                'so instead we copy it to a temporary file.
                Dim out As OutputStream = File.OpenOutput(File.DirInternal, "temp"False)
                
    File.Copy2(in, out)
                out.Close
                ImageView1.SetBackgroundImage(LoadBitmapResize(
    File.DirInternal, "temp", ImageView1.Width, ImageView1.Height, True))
            
    End If
        
    End If
    End Sub

    Private Sub GetCurrentFolder As ExternalFile
        
    Return FoldersStack.Get(FoldersStack.Size - 1'get the last item
    End Sub


    Private Sub IsImageFile (Name As StringAs Boolean
        
    Dim n As String = Name.ToLowerCase
        
    For Each extension As String In Array(".jpg"".png"".gif"".bmp")
            
    If n.EndsWith(extension) Then Return True
        
    Next
        
    Return False
    End Sub


    Sub Activity_Resume

    End Sub

    Sub Activity_Pause (UserClosed As Boolean)

    End Sub


    '>>>>>>>>>>>>>>>>>>>>> Below is from Module
    'Lets the user pick a folder.
    'Optionally using the previous selected folder.
    Public Sub SelectDir (UsePreviouslySelectedIfAvaiable As Boolean)
        
    If UsePreviouslySelectedIfAvaiable And File.Exists(File.DirInternal, FileName) Then
            PersistantUri = 
    File.ReadString(File.DirInternal, FileName)
            
    Dim list As List = ctxt.RunMethodJO("getContentResolver"Null).RunMethod("getPersistedUriPermissions"Null)
            
    If list.IsInitialized Then
                
    For Each uripermission As JavaObject In list
                    
    Dim u As Uri = uripermission.RunMethod("getUri"Null)
                    
    Dim temp As Object = u
                    
    Dim s As String = temp
                    
    If s = PersistantUri And uripermission.RunMethod("isWritePermission"Null) = True Then
                        
    Log("Can use persistant uri!")
                        SetPickedDir
                        
    Return
                    
    End If
                
    Next
            
    End If
        
    End If
        
    Dim i As Intent
        i.Initialize(
    "android.intent.action.OPEN_DOCUMENT_TREE""")
        i.PutExtra(
    "android.content.extra.SHOW_ADVANCED"True)
        StartActivityForResult(i)
    End Sub

    'List all files in the given folder.
    Public Sub ListFiles (Folder As ExternalFile) As List
        
    Dim files() As Object = Folder.Native.RunMethod("listFiles"Null)
        
    Dim res As List
        res.Initialize
        
    For Each o As Object In files
            
    Dim f As JavaObject = o
            res.Add(DocumentFileToExternalFile(f))
        
    Next
        
    Return res
    End Sub
    'Finds the file with the given name.
    'Returns an uninitialized ExternalFile if not found.
    Public Sub FindFile (Parent As ExternalFile, Name As StringAs ExternalFile
        
    Dim f As JavaObject = Parent.Native.RunMethod("findFile"Array(Name))
        
    Return DocumentFileToExternalFile(f)
    End Sub

    'Creates a new file.
    Public Sub CreateNewFile (Parent As ExternalFile, Name As StringAs ExternalFile
        
    Return DocumentFileToExternalFile(Parent.Native.RunMethod("createFile"Array("", Name)))
    End Sub

    'Deletes the file.
    Public Sub DeleteFile (EF As ExternalFile) As Boolean
        
    If EF.IsInitialized = False Then Return False
        
    Return EF.Native.RunMethod("delete"Null)
    End Sub

    'Open an output stream that writes to the file.
    Public Sub OpenOutputStream(EF As ExternalFile) As OutputStream
        
    Return ctxt.RunMethodJO("getContentResolver"Null).RunMethod("openOutputStream"Array(EF.Native.RunMethod("getUri"Null)))
    End Sub
    'Open an input stream that reads from the file.
    Public Sub OpenInputStream(EF As ExternalFile) As InputStream
        
    Return ctxt.RunMethodJO("getContentResolver"Null).RunMethod("openInputStream"Array(EF.Native.RunMethod("getUri"Null)))
    End Sub

    'Finds the file with the given name. If not found creates a new file.
    Public Sub FindFileOrCreate (Parent As ExternalFile, Name As StringAs ExternalFile
        
    Dim f As ExternalFile = FindFile(Parent, Name)
        
    If f.IsInitialized = False Then
            
    Return CreateNewFile(Parent, Name)
        
    Else
            
    Return f
        
    End If
    End Sub


    Private Sub DocumentFileToExternalFile (DocumentFile As JavaObjectAs ExternalFile
        
    Dim ef As ExternalFile
        
    If DocumentFile.IsInitialized = False Then
            
    Return ef
        
    End If
        ef.Initialize
        ef.Name = DocumentFile.RunMethod(
    "getName"Null)
        ef.Length = DocumentFile.RunMethod(
    "length"Null)
        ef.IsFolder = DocumentFile.RunMethod(
    "isDirectory"Null)
        ef.Native = DocumentFile
        ef.LastModified = DocumentFile.RunMethod(
    "lastModified"Null)
        
    Return ef
    End Sub

    Private Sub SetPickedDir
        Root = DocumentFileToExternalFile(GetPickedDir(PersistantUri))
        CallSubDelayed(mCallback, mEventName & 
    "_ExternalFolderAvailable")
    End Sub

    Private Sub ion_Event (MethodName As String, Args() As Object) As Object
        
    If Args(0) = -1 Then 'resultCode = RESULT_OK
            Dim i As Intent = Args(1)
            
    Dim jo As JavaObject = i
            
    Dim treeUri As Uri = jo.RunMethod("getData"Null)
            
    Dim takeFlags As Int = Bit.And(i.Flags, 3)
            ctxt.RunMethodJO(
    "getContentResolver"Null).RunMethod("takePersistableUriPermission"Array(treeUri, takeFlags))
            
    Dim temp As Object = treeUri
            PersistantUri = temp
            
    File.WriteString(File.DirInternal, FileName, PersistantUri)
            
    Log(PersistantUri)
            SetPickedDir
        
    End If
        
    Return Null
    End Sub



    Private Sub GetPickedDir (uri As StringAs JavaObject
        
    Dim DocumentFileStatic As JavaObject
        
    Dim treeUri As Uri
        treeUri.Parse(
    uri)
        
    Dim PickedDir As JavaObject = DocumentFileStatic.InitializeStatic("android.support.v4.provider.DocumentFile").RunMethod("fromTreeUri"Array(ctxt, treeUri))
        
    Return PickedDir
    End Sub

    Private Sub StartActivityForResult(i As Intent)
        
    Dim jo As JavaObject = GetBA
        ion = jo.CreateEvent(
    "anywheresoftware.b4a.IOnActivityResult""ion"Null)
        jo.RunMethod(
    "startActivityForResult"Array As Object(ion, i))
    End Sub

    Private Sub GetBA As Object
        
    Dim jo As JavaObject = Me
        
    Return jo.RunMethod("getBA"Null)
    End Sub
    '>>>>>>>>>>>>>>>>>>>>> Above is from Module
     
  16. Brandsum

    Brandsum Active Member Licensed User

    Answer point wise,
    1. Did you copied external storage class code to main module? If yes then you are doing wrong.
    2. Did the original external storage example worked?
     
  17. ElliotHC

    ElliotHC Active Member Licensed User

    The original external storage app works just fine, the issue is that I really don't know how to make it run as a service.

    I can remove the interactions, I can put a timer, change listviews for lists..
     
  18. DonManfred

    DonManfred Expert Licensed User

    No, you can´t. The interactions are needed. The user must initially select the External SD. This can only be initiated from an Activity.
    Once you know the persistenturi you can store it and then use it to further interact with the SDCard.
     
    Brandsum likes this.
  19. ElliotHC

    ElliotHC Active Member Licensed User

    Ok, so how do I take that project and add in a service that every second, checks and puts the names of the files in that folder in a list? Is it even possible? It has to run in the background!
     
  20. Brandsum

    Brandsum Active Member Licensed User

    Why do you need the timer? Do you need the file name that will be created or deleted over time? A timer running every second to get file list and put them in listview will make your app consume more memory and unresponsive. Use fileobserver.
     
    ElliotHC likes this.
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