ausgeorge
ausgeorge

Reputation: 1015

AndroidTV Missing DPad functionality

My app is fully usable and navigatable on AndroidTV using the DPad. Well, it certainly is on MY AndroidTV, as well as AVD.

However, Google keeps on rejecting my appeal to have it marked as AndroidTV capable.

There is no feedback, other than

Missing DPad functionality Your app requires user interaction for menus or app navigation. Please make sure that all menus and app navigation are fully functional using a DPad. Please refer to our DPAD Control and Hardware Declaration documentation.

Do you know if they actually test these apps, or do they just look for certain code patterns? The message from them looks automated, and I've not spoken to a person yet.

Would it help if I recorded my app in use and sent them a link to the demonstration?

Upvotes: 12

Views: 4414

Answers (3)

kfir
kfir

Reputation: 745

In my case there were 3 problems.

  1. I had a "Refresh" button that when pressed it was downloading a new image and replaced the current, to the automatic google testing machines - it looks like nothing happens, it was the same image. the fact that I used different drawable to show pressed/released/focused state had nothing to do with it. For those testing machines, if nothing happens then this button has no functionality and the DPAD probably is not working. I have added a simple Toast message that launches every time a user presses the button.
  2. I have contacted support from the link in the rejection email - they are very supportive. they have sent me explanation that includes an old screenshot. apparently - they were using an old version - I don't know why. After explanation - they checked the correct one.
  3. also, they test mostly the production version while most of my development was on the beta version. advance your version to production. in my case partial release of 5 percent was good enough for them to test the new production version.

after all of those measures - 12 hours later - I was approved. Now, I have removed the toast and my app was still accepted.

Update - 4/11/2024:

contacting support did not help. needed to override onKeydown which is what the pad buttons needs - and implement toasts everywhere. especially the volume buttons

int currentVolume = 50;
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    try {
            switch (keyCode) {
                case KeyEvent.KEYCODE_DPAD_UP:
                    if (remotevideoTrack != null && audioTrack != null ) {
                        currentVolume = Math.min(currentVolume + 5, 100);
                        audioTrack.setVolume(currentVolume);
                        ToastMeVeryShort("volume:" + currentVolume);
                    }
                    else
                        ToastMeVeryShort("no connection");

                    return true;
                case KeyEvent.KEYCODE_MEDIA_PLAY:
                    if (remotevideoTrack != null && audioTrack != null ) {
                        ToastMeVeryShort("running already");
                    }
                    else
                        ToastMeVeryShort("no connection");
                    return true;
                case KeyEvent.KEYCODE_MEDIA_PAUSE:
                    if (remotevideoTrack != null && audioTrack != null ) {
                        ToastMeVeryShort("running already");
                    }
                    else
                        ToastMeVeryShort("no connection");
                    return true;
                case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
                    if (remotevideoTrack != null && audioTrack != null ) {
                        ToastMeVeryShort("running already");
                    }
                    else
                        ToastMeVeryShort("no connection");
                    return true;
                case KeyEvent.KEYCODE_DPAD_DOWN:
                    if (remotevideoTrack != null && audioTrack != null ) {
                        if (audioTrack != null) {
                            currentVolume = Math.max(currentVolume - 5, 0);
                            audioTrack.setVolume(currentVolume);
                            ToastMeVeryShort("volume:" + currentVolume);
                        }

                    }
                    else
                        ToastMeVeryShort("no connection");
                    return true;
                case KeyEvent.KEYCODE_DPAD_RIGHT:                       
                    return   super.onKeyDown(keyCode, event);
                case KeyEvent.KEYCODE_DPAD_LEFT:
                    return   super.onKeyDown(keyCode, event);                        
                case KeyEvent.KEYCODE_BACK: {
                    if (remotevideoTrack != null && audioTrack != null ) {
                        ToastMeVeryShort("bye");
                    }
                    try {
                        SayByeAndClose();
                    } catch (Exception ex) {
                        Log.e(TAG, ex.toString());
                    }

                    try{
                        finish();
                        System.exit(0);
                    } catch (Exception ex) {
                        Log.e(TAG, ex.toString());
                    }

                    return true;
                }
            }
    }
    catch (Exception ex)
    {
        Log.e(TAG, ex.toString());
    }
    return false;
}

