I'm looking for a technique to determine in Java if the Android Wear device screen is round or rectangular. Note that this isn't just about layouts; my code actually needs to know which shape it's working with, because they're handled differently.
As far as I can see from code samples online, two different approaches should be possible - but I've been unable to get either of them to work. I'll include them here to eliminate them from the running, or for possible troubleshooting (if anyone can see the problem with them). Please don't refer me to another SO post that just reiterates the solutions that aren't working for me here.
Note that all code here is running on the watch. Also, I'm still using Eclipse, FWIW.
The most straightforward method I've seen involves adding an onApplyWindowInsets()
listener to a view in my layout. So I created a listener that looks like this:
@Override
public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
if (insets.isRound()) {
displayShape = "round";
} else {
displayShape = "rectangular";
}
return null;
}
and added it to the root view of my layout with code like this:
view.setOnApplyWindowInsetsListener(this);
in my onCreate() method. Looks OK as far as it goes - but the listener never gets called. I also found advice saying that I needed to invoke it manually, as such:
view.requestApplyInsets();
but that didn't seem to make any difference. I've experimented with putting it on different views, in different lifecycle methods, and so forth, but never once saw it actually get called in my app. This is running on my LG G Watch, BTW.
The second approach is something of a hack, and is based on the published WatchViewStub
helper class. I jumped through the hoops to get the wearable support library imported into an Eclipse project, then added the following to my root layout:
<android.support.wearable.view.WatchViewStub
android:id="@+id/watch_view_stub"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:rectLayout="@layout/rect"
app:roundLayout="@layout/round"
/>
and created rect.xml
as such:
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/layout_type"
android:text="rectangular"
/>
and round.xml
like this:
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/layout_type"
android:text="round"
/>
Finally, in my onCreate()
I added the following Java code:
final WatchViewStub stub = (WatchViewStub) findViewById(R.id.watch_view_stub);
stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {
@Override
public void onLayoutInflated(WatchViewStub stub) {
TextView layoutType = (TextView) findViewById(R.id.layout_type);
displayShape = layoutType.getText().toString();
}
});
It's a long way around the block, but it should work, right? Not so much... displayShape
is always set to "rectangular"
, indicating that it's always rect.xml
that gets used, even when running on a round emulator. [I don't have round-screened hardware to try it on just yet.]
So does anyone see where I've gone wrong with either of these two approaches? Or can you suggest a third way which actually works?
After several days spent chasing false leads, I've finally found the answer. It turns out that it's the android:theme
of the application in the manifest that makes the difference.
In order for WatchViewStub
to use the correct rect/round layouts, it appears that your application must use @android:style/Theme.DeviceDefault
as its theme. Here's an example:
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@android:style/Theme.DeviceDefault">
I expect it would also work if you used a theme that inherited from DeviceDefault
, though I haven't tested that. But it appears that if you use any other custom theme, WatchViewStub
will not function correctly.
@WaynePiekarski, it'd be nice if this was documented somehere.
Also, here are a couple of other tips that I learned along the way:
The rectangular layout always inflates before the round layout; IOW, on a round device, you'll get two onLayoutInflated()
callbacks. This is kind of a pain if you're using the layout inflation to get the screen shape into your Java code, and that turns out to be necessary, because...
Calling setOnApplyWindowInsetsListener()
on WatchViewStub
prevents the round layout from loading at all (at least in my testing). So if you try to use this callback to determine the screen shape, round devices will still get the square layout.
Finally, a bonus question: Is there any good reason why Android Wear doesn't just report its screen shape as a resource qualifier? You know, like -land
, -large
, and so on. Why on earth do we need to mess around with WatchViewStub
at all?
I'm not sure why it's necessary in your case to employ a callback, but an answer the general question of screen shape is here: Is there any way to detect if the clock is round?
That is, to acquire the current context, and test
context.getResources().getConfiguration().isScreenRound()
In CanvasWatchFaceService.Engine their is a overide method available setOnApplyWindowInsets you can check whether insets is round or square
@Override
public void onApplyWindowInsets(WindowInsets insets) {
super.onApplyWindowInsets(insets);
if(insets.isRound()){
//round
}
else{
//square
}
}
https://plus.google.com/+NicolasPomepuy/posts/ZJ3KZK6uu2e#+NicolasPomepuy/posts/ZJ3KZK6uu2e
and from https://github.com/PomepuyN/WatchviewStubIssue/blob/bcad0de7fa473c757dc27f9dfe65e31561c6097f/wear/src/main/java/com/example/watchviewstubissue/ViewService.java
mainView.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
51 @Override
52 public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
53 if (insets.isRound()) {
54 Log.d("ViewService", "Round");
55 } else {
56 Log.d("ViewService", "Square");
57 }
58 return insets;
59 }
60 });
The diff between your code and his is that you are returning null and he is returning insets.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With