Android Question Detecting a round display on Wear?

TpS

Member
Licensed User
Longtime User
I´we recently done my first app containing the Wear addon.
However, to be accepted as a "real" Wear-app it needs to have a layout that adapts to round displays aswell.

In the Wearable UI Library for Eclipse (http://developer.android.com/training/wearables/ui/layouts.html) there´s a possibility to detect a round display and to use another layout on thoose models, do we have this option on B4A in some way?
 

Johan Schoeman

Expert
Licensed User
Longtime User
  • Like
Reactions: TpS
Upvote 0

Johan Schoeman

Expert
Licensed User
Longtime User
I wonder how android handles it: f.e. what is 100%x or y?
In the code of the link that I have posted there seems to be an android method to check if it is round. If Round then they check if the screen is 320 x 290 pix. If true then the screen is MOTO_ROUND (round but with flat bottom). If not ROUND and not MOTO_ROUND then it must be SQUARE.
 
  • Like
Reactions: TpS
Upvote 0

TpS

Member
Licensed User
Longtime User
There is a possible solution here that can be built into a library. I don't have a wear device to test the lib else I would have created the lib. Perhaps someone with a wear device that are also able to build the lib can help help you out with this.

https://github.com/tajchert/ShapeWear/tree/master/wear/src/main/java/pl/tajchert/shapewear
Oh, that looks nice.
Sadly I´m not self capable of writing my own library so I have to lay my trust in you guys with greater skills.
I have to wait and see then.
 
Upvote 0

Johan Schoeman

Expert
Licensed User
Longtime User
Oh, that looks nice.
Sadly I´m not self capable of writing my own library so I have to lay my trust in you guys with greater skills.
I have to wait and see then.
Will try and wrap it....but no guarantee it will work as I don't have a wear device to test it on. You wil have to test it if I do manage to get it wrapped and let me know if it is working or not.
 
  • Like
Reactions: TpS
Upvote 0

TpS

Member
Licensed User
Longtime User
Will try and wrap it....but no guarantee it will work as I don't have a wear device to test it on. You wil have to test it if I do manage to get it wrapped and let me know if it is working or not.
I'll gladly try it, however I only have a Sony SW3 with square display but I can try to create a round one in the SDK typ try with.
Thanks a lot!
 
Upvote 0

Johan Schoeman

Expert
Licensed User
Longtime User
I'll gladly try it, however I only have a Sony SW3 with square display but I can try to create a round one in the SDK typ try with.
Thanks a lot!
OK - let's try this. I am getting an answer back from my tablet but seeing that the tablet's screen size falls outside the range of what this lib looks for it reports just on the size found and that the shape is UNDETECTED (i.e the default shape that the library is set to).

Please try and let me know what you get. Attaching a small B4A project and the B4A library files. Copy the library files to your additional library folder.
 

Attachments

  • b4aShapeWear.zip
    6.8 KB · Views: 394
  • ShapeWearLibFiles.zip
    7.4 KB · Views: 400
  • Like
Reactions: TpS
Upvote 0

TpS

Member
Licensed User
Longtime User
OK - let's try this. I am getting an answer back from my tablet but seeing that the tablet's screen size falls outside the range of what this lib looks for it reports just on the size found and that the shape is UNDETECTED (i.e the default shape that the library is set to).

Please try and let me know what you get. Attaching a small B4A project and the B4A library files. Copy the library files to your additional library folder.
After some testing (and fiddling to get the ADB-logging active on the Wear) we seem to have a success here.
This is the Log from my test:
B4X:
** Activity (main) Create, isFirst = false **
in the class : public static ScreenShape getShape() and shape is RECTANGLE
in the class : public static ScreenShape getShape() and shape is RECTANGLE
in public void shapeDetected
shapeDetected isRound:RECTANGLE
in the class : public static ScreenShape getShape() and shape is RECTANGLE
shapeDetected getShape:RECTANGLE
in public void sizeDetected - w:320, h:320
in public void sizeDetected - w:320, h:320
** Activity (main) Resume **
in the class : public static ScreenShape getShape() and shape is RECTANGLE
shape: RECTANGLE
shape: false
** Activity (main) Pause, UserClosed = false **

Now is the question, can you add some new method containing a String or a boolean that I can use in the Activity_Create to decide what Layout that should load?

Big thanks so far!
 
Upvote 0

Johan Schoeman

Expert
Licensed User
Longtime User
After some testing (and fiddling to get the ADB-logging active on the Wear) we seem to have a success here.
This is the Log from my test:
B4X:
** Activity (main) Create, isFirst = false **
in the class : public static ScreenShape getShape() and shape is RECTANGLE
in the class : public static ScreenShape getShape() and shape is RECTANGLE
in public void shapeDetected
shapeDetected isRound:RECTANGLE
in the class : public static ScreenShape getShape() and shape is RECTANGLE
shapeDetected getShape:RECTANGLE
in public void sizeDetected - w:320, h:320
in public void sizeDetected - w:320, h:320
** Activity (main) Resume **
in the class : public static ScreenShape getShape() and shape is RECTANGLE
shape: RECTANGLE
shape: false
** Activity (main) Pause, UserClosed = false **

Now is the question, can you add some new method containing a String or a boolean that I can use in the Activity_Create to decide what Layout that should load?

Big thanks so far!
Will add an Event that will return width, height, and shape to B4A
 
  • Like
Reactions: TpS
Upvote 0

Johan Schoeman

Expert
Licensed User
Longtime User
Now is the question, can you add some new method containing a String or a boolean that I can use in the Activity_Create to decide what Layout that should load?

Big thanks so far!

Try this - have added 3 x getters to the wrapper so that you can get/fetch the shape, width. and height. Please test and let me know if OK.

B4X:
Sub Activity_Resume
   
'    sw.ShowWearDeviceShape
    Log(sw.Shape)                                 'this is a String coming back
    Log(sw.ScreenHeightPX)                        'this in an Int coming back
    Log(sw.ScreenWidthPX)                         'this is an Int coming back

End Sub

Can you also simulate the ROUND and MOTO to see if it comes back with the correct results?
 

Attachments

  • ShapeWearLibFiles1.zip
    7.3 KB · Views: 381
  • b4aShapeWear1.zip
    6.7 KB · Views: 366
  • Like
Reactions: TpS
Upvote 0

TpS

Member
Licensed User
Longtime User
Try this - have added 3 x getters to the wrapper so that you can get/fetch the shape, width. and height. Please test and let me know if OK.

B4X:
Sub Activity_Resume
  
'    sw.ShowWearDeviceShape
    Log(sw.Shape)                                 'this is a String coming back
    Log(sw.ScreenHeightPX)                        'this in an Int coming back
    Log(sw.ScreenWidthPX)                         'this is an Int coming back

End Sub

Can you also simulate the ROUND and MOTO to see if it comes back with the correct results?
Hmm, this is real strange..
Either the library is unstable in some way or I have missed something, se examples below:

Example 1 is from yesterdays succesful test
B4X:
in the class : public static ScreenShape getShape() and shape is RECTANGLE
shape: RECTANGLE
shape: false

Example 2 is from todays test with the new library, W and H works but Shape is undetected.
B4X:
Shape: UNDETECTED
Height: 320
Width: 320

Example 3 is from today when I tried to back to old library and old code again, but still shape is undetected.
B4X:
in the class : public static ScreenShape getShape() and shape is UNDETECTED
shape: UNDETECTED
ScreenShapeNotDetectedException from isRound: ShapeWear still doesn't have correct screen shape at this point, subscribe to OnShapeChangeListener or call this method later on. Also you can call getShape() to get String representation, will return SHAPE_UNSURE if not specified.

And the code is totally stripped so nothing should disturb:
B4X:
Sub Process_Globals
End Sub

Sub Globals
    Dim sw As ShapeWear
End Sub

Sub Activity_Create(FirstTime As Boolean)
    sw.Initialize("sw")
End Sub

Sub Activity_Resume
    sw.ShowWearDeviceShape
End Sub

Sub Activity_Pause (UserClosed As Boolean)
End Sub

Any ideas?
 
Upvote 0

Johan Schoeman

Expert
Licensed User
Longtime User
Any ideas?

The attached should fix it. I added a trigger to the original code based on a StackOverflow posting (view.requestApplyInsets();). That sorted out the problem. Have tested it with Round and Square on the AVD. Have also added/changed the projects manifest:

B4X:
AddManifestText(<uses-feature android:name="android.hardware.type.watch" />)

SetApplicationAttribute(android:theme, "@android:style/Theme.DeviceDefault")

1. Posting the B4A test project
2. Java Code
3. B4A library files

Have a great 2016! ;)

