Android Tutorial ABWearOS Library 1.0

Discussion in 'Tutorials & Examples' started by alwaysbusy, Oct 8, 2018.

  1. alwaysbusy

    alwaysbusy Expert Licensed User

    Download library here: https://www.b4x.com/android/forum/threads/abwearos-library-1-0.98036/

    This library requires B4A 8.50+

    This library should implement the new datalayer Google Api to send and sync data on Wear and uses the latest Google Play services (SDK 28)

    I tried to convert the older API @barx wrote, however there were a lot of changes so in the end, the two libraries are not compatible. In many ways, the new API is actually a lot simpler.

    I have not been able to test everything of this library. A lot is tested because I used in in an app I wrote, but the e.g. Channel Api has not. Report back (with example code if possible) if problems should come up.

    The library doc:
    ABWearOS
    Author:
    Alain Bailleul
    Version: 1
    • ABWearOSDataMap
      Methods:
      • Size As int
        Returns the number of Key-Value pairs currently in the DataMap
      • PutByte (Key As java.lang.String, Val As byte) As void
        Adds a Byte data item to the DataMap

        Key - a key used to reference the data item
        Val - the value to set to.
      • Remove (Key As java.lang.String) As void
        Removes an item from the DataMap with the given Key
      • IsInitialized As boolean
      • Initialize (ba As anywheresoftware.b4a.BA) As void
        Initializes the object.
        No Eventname is required. The DataLayer Eventname is used.
      • GetFloat (Key As java.lang.String) As float
        Gets a Float data item from the DataMap

        Key - The reference as set in in the PutFloat() method
      • Clear As void
        Clears all previously added data items from the DataMap
      • PutAsset (Key As java.lang.String, Asset As com.google.android.gms.wearable.Asset) As void
        Adds an Asset data item to the DataMap

        Key - a key used to reference the data item
        Asset - the Asset object to pass.
      • GetLongArray (Key As java.lang.String) As long[]
        Gets a Long Array data item from the DataMap

        Key - The reference as set in in the PutLongArray() method
      • GetByteArray (Key As java.lang.String) As byte[]
        Gets a Byte Array data item from the DataMap

        Key - The reference as set in in the PutByteArray() method
      • PutByteArray (Key As java.lang.String, Val As byte[]) As void
        Adds a Byte Array data item to the DataMap

        Key - a key used to reference the data item
        Val - the value to set to.
      • PutDouble (Key As java.lang.String, Val As double) As void
        Adds a Double data item to the DataMap

        Key - a key used to reference the data item
        Val - the value to set to.
      • GetStringArray (Key As java.lang.String) As java.lang.String[]
        Gets a StringArray data item from the DataMap

        Key - The reference as set in in the PutStringArray method
      • GetAsset (Key As java.lang.String) As com.google.android.gms.wearable.Asset
        Gets an Asset data item from the DataMap

        Key - The reference as set in in the PutAsset() method
      • GetDouble (Key As java.lang.String) As double
        Gets a Double data item from the DataMap

        Key - The reference as set in in the PutDouble() method
      • GetBoolean (Key As java.lang.String) As java.lang.Boolean
        Gets a Boolean data item from the DataMap

        Key - The reference as set in in the PutBoolean() method
      • GetByte (Key As java.lang.String) As byte
        Gets a Byte data item from the DataMap

        Key - The reference as set in in the PutByte() method
      • GetLong (Key As java.lang.String) As long
        Gets a Long data item from the DataMap

        Key - The reference as set in in the PutLong() method
      • isEmpty As boolean
        Return True if the DataMap is currently empty
      • PutInt (Key As java.lang.String, Val As int) As void
        Adds an Int data item to the DataMap.

        Key - a key use to reference the data item
        Val - the value to set to.
      • PutLong (Key As java.lang.String, Val As long) As void
        Adds a Long data item to the DataMap

        Key - a key used to reference the data item
        Val - the value to set to.
      • ContainsKey (Key As java.lang.String) As boolean
        Checks if the given key is contained in the DataMap.

        Returns True if the key is present
      • GetFloatArray (Key As java.lang.String) As float[]
        Gets a Float Array data item from the DataMap

        Key - The reference as set in in the PutFloatArray() method
      • PutBoolean (Key As java.lang.String, Val As java.lang.Boolean) As void
        Adds a Boolean data item to the DataMap

        Key - a key used to reference the data item
        Val - the value to set to.
      • PutLongArray (Key As java.lang.String, Val As long[]) As void
        Adds a Long Array data item to the DataMap

        Key - a key used to reference the data item
        Val - the value to set to.
      • GetInt (Key As java.lang.String) As int
        Gets an Int data item from the DataMap

        Key - The reference as set in in the PutInt() method
      • PutStringArray (Key As java.lang.String, Val As java.lang.String[]) As void
        Adds a String Array data item to the DataMap

        Key - a key used to reference the data item
        Val - the value to set to.
      • Get (Key As java.lang.String) As java.lang.Object
        Returns the DataMap entry with the given Key as an Object
      • toByteArray As byte[]
        Returns the DataMap as a ByteArray
      • GetString (Key As java.lang.String) As java.lang.String
        Gets a String data item from the DataMap

        Key - The reference as set in in the PutString() method
      • PutString (Key As java.lang.String, Val As java.lang.String) As void
        Adds a String data item to the DataMap

        Key - a key used to reference the data item
        Val - the value to set to.
      • toString As java.lang.String
        Returns a string representation of the DataMap
      • PutFloat (Key As java.lang.String, Val As float) As void
        Adds a Float data item to the DataMap

        Key - a key used to reference the data item
        Val - the value to set to.
      • PutFloatArray (Key As java.lang.String, Val As float[]) As void
        Adds a Float Array data item to the DataMap

        Key - a key used to reference the data item
        Val - the value to set to.
    • ABWearOSChannel
      Methods:
      • GetInputStream As void
        Get an input stream which can read data from the remote node.

        event: ChannelInputStreamResult(Success as Boolean, NodeId as String, Stream As InputStream)
      • GetOutputStream As void
        Get an output stream which can send data to a remote node.

        event: ChannelOutputStreamResult(Success as Boolean, NodeId as String, Stream As OutputStream)
      Properties:
      • Path As java.lang.String [read only]
        Returns the path that was used to open the channel.
      • NodeId As java.lang.String [read only]
        Returns the node ID of the node on the other side of the channel.
      • DescribeContents As int [read only]
        Returns one of the CHANNEL_ constants
    • ABWearOSAmbient
      Events:
      • Enter (IsLowBitAmbient As Boolean, DoBurnInProtection As Boolean)
      • Update (IsAmbient as Boolean As )
      • Exit ( As )
      Methods:
      • Initialize (ba As anywheresoftware.b4a.BA, EventName As java.lang.String) As void
        Initializes the object and sets the subs that will handle the events.
    • ABWearOS
      Events:
      • LocalNodeIDResult (Success As boolean, NodeId as String As , NodeDisplayName As String)
      • NodeResults (Success As Boolean, Results As List)
      • MessageSent (Success As Boolean, Path as String As , Node as String As )
      • MessageReceived (SourceNodeID As String, RequestID As Int, msgPath As String, Data As String)
      • DataMapDeleted (Success As Boolean, Path as string As )
      • DataMapResults (Success As Boolean, Results As Map)
      • DataMapResult (Success As Boolean, Tag As String, Result As DataMap)
      • DataMapAdded (Success As Boolean, Path As String)
      • DataChanged (ChangedItems As Map, DeletedItems As Map)
      • BitmapResult (Success As Boolean, Tag As String, Result As Bitmap)
      • FileResult (Success as Boolean As , Tag As String, Dir As String, Filename As String)
      • CapabilityChanged (Name as String As , Nodes as List As )
      • CapabilityAdded (Success as Boolean As , Capability As String)
      • CapabilityRemoved (Success as Boolean As , Capability As String)
      • CapabilitiesResults (Success As Boolean, Results as List As )
      • CapabilityResult (Success As Boolean, Capability as String As , Results as List As )
      • ChannelInputStreamResult (Success as Boolean As , NodeId as String As , Stream As InputStream)
      • ChannelOutputStreamResult (Success as Boolean As , NodeId as String As , Stream As OutputStream)
      • ChannelCloseResult (Success as Boolean As , Channel as ABWearOSChannel As )
      • ChannelOpenResult (Success as Boolean As , channel As ABWearOSChannel)
      • ChannelClosed (Channel as ABWearOSChannel As , closeReason as int As , errorCode as int As )
      • ChannelOpened (Channel as ABWearOSChannel As )
      • ChannelInputClosed (Channel as ABWearOSChannel As , closeReason as int As , errorCode as int As )
      • ChannelOutputClosed (Channel as ABWearOSChannel As , closeReason as int As , errorCode as int As )
      • ChannelReceiveFileResult (Success as Boolean As )
      • ChannelSendFileResult (Success as Boolean As )
      Fields:
      • CLOSE_REASON_DISCONNECTED As int
      • CAPABILITY_FILTER_REACHABLE As int
      • CHANNEL_CLOSE_REASON_DISCONNECTED As int
      • CHANNEL_CLOSE_REASON_LOCAL_CLOSE As int
      • CLOSE_REASON_LOCAL_CLOSE As int
      • CAPABILITY_FILTER_LITERAL As int
      • CAPABILITY_FILTER_PREFIX As int
      • CLOSE_REASON_NORMAL As int
      • CAPABILITY_FILTER_ALL As int
      • CHANNEL_CLOSE_REASON_REMOTE_CLOSE As int
      • CLOSE_REASON_REMOTE_CLOSE As int
      • CHANNEL_CONTENTS_FILE_DESCRIPTOR As int
      • CHANNEL_PARCELABLE_WRITE_RETURN_VALUE As int
      • CHANNEL_CLOSE_REASON_NORMAL As int
      Methods:
      • RemoveLocalCapability (capability As java.lang.String) As void
        Announces that a capability is no longer available on the local node.

        Note: this will not remove any capabilities announced in the Manifest for an app.

        event: CapabilityRemoved (Success as boolean, Capability as String)
      • GetConnectedNodes As void
        Get a list of the connected Nodes (Devices)

        event: NodeResults(Success, List)

        The returned List will contains a Map for each node (Case Sensitive!).
        The map will then contain 3 Key-Value pairs:
        ID - The ID of the node, this is used to reference the node when sending messages etc
        DisplayName - A HumanReadable name for the device (on my Samsung Gear Live this matched the ID so was of no use)
        IsNearby - boolean is the device is nearby
      • GetCapability (capability As java.lang.String, nodeFilter As int) As void
        Returns information about a capability, including the nodes that declare that capability.

        The nodeFilter parameter controls whether all nodes are returned, CAPABILITY_FILTER_ALL,
        or only those that are currently reachable by this node, CAPABILITY_FILTER_REACHABLE.

        event: CapabilityResult(Success As Boolean, Capability as String, Results as List)

        The returned List will contains a Map for each node (Case Sensitive!).
        The map will then contain 3 Key-Value pairs:
        ID - The ID of the node, this is used to reference the node when sending messages etc
        DisplayName - A HumanReadable name for the device (on my Samsung Gear Live this matched the ID so was of no use)
        IsNearby - boolean is the device is nearby
      • AddDataMap (path As java.lang.String, datamap As com.google.android.gms.wearable.DataMap) As void
        Adds a Data Map to the Client to sync across the Wearable Data connection.
        DataMaps are synchronized across all devices
        Path - The path to store the DataMap under. e.g "/User"
        DataMap - The DataMap object to add

        event: DataMapAdded(Success, path)
      • AssetToFile (tag As java.lang.String, asset As com.google.android.gms.wearable.Asset, targetDir As java.lang.String, targetFileName As java.lang.String) As void
        Convert an Asset to a File

        Tag - A tag used to identify the request in the resulting callback
        Asset - The Asset object to extract the File from.
        TargetDir - The directory where the File will be created
        TargetFilename - The filename that the extracted File will be named

        event: FileResult(success, tag, targetdir, targetFileName)
      • Initialize (ba As anywheresoftware.b4a.BA, Eventname As java.lang.String) As void
        Initializes the object.
      • Disconnect As void
        Disconnects the Google Play services client

        Should always be called once you have finished with the Data Layer e.g. when the app closes or is paused.
      • GetAllDataMaps As void
        Get all the present DataMaps as a Map.

        Each Map Key-Value pair is as follows
        Key - The path that the DataMap resides
        Value - The DataMap object

        Event: DataMapResults(Success, Results)
      • GetLocalNode As void
        Returns the local node id

        event: LocalNodeIDResult(success, nodeId, nodeDisplayName)
      • GetDataMap (path As java.lang.String, tag As java.lang.String) As void
        Get a DataMap.

        Event: DataMapResult(Success, Tag , Result)
      • ReceiveFile (channel As com.ab.abwearos.ABWearOSChannel, filePath As java.lang.String, fileName As java.lang.String, append As boolean) As void
        Reads input from a channel into a file. This is equivalent to calling GetInputStream(), reading from the input stream and writing it to a file,
        but is implemented more efficiently. Writing to the file will be done in a background process owned by Google Play services.

        This method should only be used once on any channel, and once it has been called, GetInputStream() cannot be used.
        The channel should not be immediately closed after calling this method.

        events: ChannelReceiveFileResult(Success as boolean) if the call succeeded
        ChannelInputClosed(Channel as ABWearOSChannel, closeReason as int, errorCode as int) when the file is received
      • BitmapToAsset (bitmap As android.graphics.Bitmap) As com.google.android.gms.wearable.Asset
        Convert a Bitmap to an Asset
      • SendMessage (path As java.lang.String, node As java.lang.String, message As java.lang.String) As void
        Sends a message to a specified node

        event: MessageSent(Success, path, node)
      • GetAllCapabilities (nodeFilter As int) As void
        Returns information about all capabilities, including the nodes that declare those capabilities.

        The nodeFilter parameter controls whether all nodes are returned, CAPABILITY_FILTER_ALL,
        or only those that are currently reachable by this node, CAPABILITY_FILTER_REACHABLE.

        event: CapabilitiesResults(Success as Boolean, Results as List)

        Is a lists of Maps. The map will then contain 2 Key-Value pairs:
        Name - Capability name
        Nodes - A list of Maps: the map will then contain 3 Key-Value pairs:
        ID - The ID of the node, this is used to reference the node when sending messages etc
        DisplayName - A HumanReadable name for the device (on my Samsung Gear Live this matched the ID so was of no use)
        IsNearby - boolean is the device is nearby
      • AddLocalCapability (capability As java.lang.String) As void
        Announces that a capability has become available on the local node.

        event: CapabilityAdded (Success as boolean, Capability as String)
      • AssetToBitmap (tag As java.lang.String, asset As com.google.android.gms.wearable.Asset) As void
        Convert an Asset to a Bitmap

        Tag - a Tag used to identify the request in the resulting callback
        Asset - the Asset object to extract the File from

        event: BitmapResult(success, tag, bitmap)
      • FileToAsset (Dir As java.lang.String, Filename As java.lang.String) As com.google.android.gms.wearable.Asset
        Convert a File to an Asset
      • Connect As void
        Connects the Google Play services client (required for the Data Layer to work)

        Make sure you disconnect the client once done (probably best to do this in Activity_Pause()
      • DeleteDataMap (path As java.lang.String) As void
        Deletes a DataMap

        event: DataMapDeleted(Success, path)
      • SendFile (channel As com.ab.abwearos.ABWearOSChannel, filePath As java.lang.String, fileName As java.lang.String) As void
        Reads from a file into the output side of a channel. This is equivalent to calling GetOutputStream(),
        reading from a file and writing into the OutputStream, but is implemented more efficiently.
        Reading from the file will be done in a background process owned by Google Play services.

        This method should only be used once on any channel, and once it has been called, GetOutputStream() cannot be used.
        The channel should not be immediately closed after calling this method.

        events: ChannelSendFileResult(Success as boolean) if the call succeeded
        ChannelOutputClosed(Channel as ABWearOSChannel, closeReason as int, errorCode as int) when the file is send
      • SendFileOffset (channel As com.ab.abwearos.ABWearOSChannel, filePath As java.lang.String, fileName As java.lang.String, offset As long, length As long) As void
        Reads from a file into the output side of a channel. This is equivalent to calling GetOutputStream(),
        reading from a file and writing into the OutputStream, but is implemented more efficiently.
        Reading from the file will be done in a background process owned by Google Play services.

        This method should only be used once on any channel, and once it has been called, GetOutputStream() cannot be used.
        The channel should not be immediately closed after calling this method.

        events: ChannelSendFileResult(Success as boolean) if the call succeeded
        ChannelOutputClosed(Channel as ABWearOSChannel, closeReason as int, errorCode as int) when the file is send
      • ChannelClose (channel As com.ab.abwearos.ABWearOSChannel, errorCode As int) As void
        Closes a channel, passing an application-defined error code to the remote node.
        The error code will be passed to ChannelClosed event, and will cause remote reads and writes to the channel to fail.

        The InputStream and OutputStream returned from GetInputStream() or GetOutputStream(l) should be closed prior to calling this method.
        If they are not, both streams will throw an exception.

        errorCode = 0 is used to indicate that no error occurred.

        events: ChannelCloseResult(Success As Boolean, Channel as ABWearOSChannel) if this called succeeds on the calling device
        ChannelClosed(Channel as ABWearOSChannel, closeReason as int, errorCode as int) will be raised on the remote device
      • ChannelOpen (nodeId As java.lang.String, path As java.lang.String) As void
        Opens a channel to exchange data with a remote node.
        Channel which are no longer needed should be closed using close(Channel).

        This call involves a network round trip, so may be long running.
        Client must remain connected during that time, or the request will be cancelled (like any other Play Services API calls).

        events: ChannelOpenResult(Success As Boolean, Channel As ABWearOSChannel) if this called succeeds on the calling device
        ChannelOpened(Channel as ABWearOSChannel) will be raised on the remote device
      Properties:
      • ShowDebug As boolean [write only]
        Shows some debug info from within the library

    Installation:

    Copy all four jar files to your Additional libraries folder. In the library manager, select ABWearOS.

    -- Mobile --
    Additional jars in Region Project Attributes:
    Code:
    #AdditionalJar: com.google.android.gms:play-services-wearable
    #AdditionalJar: com.android.support:wear
    Manifest:
    Code:
    AddManifestText(
    <uses-sdk android:minSdkVersion=
    "14" android:targetSdkVersion="26"/>
    <supports-screens android:largeScreens=
    "true"
        android:normalScreens=
    "true"
        android:smallScreens=
    "true"
        android:anyDensity=
    "true"/>)
    SetApplicationAttribute(android:icon, 
    "@drawable/icon")
    SetApplicationAttribute(android:
    label"$LABEL$")
    CreateResourceFromFile(Macro, Themes.DarkTheme)
    'End of default text.

    AddPermission(android.permission.READ_EXTERNAL_STORAGE)
    AddPermission(android.permission.WRITE_EXTERNAL_STORAGE)

    AddApplicationText(<meta-data
                    android:name=
    "com.google.android.gms.version"
                    android:value=
    "@integer/google_play_services_version" />
    )
    -- Wear --
    Additional jars in Region Project Attributes:
    Code:
    #AdditionalJar: com.google.android.gms:play-services-wearable
    #AdditionalJar: com.android.support:wear
    If you want the app to always stay in front, you will need to activate the ambient mode.

    In #Region Activity Attributes add:
    Code:
    #Extends: com.ab.abwearos.ABWearOSAmbient
    Manifest:
    Code:
    AddManifestText(
    <uses-sdk android:minSdkVersion=
    "5" android:targetSdkVersion="26"/>
    <uses-feature android:name=
    "android.hardware.type.watch"/>
    )
    SetApplicationAttribute(android:icon, 
    "@drawable/icon")
    SetApplicationAttribute(android:
    label"$LABEL$")
    CreateResourceFromFile(Macro, Themes.DarkTheme)
    'End of default text.

    AddPermission(android.permission.READ_EXTERNAL_STORAGE)
    AddPermission(android.permission.WAKE_LOCK)

    AddApplicationText(<meta-data
       android:name=
    "com.google.android.gms.version"
       android:value=
    "@integer/google_play_services_version" />
       <uses-library android:name=
    "com.google.android.wearable" android:required="false" />
    )
    The ABWearOS library can be defined ONLY once in your project and you must share the same instance in other activities/services. All the events will be raised in the activity/service where ABWearOS is defined.

    e.g. if you have have in your main activity, then all events wll be raised in THIS activity:
    Code:
    Sub Globals
       
    ' can be accessed from all modules
       public wear As ABWearOS
    End Sub

    The ambient mode 
    is to keep your app in the forgroud, if you app goes in ambient mode.  Can be handy e.g. for a walking app.
    Sub Globals
       
    ' is an activity object, so must be declared here.
       Private ambient As ABWearOSAmbient
    End Sub
    In the Activity_Create (or Service_Create) initialize them:
    Code:
    ambient.Initialize("ambient")
    wear.Initialize(
    "wear")
    In Activity_Resume (or Service_Start) you do the connect:
    Code:
    wear.connect
    In Activity_Pause (or Service_Destroy) you disconnect:
    Code:
    wear.disconnect
    Inbetween you can do all kind of stuff. In most cases you will want to run wear.GetConnectedNodes first so you get a list of all the devices connected. Google Play Services acts a bit like MQTT, so you send messages (or datamaps) between devices using a path (e.g. "/mypath" and a nodeid. This node id you get by running GetConnectedNodes() and GetLocalNode() to get your own nodeId.

    All calls to the library run in seperate threads: this means a call you do will never immidiately return a result, you will have to wait for an event. e.g. wear.SendMessage() will return the wear_MessageSent event. Check out the help to see which event is returned by which function.

    Some calls will return two events, e.g. the ChannelClose method will return two events. One on the sending device and one on the receiving device:

    if this called succeeds on the calling device:
    Code:
    ChannelCloseResult(Success As Boolean, Channel as ABWearOSChannel)
    will be raised on the remote device:
    Code:
    ChannelClosed(Channel as ABWearOSChannel, closeReason as int, errorCode as int)
     
    Last edited: Apr 5, 2019
  2. Peter Simpson

    Peter Simpson Expert Licensed User

    This is excellent @alwaysbusy,
    I'm straight on it, lets see what the score is with it then, looks good though ;).

    Cheers...
     
    Last edited: Oct 8, 2018
  3. alwaysbusy

    alwaysbusy Expert Licensed User

    A snippet from the app I wrote which shows how to send a datamap from the mobile phone to the wear app:

    ' mobile, wear is defined in a service and it has a method StartGame() where I upload my golf clubs to the wear app:
    Code:
    public Sub StartGame()
       
    ' Mapclubs is dimmed in Process_Globals as: Private MapClubs As ABWearOSDataMap
       MapClubs.Initialize

       wear.Connect
       wear.GetConnectedNodes
       
       
    Dim clubs As List = GetClubs
       MapClubs.Clear
       MapClubs.PutString(
    "MapType""MapClubs")
       
    Dim Keys As List
       Keys.Initialize
       
    For i = 0 To clubs.Size - 1
           
    Dim club As clsClub = clubs.Get(i)
           MapClubs.PutString(club.ClubName, club.ToString)
           Keys.Add(club.ClubName)
       
    Next
       MapClubs.PutStringArray(
    "Keys", ToArray(Keys))
       wear.AddDataMap(
    "/golfcaddy", MapClubs)
    End Sub

    Sub ToArray(l As ListAs String()
       
    Dim ArrayOf(l.Size) As String
       
    For i = 0 To l.Size - 1
           ArrayOf(i) = l.Get(i)
       
    Next
       
    Return ArrayOf
    End Sub
    ' wear device (wear is defined in the activity here):
    Code:
    Sub wear_DataChanged(ChangedItems As Map, DeletedItems As Map)
       
    For Each key As String In ChangedItems.Keys
           
    Dim m As ABWearOSDataMap = ChangedItems.get(key)
           
    Dim MapType As String = m.GetString("MapType")
           
    Select Case MapType
               
    Case "MapClubs"
                   
    Log("New clubs")
                   
                   RealClubs.Clear
                   
    Dim keys() As String = m.GetStringArray("Keys")
                   
    For i = 0 To keys.Length - 1
                       
    Dim club As clsClub
                       club.Initialize
                       club.FromString(m.GetString(keys(i)))
                       RealClubs.Add(club)
                   
    Next
              
    Case ' it does other things like handeling an uploaded course
                  ...
          
    End Select
       
    Next
    End Sub
     
    Erel, DonManfred and Peter Simpson like this.
  4. alwaysbusy

    alwaysbusy Expert Licensed User

    A template project for the mobile and wear part. It doesn't do anything, but normally all settings (like the Manifest and the #AdditionalJars) should be in place.
     

    Attached Files:

  5. fabpalma

    fabpalma Member Licensed User

    Hi, first many thanks for your job !!
    I am trying to compile your example but I got immediatly an error:

    B4A Version: 7.80
    Code analysis. (0.00s)
    Code compilation. error
    Reference to an object not set on an object instance.

    (translated from italian)

    But in the code editor I'm not able to see any error.
    Can I use B4A version 7.80 or I need to upgrade ?
    I have solved all the maven* missing alerts but it wasn't enough !

    Do I need to copy some jar file from SDK into library folder ?

    Thanks in advance.
    Regards
     
  6. alwaysbusy

    alwaysbusy Expert Licensed User

    I'm using B4A 8.50. It is possible that only the later version of B4A can use these type of #AdditionJars, but I'm not sure. The jars included in the zip should be enough (if you have installed the complete SDK 28 and pointed B4A to android-28\android.jar).

    Maybe wait until @Erel gives an answer if 7.80 is enough for Android SDK 28.

    Is there someone who uses B4A 8.50 and has the same problem? If so, then I will have to investigate.
     
  7. DonManfred

    DonManfred Expert Licensed User

    it is suggested to update. By end of the year google will force us to use SDK 26. You need B4A 8+ if you want to run your apps on newer devices.
     
    Peter Simpson and Johan Hormaza like this.
  8. Peter Simpson

    Peter Simpson Expert Licensed User

    Nope, withing minutes of you adding your example, I had got it working with B4A v8.50, Java 10.0.2, SmartWatch is Android OS 8.0.0 with Wear OS 2.0.

    Thank you...
     
    Last edited: Oct 9, 2018
    DonManfred and alwaysbusy like this.
  9. Erel

    Erel Administrator Staff Member Licensed User

    V7.80 should work with Android SDK 28. The problem is somewhere else. As written above it is recommended to update to B4A v8+ anyway as it is required for several features once you set targetSdkVersion to 26+.
     
    Johan Hormaza and alwaysbusy like this.
  10. fabpalma

    fabpalma Member Licensed User

    I purchased the update to version 8.50 and I recompiled the project without changing anything and it was successful.
    Evidently there are some features required in version 8.50.
    I think it's better to write it in the library post.

    Now I can try the alwaysbusy library!
    Thank you.
     
    DonManfred and Erel like this.
  11. alwaysbusy

    alwaysbusy Expert Licensed User

    Done
     
  12. seskindell

    seskindell Active Member Licensed User

    I have 8.5 installed. I am getting the error message "Maven artifact not found: com.android.support/wear". I am setup with jdk-10.0.2 and Android-28 (everything installed).

    Please help.
     
    Last edited: Oct 15, 2018
  13. fabpalma

    fabpalma Member Licensed User

    Run SDK Manager from B4A IDE and check that com.android.support:wear (Google Maven) Version 28.0.0 is installed.
    Otherwise, select it and press [Install Selected].
    You have to do the same for every missing reference.
     
  14. alwaysbusy

    alwaysbusy Expert Licensed User

  15. seskindell

    seskindell Active Member Licensed User

    Tried to compile the sample template for the mobile and wear devices. Using 8.5 with everything installed correctly.
    The mobile app compiles fine. The Wear device (which is a gen 4 fossil smart watch) brings up the following errors:

    Logger connected to: samsung SM-G900V
    --------- beginning of main
    ** Activity (main) Create, isFirst = true **
    ** Activity (main) Resume **
    *** Service (wearservice) Create ***
    ** Service (wearservice) Start **
    ** Activity (main) Pause, UserClosed = false **
    ** Activity (main) Resume **
    ** Service (wearservice) Start **
    Partial wakeLock already held.
    ** Activity (main) Pause, UserClosed = false **
    *** Service (starter) Create ***
    ** Service (starter) Start **
    ** Activity (main) Create, isFirst = true **
    main_activity_create (java line: 357)
    java.lang.ClassCastException: com.ab.weardemo.main cannot be cast to com.ab.abwearos.ABWearOSAmbient
    at com.ab.abwearos.ABWearOSAmbient$ABWearOSAmbientListener.Initialize(ABWearOSAmbient.java:112)
    at com.ab.weardemo.main._activity_create(main.java:357)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:191)
    at com.ab.weardemo.main.afterFirstLayout(main.java:104)
    at com.ab.weardemo.main.access$000(main.java:17)
    at com.ab.weardemo.main$WaitForLayout.run(main.java:82)
    at android.os.Handler.handleCallback(Handler.java:739)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:145)
    at android.app.ActivityThread.main(ActivityThread.java:5835)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
    *** Service (starter) Create ***
    ** Service (starter) Start **
    ** Activity (main) Create, isFirst = true **
    ** Activity (main) Resume **
    GetConnectedNodes: 1 found
    true
    7f1514ae: Q Explorist HR 2784
    ** Activity (main) Pause, UserClosed = false **
     
  16. seskindell

    seskindell Active Member Licensed User

    These are the errors I get when I try compiling the wear app from the template (no changes to the template code) -- using SDK 28:

    PackageAdded: package:com.ab.weardemo
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.ab.weardemo/com.ab.weardemo.main}: java.lang.IllegalStateException: Could not find wearable shared library classes. Please add <uses-library android:name="com.google.android.wearable" android:required="false" /> to the application manifest
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2661)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726)
    at android.app.ActivityThread.access$900(ActivityThread.java:172)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1421)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:145)
    at android.app.ActivityThread.main(ActivityThread.java:5835)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
    Caused by: java.lang.IllegalStateException: Could not find wearable shared library classes. Please add <uses-library android:name="com.google.android.wearable" android:required="false" /> to the application manifest
    at android.support.wear.ambient.SharedLibraryVersion.verifySharedLibraryPresent(SharedLibraryVersion.java:57)
    at android.support.wear.ambient.WearableControllerProvider.getWearableController(WearableControllerProvider.java:48)
    at android.support.wear.ambient.AmbientDelegate.onCreate(AmbientDelegate.java:103)
    at android.support.wear.ambient.AmbientModeSupport.onCreate(AmbientModeSupport.java:198)
    at android.support.v4.app.Fragment.performCreate(Fragment.java:2414)
    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1418)
    at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1784)
    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1852)
    at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:802)
    at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2625)
    at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2411)
    at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2366)
    at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2273)
    at android.support.v4.app.FragmentManagerImpl.dispatchStateChange(FragmentManager.java:3273)
    at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:3229)
    at android.support.v4.app.FragmentController.dispatchActivityCreated(FragmentController.java:201)
    at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:620)
    at com.ab.weardemo.main.onStart(main.java:175)
    at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1234)
    at android.app.Activity.performStart(Activity.java:6258)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2624)
    ... 10 more
     
  17. alwaysbusy

    alwaysbusy Expert Licensed User

    Are you trying to run the wear app on your phone? it will only run on a wear device connected to your pc and it should be running Wear OS 2.0+. If your watch doesn’t support ambient mode, you can try removing the #Extends line, the ABWearOSAmbient library (and relevant code)
     
  18. seskindell

    seskindell Active Member Licensed User

    I am running OS 2.0 on the watch. How do you install the app to the watch? I thought it would automatically install.
    Thank you,
    Steve
     
  19. alwaysbusy

    alwaysbusy Expert Licensed User

    No, barx used to have a way, but I don't think it works anymore (at least following his tutorial, it didn't work for me). You have to connect the watch through USB and then install it.
     
  20. seskindell

    seskindell Active Member Licensed User

    Yes ... I was trying to run the Wear app of the template on the Mobile rather than the wear device.
    I finally viewed tutorials on Youtube to figure out how to install the demo.apk on the watch wear device.
    I had to configure debugging wifi on the watch and find the ip address of the watch. Then I issued the dos commands:

    adb forward tcp:5555 localabstract:/adb-hub
    adb connect 10.0.1.41:5555
    (10.0.1.41 is the ip address of the watch)

    Once the connection was made I issued the command from DOS:

    adb -e install demo.apk

    That installed the app on the watch.

    It would be really helpful to have a button and edittext field on both the wear device and the mobile device and show how the
    edittext string goes from the mobile device to the wear device .. and how the edittext string goes from the wear device to the mobile device when the
    respective button is pressed. That would be REALLY helpful to me.

    - Steve
     
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