如何检测手机是否连接到Android Auto

9lowa7mx  于 2023-02-02  发布在  Android
关注(0)|答案(5)|浏览(177)

我正在制作一个应用程序,当手机连接到Android Auto时,它应该会改变自己的行为。它没有任何Auto功能,不会作为Android Auto应用程序进行营销/提交。
有没有办法检测手机是否连接到Android Auto?我知道Auto媒体应用程序可以通过BroadcastReceiver注册com.google.android.gms.car.media.STATUS操作来检测它们的连接状态。文档不是100%清楚,所以这是否也能可靠地用于所有其他非Auto应用程序?

falq053o

falq053o1#

编辑:在Android 12中,该解决方案不再起作用,相反,最好使用此处记录的CarConnection API
我知道这是一个老线索,但由于它首先出现在谷歌,here is the answer from another question

public static boolean isCarUiMode(Context c) {
UiModeManager uiModeManager = (UiModeManager) c.getSystemService(Context.UI_MODE_SERVICE);
if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_CAR) {
    LogHelper.d(TAG, "Running in Car mode");
    return true;
} else {
    LogHelper.d(TAG, "Running on a non-Car mode");
    return false;
}

}

nkcskrwz

nkcskrwz2#

Configuration.UI_MODE_TYPE_CAR在Anroid 12上不起作用。您可以在androidx.car.app:app库中使用CarConnection API。但如果您不需要其他功能,则无法仅为汽车连接导入整个库。
所以我写了一段代码的基础上CarConnection检测Android自动连接,如下:

class AutoConnectionDetector(val context: Context) {

    companion object {
        const val TAG = "AutoConnectionDetector"

        // columnName for provider to query on connection status
        const val CAR_CONNECTION_STATE = "CarConnectionState"

        // auto app on your phone will send broadcast with this action when connection state changes
        const val ACTION_CAR_CONNECTION_UPDATED = "androidx.car.app.connection.action.CAR_CONNECTION_UPDATED"

        // phone is not connected to car
        const val CONNECTION_TYPE_NOT_CONNECTED = 0

        // phone is connected to Automotive OS
        const val CONNECTION_TYPE_NATIVE = 1

        // phone is connected to Android Auto
        const val CONNECTION_TYPE_PROJECTION = 2

        private const val QUERY_TOKEN = 42

        private const val CAR_CONNECTION_AUTHORITY = "androidx.car.app.connection"

        private val PROJECTION_HOST_URI = Uri.Builder().scheme("content").authority(CAR_CONNECTION_AUTHORITY).build()
    }

    private val carConnectionReceiver = CarConnectionBroadcastReceiver()
    private val carConnectionQueryHandler = CarConnectionQueryHandler(context.contentResolver)

    fun registerCarConnectionReceiver() {
        context.registerReceiver(carConnectionReceiver, IntentFilter(ACTION_CAR_CONNECTION_UPDATED))
        queryForState()
    }

    fun unRegisterCarConnectionReceiver() {
        context.unregisterReceiver(carConnectionReceiver)
    }

    private fun queryForState() {
        carConnectionQueryHandler.startQuery(
            QUERY_TOKEN,
            null,
            PROJECTION_HOST_URI,
            arrayOf(CAR_CONNECTION_STATE),
            null,
            null,
            null
        )
    }

    inner class CarConnectionBroadcastReceiver : BroadcastReceiver() {
      // query for connection state every time the receiver receives the broadcast
        override fun onReceive(context: Context?, intent: Intent?) {
            queryForState()
        }
    }

    internal class CarConnectionQueryHandler(resolver: ContentResolver?) : AsyncQueryHandler(resolver) {
        // notify new queryed connection status when query complete
        override fun onQueryComplete(token: Int, cookie: Any?, response: Cursor?) {
            if (response == null) {
                Log.w(TAG, "Null response from content provider when checking connection to the car, treating as disconnected")
                notifyCarDisconnected()
                return
            }
            val carConnectionTypeColumn = response.getColumnIndex(CAR_CONNECTION_STATE)
            if (carConnectionTypeColumn < 0) {
                Log.w(TAG, "Connection to car response is missing the connection type, treating as disconnected")
                notifyCarDisconnected()
                return
            }
            if (!response.moveToNext()) {
                Log.w(TAG, "Connection to car response is empty, treating as disconnected")
                notifyCarDisconnected()
                return
            }
            val connectionState = response.getInt(carConnectionTypeColumn)
            if (connectionState == CONNECTION_TYPE_NOT_CONNECTED) {
                Log.i(TAG, "Android Auto disconnected")
                notifyCarDisconnected()
            } else {
                Log.i(TAG, "Android Auto connected")
                notifyCarConnected()
            }
        }
    }
}

此解决方案适用于android 6~12,如果需要在android 5上检测汽车连接状态,请使用Configuration.UI_MODE_TYPE_CAR解决方案。