1.png



2.png


AVD Manager setup for ROUND:
3.png



AVD Manager setup for RECTANGULAR:
4.png



ANDROID SDK Manager - you also need to install Android 4.4W.2 (API20)
5.png


These are the steps that I have followed to for eg set up the Round display of the AVD Manager:

In B4A:
1. Tools ----> Run AVD Manager
2. Once AVD Manager started you go to the tab that says Device Definitions
3. Scroll down and look for:
Android Wear Round by Google
Screen 1.7", 320 x 320, Small hdpi
RAM: 512 MiB
4. Click on the Create AVD... button at the right top of the AVD Manager
5. The AVD setup screen that I have posted in this thread will pop up.
6. Set it up as what I have shown in this thread (NB - we are busy doing Round as per (3) above. So use the info of the pic that I have posted for Round.)
7. Click on OK - a screen showing the setup should pop up
8. Click on OK on the screen in (7) above
9. It will automatically go back to the Android Virtual Devices tab of the AVD Manager
10. Click Start... (second button from the top on the AVD Manager)
11. Click Launch on the Launch Options popup that you should see now.
12. A new popup will display Starting Android Emulator
13. Emulator screen will be generated and will be black except for visible round markings in background and solid black square in foreground
14. Just leave it now to do whatever it is busy doing
15. A white screen should appear in the emulator with the words Just a minute... and a green round progress indicator displaying
16. Leave it - eventually it will say Paired... with a tick mark (like a tick mark when you got an answer correct in a test while in school)
17. Once (16) shows then click on Connect in the B4A logs tab. It should come back with LogCat connected to: emulator-5554
18. Run the B4A project.
19 It should show the pic I have posted with the emulator Screen showing ROUND, Width = 320, Height = 320
 