Upvotes: 2

user21930091
user21930091

Reputation: 1

im facing the same problem.. i tested in fire tv and TV emulator and i think the dpad function is good..

Here is my manifest files

  <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.hsvision.hsvplay.android.tv">
<!--
     io.flutter.app.FlutterApplication is an android.app.Application that
     calls FlutterMain.startInitialization(this); in its onCreate method.
     In most cases you can leave this as-is, but you if you want to provide
     additional functionality it is fine to subclass or reimplement
     FlutterApplication and put your custom class here.
-->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />


<uses-feature android:name="android.hardware.touchscreen"
    android:required="false"/>
<uses-feature android:name="android.hardware.faketouch"
    android:required="false"/>
<uses-feature android:name="android.hardware.telephony"
    android:required="false"/>
<uses-feature android:name="android.hardware.camera"
    android:required="false"/>
<uses-feature android:name="android.hardware.nfc"
    android:required="false"/>
<uses-feature android:name="android.hardware.location.gps"
    android:required="false"/>
<uses-feature android:name="android.hardware.microphone"
    android:required="false"/>
<uses-feature android:name="android.hardware.sensor"
    android:required="false"/>
<uses-feature android:name="android.software.leanback"
    android:required="true" />
<uses-feature android:name="android.hardware.wifi"
    android:required="false"/>

<application
    android:usesCleartextTraffic="true"
    android:banner="@drawable/banner"
    android:icon="@drawable/banner"
    android:label="HSV PLAY TV"
    android:theme="@style/Theme.Leanback">

    <meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/facebook_app_id"/>

    <activity android:name="com.facebook.FacebookActivity"
        android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"
        android:label="@string/app_name" />
    <activity
        android:name="com.facebook.CustomTabActivity"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:scheme="@string/fb_login_protocol_scheme" />
        </intent-filter>
    </activity>

    <activity
        android:exported="true"
        android:name=".MainActivity"
        android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
        android:hardwareAccelerated="true"
        android:launchMode="singleTop"
        android:theme="@style/LaunchTheme"
        android:windowSoftInputMode="adjustResize" >

        <!--
             Specifies an Android theme to apply to this Activity as soon as
             the Android process has started. This theme is visible to the user
             while the Flutter UI initializes. After that, this theme continues
             to determine the Window background behind the Flutter UI.
        -->
        <meta-data
            android:name="io.flutter.embedding.android.NormalTheme"
            android:resource="@style/NormalTheme" />
        <!--
             Displays an Android View that continues showing the launch screen
             Drawable until Flutter paints its first frame, then this splash
             screen fades out. A splash screen is useful to avoid any visual
             gap between the end of Android's launch screen and the painting of
             Flutter's first frame.
        -->
        <meta-data
            android:name="io.flutter.embedding.android.SplashScreenDrawable"
            android:resource="@drawable/launch_background" />

        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LEANBACK_LAUNCHER" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <!--

Don't delete the meta-data below. This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->

Upvotes: 0

TheHavays
TheHavays

Reputation: 11

AndroidTV applications support and expects leanback activities. Also, D-pad needs to minimum remote controller support like up, down, left, right, select, Back, and Home buttons.

D-pad minimum controls The default controller for a TV device is a D-pad. In general, your app should be operable from a remote controller that only has up, down, left, right, select, Back, and Home buttons. If your app is a game that typically requires a game controller with additional controls, your app should attempt to allow gameplay with these D-pad controls. In this case, your app should also warn the user that a controller is required and allow them to exit your game gracefully using the D-pad controller. For more information about handling navigation with D-pad controller for TV devices, see Create TV navigation.

Adding the below lines to your main activity in AndroidManifest.xml may help Dpad support.

        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.LAUNCHER" />
            <category android:name="android.intent.category.LEANBACK_LAUNCHER" />
        </intent-filter>

If its not working and these lines already in manifest please share your manifest file.

Upvotes: 0

Related Questions