Android Question Loading a kmz file into Google Earth

Discussion in 'Android Questions' started by Kevin, Jul 15, 2018.

Tags:

Similar threads

Share My Creation KML Land
B4A Question Dialog box "Open with"
B4A Example GIF FILE - 3 x ROTATING EARTH
B4A Example TIP: Replace your Floats by Doubles
B4A Question Goggle Earth
  1. Kevin

    Kevin Well-Known Member Licensed User

    I wrote an app for my employer a while back and it has been working fine. I recently changed the manifest to target API 23 and added support for Runtime permissions and it continued to work as expected.

    My employer recently upgraded our company-provided cell phones and we went from the Galaxy S7 to the Galaxy S9. I forget which version of Android the S7 had been on when we switched over but it had obviously been updated several times over the years we had it.

    On the S9 now, we are running Android 8.0. Since changing over to the new phones though, one part of the app no longer works.

    We have KMZ files that show our pipeline map overlayed in Google Earth. On the new phones, the KMZ files get copied to an external folder properly but Google Earth fails to load them.

    I ran across the file provider tutorial and tried getting it to work that way but had no luck. I'm not even sure if that is where the problem lies or not.

    Is anyone familiar with how to properly open a KMZ file with Google Earth on the latest version of Android?

    Code:
    Sub CopyKMZ (sFN As StringAs Boolean
        
    Dim sFolder As String = File.DirDefaultExternal 'RTPerm.GetSafeDirDefaultExternal ("")
        
        
    If File.ExternalReadable = True Then
            
    If File.Exists (sFolder, sFN) = True Then Return True ' Already there
        End If
        
        
    If File.ExternalWritable = True Then
            
    Try
                
    File.Copy (File.DirAssets, sFN, sFolder, sFN)
                
    Return True
                    
    Catch
                        
    ToastMessageShow ("Failed to copy " & Chr(34) & sFN & Chr(34) & " to public folder.  Is the phone's storage full?"False)
                        
    Return False
            
    End Try
                
    Else ' Not writable
            ToastMessageShow ("Failed to copy " & Chr(34) & sFN & Chr(34) & " to public folder.  App needs permission to access external folder."True)
                    
    Return False
        
    End If
    End Sub

    Sub ShowAssetsinGE (iArea As Int)

        
    Dim sAreaFilename As String
        
    Select Case iArea
            
    Case 0
                sAreaFilename = 
    "Hammond.kmz"
            
    Case 1
                sAreaFilename = 
    "WoodRiver.kmz"
            
    Case 2
                sAreaFilename = 
    "Glenpool.kmz"
            
    Case 3
                sAreaFilename = 
    "Greenville.kmz"
            
    Case 4
                sAreaFilename = 
    "Arlington.kmz"
            
    Case 5
                sAreaFilename = 
    "Houston.kmz"
            
    Case 6
                sAreaFilename = 
    "PortArthur.kmz"
            
    Case 7
                
    Msgbox ("There are no pipeline assets associated with the Tulsa area."Application.LabelName)
                
    Return
        
    End Select
            
        RTPerm.CheckAndRequest (RTPerm.PERMISSION_WRITE_EXTERNAL_STORAGE)
        
    Wait for Activity_PermissionResult (Permission As String, Result As Boolean)
        
    If Result Then
            
    If CopyKMZ (sAreaFilename) = False Then
                
    Msgbox ("Unable to load the pipeline map into Google Earth because the file could not be copied." & CRLF & CRLF & "Is your device low on space?""Oops!")
                
    Return
            
    End If
            
    If File.ExternalReadable = False Then
                
    Msgbox ("Unable to load the pipeline map into Google Earth because the file could not be accessed.""Oops!")
                
    Return
            
    End If
            
    'Should be good regarding external storage
            Dim iIntent As Intent, sPackage As String
            
    Dim sFolder As String = File.DirDefaultExternal 'RTPerm.GetSafeDirDefaultExternal ("")
            iIntent.Initialize(iIntent.ACTION_VIEW, "file://" &  sFolder & "/" & sAreaFilename)
            sPackage = 
    "com.google.earth/.EarthActivity"
            iIntent.SetComponent(sPackage)
            
    Try
                
    ToastMessageShow ("Loading assets into Google Earth." & CRLF & "Please wait..."True):Sleep(0)
                
    StartActivity(iIntent)
                    
    Catch
                    
    If Msgbox2 ("Failed to start the Google Earth app." & CRLF & CRLF & "Would you like to try installing it now?""Uh-oh!""Yes""No"""Null) = DialogResponse.POSITIVE Then InstallApp (0)
            
    End Try
                
    Else
                
    Msgbox ("In order for this app to display pipeline assets in Google Earth, you must grant it permission to access files on your device so that the asset files can be copied to a storage location accessible by other apps.""Permission required!")
        
    End If
    End Sub
     
  2. DonManfred

    DonManfred Expert Licensed User

    you still did not understand how it work.
    replace the file:... part with the uri from the fileprovider

    Copy file
    Code:
    File.Copy(File.DirAssets, sFN, Starter.shared, sFN) ' copy your file here to thepath fileprovider is using
    Code:
    iIntent.Initialize(iIntent.ACTION_VIEW, CreateFileProviderUri(Starter.shared, sFN))
    Code:
    Sub CreateFileProviderUri (Dir As String, FileName As StringAs Object
        
    Dim FileProvider As JavaObject
        
    Dim context As JavaObject
        context.InitializeContext
        FileProvider.InitializeStatic(
    "android.support.v4.content.FileProvider")
        
    Dim f As JavaObject
        f.InitializeNewInstance(
    "java.io.File"Array(Dir, FileName))
        
    Return FileProvider.RunMethod("getUriForFile"Array(context, Application.PackageName & ".provider", f))
    End Sub
     
  3. Kevin

    Kevin Well-Known Member Licensed User

    I should have clarified that the code I posted was without the File Provider change. Not sure if it was even the correct path, I elected to post what used to work, hoping someone could suggest what needs to be changed.

    Below is using the File Provider option. It results in Google Earth crashing.

    Code:
    Sub CopyKMZ (sFN As StringAs Boolean
        
    Dim sFolder As String = RTPerm.GetSafeDirDefaultExternal ("maps"'File.DirDefaultExternal
        Log ("Copy KMZ to folder: " & sFolder)
        
        
    If File.ExternalReadable = True Then
            
    If File.Exists (sFolder, sFN) = True Then Return True ' Already there
        End If
        
        
    If File.ExternalWritable = True Then
            
    Try
                
    File.Copy (File.DirAssets, sFN, sFolder, sFN)
                
    Return True
                    
    Catch
                        
    ToastMessageShow ("Failed to copy " & Chr(34) & sFN & Chr(34) & " to public folder.  Is the phone's storage full?"False)
                        
    Return False
            
    End Try
                
    Else ' Not writable
            ToastMessageShow ("Failed to copy " & Chr(34) & sFN & Chr(34) & " to public folder.  App needs permission to access external folder."True)
                    
    Return False
        
    End If
    End Sub

    Sub ShowAssetsinGE (iArea As Int)

        
    Dim sAreaFilename As String
        
    Select Case iArea
            
    Case 0
                sAreaFilename = 
    "hammond.kmz"
            
    Case 1
                sAreaFilename = 
    "woodriver.kmz"
            
    Case 2
                sAreaFilename = 
    "glenpool.kmz"
            
    Case 3
                sAreaFilename = 
    "greenville.kmz"
            
    Case 4
                sAreaFilename = 
    "arlington.kmz"
            
    Case 5
                sAreaFilename = 
    "houston.kmz"
            
    Case 6
                sAreaFilename = 
    "portarthur.kmz"
            
    Case 7
                
    Msgbox ("There are no pipeline assets associated with the Tulsa area."Application.LabelName)
                
    Return
        
    End Select
            
    '    RTPerm.CheckAndRequest (RTPerm.PERMISSION_WRITE_EXTERNAL_STORAGE)
    '    Wait for Activity_PermissionResult (Permission As String, Result As Boolean)
    '    If Result Then
            If CopyKMZ (sAreaFilename) = False Then
                
    Msgbox ("Unable to load the pipeline map into Google Earth because the file could not be copied." & CRLF & CRLF & "Is your device low on space?""Oops!")
                
    Return
            
    End If
            
    If File.ExternalReadable = False Then
                
    Msgbox ("Unable to load the pipeline map into Google Earth because the file could not be accessed.""Oops!")
                
    Return
            
    End If
            
    'Should be good regarding external storage
            Dim iIntent As Intent, sPackage As String
            
    Dim sFolder As String = RTPerm.GetSafeDirDefaultExternal ("maps"'File.DirDefaultExternal
    '        iIntent.Initialize(iIntent.ACTION_VIEW, "file://" &  sFolder & "/" & sAreaFilename)

    '        iIntent.Initialize(iIntent.ACTION_VIEW, "")
    '        iIntent.SetType("text/plain") 'it is not related to the file itself.
    '        iIntent.PutExtra("android.intent.extra.STREAM",  CreateFileProviderUri(sFolder, sAreaFilename))
    '        sPackage = "com.google.earth/.EarthActivity"
    '        iIntent.SetComponent(sPackage)
            
        iIntent.Initialize(iIntent.ACTION_VIEW, CreateFileProviderUri(sFolder, sAreaFilename))

            
    Try
                
    'ToastMessageShow ("Loading assets into Google Earth." & CRLF & "Please wait...", True):Sleep(0)
                StartActivity(iIntent)
                    
    Catch
                    
    If Msgbox2 ("Failed to start the Google Earth app." & CRLF & CRLF & "Would you like to try installing it now?""Uh-oh!""Yes""No"""Null) = DialogResponse.POSITIVE Then InstallApp (0)
            
    End Try
    '            Else
    '            Msgbox ("In order for this app to display pipeline assets in Google Earth, you must grant it permission to access files on your device so that the asset files can be copied to a storage location accessible by other apps.", "Permission required!")
    '    End If
    End Sub

    Sub CreateFileProviderUri (Dir As String, FileName As StringAs Object
        
    Dim FileProvider As JavaObject
        
    Dim context As JavaObject
        context.InitializeContext
        FileProvider.InitializeStatic(
    "android.support.v4.content.FileProvider")
        
    Dim f As JavaObject
        f.InitializeNewInstance(
    "java.io.File"Array(Dir, FileName))
        
    Return FileProvider.RunMethod("getUriForFile"Array(context, Application.PackageName & ".provider", f))
    End Sub
    Manifest:
    Code:
    'This code will be applied to the manifest file during compilation.
    'You do not need to modify it in most cases.
    'See this link for for more information: http://www.basic4ppc.com/forum/showthread.php?p=78136
    ' For target, limit to 23 otherwise there doesn't seem to be a way to pass the KMZ files to GE!
    AddManifestText(
    <uses-sdk android:minSdkVersion=
    "16" android:targetSdkVersion="23"/>
    <uses-permission android:name=
    "com.android.launcher.permission.INSTALL_SHORTCUT"/>
    <supports-screens android:largeScreens=
    "true"
        android:normalScreens=
    "true"
        android:smallScreens=
    "true"
        android:anyDensity=
    "true"/>)
    SetApplicationAttribute(android:icon, 
    "@drawable/icon")
    SetApplicationAttribute(android:
    label"$LABEL$")
    'End of default text.

    SetApplicationAttribute(android:hardwareAccelerated, 
    "true")
    'SetActivityAttribute(Main, android:theme, "@style/MyFastScrollerTheme")

    'New for sharing KML with Google Earth
    AddManifestText(<uses-permission
        android:name=
    "android.permission.WRITE_EXTERNAL_STORAGE"
        android:maxSdkVersion=
    "18" />
    )

    AddApplicationText(
      <provider
      android:name=
    "android.support.v4.content.FileProvider"
      android:authorities=
    "$PACKAGE$.provider"
      android:exported=
    "false"
      android:grantUriPermissions=
    "true">
      <meta-data
      android:name=
    "android.support.FILE_PROVIDER_PATHS"
      android:resource=
    "@xml/provider_paths"/>
      </provider>
    )
    CreateResource(xml, provider_paths,
       <external-files-
    path name="name" path="maps" />
    )
     
  4. Kevin

    Kevin Well-Known Member Licensed User

    Well, I'm at a loss here. I don't know why using the File Provider URI crashes the Earth app but it does.

    Using the original method (the code in my original post) used to work fine, but something must have changed in Earth. When I pass the file that way, it shows up in "My Places" in the Earth app but the map overlay is not displayed. Even opening the KMZ file from a file explorer app launches Earth but with the same behavior - nothing happens, but it is listed in "My Places". Toggling visibility makes absolutely no difference at all. It wouldn't be the first time that Google broke something that used to work fine.

    For all I know, the Earth app crashing when using the File Provider URI may be a bug in Earth. Using the file sharing example that Erel posted works fine in that I can "share" the KMZ file with other apps (such as Email) but Earth isn't listed as a possible app to "share" the file to.
     
  5. Johan Hormaza

    Johan Hormaza Active Member Licensed User

    Change the file to .kml
     
  6. Kevin

    Kevin Well-Known Member Licensed User

    I tried that but it made no difference. They are definitely KMZs though anyway, as they are compressed.
     
  7. Marcob

    Marcob Member Licensed User

    I fixed my Google Earth crash issue by granting the read URI permission with:

    Code:
    iIntent.Flags = 1 'set FLAG_GRANT_READ_URI_PERMISSION
    before StartActivity(iIntent)

    I hope that helps.
     
  8. agraham

    agraham Expert Licensed User

    This is how I pass a KML file to AlpineQuest and Google Earth
    Code:
    Dim kml As String = "<?xml version='1.0' encoding='UTF-8'?>" & CRLF
       kml = kml & 
    "<kml xmlns='http://www.opengis.net/kml/2.2'>" & CRLF
       kml = kml & 
    "  <Document>" & CRLF
       kml = kml & 
    "    <name>" & KMLname & "</name>" & CRLF
       kml = kml & 
    "    <Placemark>" & CRLF
       kml = kml & 
    "      <name>" & KMLname & "</name>" & CRLF
       kml = kml & 
    "      <description>" & KMLgridRef & "</description>" & CRLF
       kml = kml & 
    "      <Point>" & CRLF
       kml = kml & 
    "        <coordinates>" & wgs84longitude & "," & wgs84latitude & ",0 </coordinates>" & CRLF
       kml = kml &  
    "      </Point>" & CRLF
       kml = kml & 
    "    </Placemark>" & CRLF
       kml = kml & 
    "  </Document>" & CRLF
       kml = kml & 
    "</kml>"
       
    ' AlpineQuest doesn't seem to like spaces in filenames when opened by FileProvider and throws a permission exception
       Dim Filename As String = KMLname.Replace(" ""_") & ".kml"
       
    File.WriteString(path, Filename, kml)

       Provider.SharedFolder = 
    File.DirRootExternal
       
    Dim intent1 As Intent
       intent1.Initialize(intent1.ACTION_VIEW, Provider.GetFileUri(
    "Download/" & Filename))
       intent1.SetType(
    "application/vnd.google-earth.kml+xml")
       intent1.Flags = 
    1 'FLAG_GRANT_READ_URI_PERMISSION
       StartActivity(intent1)
     
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