Attachments

  • TheJavaCode.zip
    33.7 KB · Views: 428
  • b4aShapeWear.zip
    8.3 KB · Views: 475
  • ShapeWearLibFiles.zip
    7.4 KB · Views: 424
Last edited:
Upvote 0

TpS

Member
Licensed User
Longtime User
Great work, Last file works nicely!

Only problem is that the shape isn´t inititalized until after Activity_Resume has passed, before that it only returns "UNDETECTED" no mather how long I wait (tried For Next loop, and Do While but no success)

I solved it this way and it seems to work so far. Using a one Tick timer that triggers just after the Resume seems to do the trick.

B4X:
Sub Process_Globals
    Dim timerDetect As Timer
End Sub

Sub Globals
    Dim sw As ShapeWear
End Sub

Sub Activity_Create(FirstTime As Boolean)
    sw.Initialize("")
    sw.ShowWearDeviceShape
    sw.initShapeWear1

    timerDetect.Initialize("TimerDetect",500)
    timerDetect.Enabled = True
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub TimerDetect_Tick

    If sw.Shape = "RECTANGLE" Then
        Activity.LoadLayout("LayoutRect")
    else if sw.Shape = "ROUND" Then
        Activity.LoadLayout("LayoutRound")
    else if sw.Shape = "MOTO" Then
        Activity.LoadLayout("LayoutRound")
    Else
        Activity.LoadLayout("LayoutRect")
    End If