6kkfgxo0

6kkfgxo03#

推荐G.Zxuan工作完美,但我们必须在build.gradle中添加依赖项“androidx.car.app:app-projected:1.1.0”

yvfmudvl

yvfmudvl4#

请参见https://developer.android.com/training/cars/apps#car-connection

val Context.isAndroidAutoConnected: LiveData<Boolean>
    get() = CarConnection(this).type
        .map { it == CarConnection.CONNECTION_TYPE_PROJECTION }

app/build.gradle

dependencies {
    implementation 'androidx.car.app:app:1.1.0'
    implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.5.1"
}
kcrjzv8t

kcrjzv8t5#

@G.Zxuan的Kotlin解决方案很好用,我把它转成了Java,还加了监听器接口,在安卓12上测试

public class AutoConnectionDetector {
    private final Context context;
    private static String TAG = "AutoConnectionDetector";
    private final CarConnectionBroadcastReceiver carConnectionReceiver = new CarConnectionBroadcastReceiver();
    private final CarConnectionQueryHandler carConnectionQueryHandler;
    // columnName for provider to query on connection status
    private static final String CAR_CONNECTION_STATE = "CarConnectionState";

    // auto app on your phone will send broadcast with this action when connection state changes
    private final String ACTION_CAR_CONNECTION_UPDATED = "androidx.car.app.connection.action.CAR_CONNECTION_UPDATED";

    // phone is not connected to car
    private static final int CONNECTION_TYPE_NOT_CONNECTED = 0;

    // phone is connected to Automotive OS
    private final int CONNECTION_TYPE_NATIVE = 1;

    // phone is connected to Android Auto
    private final int CONNECTION_TYPE_PROJECTION = 2;

    private final int QUERY_TOKEN = 42;

    private final String CAR_CONNECTION_AUTHORITY = "androidx.car.app.connection";

    private final Uri PROJECTION_HOST_URI = new Uri.Builder().scheme("content").authority(CAR_CONNECTION_AUTHORITY).build();

    public interface OnCarConnectionStateListener {
        void onCarConnected();

        void onCarDisconnected();
    }

    private static OnCarConnectionStateListener listener;

    public void setListener(OnCarConnectionStateListener listener) {
        AutoConnectionDetector.listener = listener;
    }

    public AutoConnectionDetector(Context context) {
        this.context = context;
        carConnectionQueryHandler = new CarConnectionQueryHandler(context.getContentResolver());
    }

    public void registerCarConnectionReceiver() {
        context.registerReceiver(carConnectionReceiver, new IntentFilter(ACTION_CAR_CONNECTION_UPDATED));
        queryForState();
        Log.i(TAG, "registerCarConnectionReceiver: ");
    }

    public void unRegisterCarConnectionReceiver() {
        context.unregisterReceiver(carConnectionReceiver);
        Log.i(TAG, "unRegisterCarConnectionReceiver: ");
    }

    private void queryForState() {
        String[] projection = {CAR_CONNECTION_STATE};
        carConnectionQueryHandler.startQuery(
                QUERY_TOKEN,
                null,
                PROJECTION_HOST_URI,
                projection,
                null,
                null,
                null
        );
    }

    private static void notifyCarConnected() {
        listener.onCarConnected();
    }

    private static void notifyCarDisconnected() {
        listener.onCarDisconnected();
    }

    class CarConnectionBroadcastReceiver extends BroadcastReceiver {
        // query for connection state every time the receiver receives the broadcast
        @Override
        public void onReceive(Context context, Intent intent) {
            queryForState();
        }
    }

    private static class CarConnectionQueryHandler extends AsyncQueryHandler {
        public CarConnectionQueryHandler(ContentResolver contentResolver) {
            super(contentResolver);
        }

        @Override
        protected void onQueryComplete(int token, Object cookie, Cursor response) {
            if (response == null) {
                Log.w(TAG, "Null response from content provider when checking connection to the car, treating as disconnected");
                notifyCarDisconnected();
                return;
            }
            int carConnectionTypeColumn = response.getColumnIndex(CAR_CONNECTION_STATE);
            if (carConnectionTypeColumn < 0) {
                Log.w(TAG, "Connection to car response is missing the connection type, treating as disconnected");
                notifyCarDisconnected();
                return;
            }
            if (!response.moveToNext()) {
                Log.w(TAG, "Connection to car response is empty, treating as disconnected");
                notifyCarDisconnected();
                return;
            }
            int connectionState = response.getInt(carConnectionTypeColumn);

            if (connectionState == CONNECTION_TYPE_NOT_CONNECTED) {
                Log.i(TAG, "Android Auto disconnected");
                notifyCarDisconnected();
            } else {
                Log.i(TAG, "Android Auto connected");
                Log.i(TAG, "onQueryComplete: " + connectionState);
                notifyCarConnected();
            }
        }
    }
}

相关问题