End Sub
 
Upvote 0

Johan Schoeman

Expert
Licensed User
Longtime User
Great work, Last file works nicely!

Only problem is that the shape isn´t inititalized until after Activity_Resume has passed, before that it only returns "UNDETECTED" no mather how long I wait (tried For Next loop, and Do While but no success)

I solved it this way and it seems to work so far. Using a one Tick timer that triggers just after the Resume seems to do the trick.

B4X:
Sub Process_Globals
    Dim timerDetect As Timer
End Sub

Sub Globals
    Dim sw As ShapeWear
End Sub

Sub Activity_Create(FirstTime As Boolean)
    sw.Initialize("")
    sw.ShowWearDeviceShape
    sw.initShapeWear1

    timerDetect.Initialize("TimerDetect",500)
    timerDetect.Enabled = True
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub TimerDetect_Tick

    If sw.Shape = "RECTANGLE" Then
        Activity.LoadLayout("LayoutRect")
    else if sw.Shape = "ROUND" Then
        Activity.LoadLayout("LayoutRound")
    else if sw.Shape = "MOTO" Then
        Activity.LoadLayout("LayoutRound")
    Else
        Activity.LoadLayout("LayoutRect")
    End If
End Sub
That is correct. See the comments in the wrapper and also look at the code in the original Java sample app. It will only detect the shape after Activity_Resume was executed. Best is to move the code that you have in Activity_Create to Activity_Resume.
 
Upvote 0

TpS

Member
Licensed User
Longtime User
That is correct. See the comments in the wrapper and also look at the code in the original Java sample app. It will only detect the shape after Activity_Resume was executed. Best is to move the code that you have in Activity_Create to Activity_Resume.
I´m not exactly sure how Wear handles apps in background, but if an app i paused and then resumed again it will load the Layout again if it´s placed in Activity_Resume.
Tried a couple of ideas before the timer thing and two layouts on top of each other didn´t look so nice :)
 
Upvote 0

Johan Schoeman

Expert
Licensed User
Longtime User
I´m not exactly sure how Wear handles apps in background, but if an app i paused and then resumed again it will load the Layout again if it´s placed in Activity_Resume.
Tried a couple of ideas before the timer thing and two layouts on top of each other didn´t look so nice :)
What about a sub in Resume that is called to check the shape and that sub then calls a sub to load the correct layout? Just a suggestion.
 
Upvote 0

TpS

Member
Licensed User
Longtime User
What about a sub in Resume that is called to check the shape and that sub then calls a sub to load the correct layout? Just a suggestion.
Might work, I just assumed that calling a sub from Resume wouldn´t do it since Resume wasn´t fully executed at that point.
Using a one time Timer seemed quite safe since I´m absolutly sure that both Create and Resume is fully executed.
 
Upvote 0

Uitenhage

Member
Licensed User
Longtime User
Johan, I have a Zen Watch 2 and a Moto 360 2nd gen. The Zen shows RECTANGLE and Height and Width = 320. The Moto shows ROUND as the shape, not MOTO as suggested above, and Height=360, Width=325 (flat bottom).

Any Ideas?
 
Upvote 0

Johan Schoeman

Expert
Licensed User
Longtime User
Johan, I have a Zen Watch 2 and a Moto 360 2nd gen. The Zen shows RECTANGLE and Height and Width = 320. The Moto shows ROUND as the shape, not MOTO as suggested above, and Height=360, Width=325 (flat bottom).

Any Ideas?
I don't have a Wear device so I am shooting in the dark here - but try with the attached library files and see what it reports the shape to be.
 

Attachments

  • ShapeWearNewLibFiles.zip
    7.4 KB · Views: 393
Upvote 0
Top