package com.fujica.abk.slice; import com.fujica.abk.ResourceTable; import com.fujica.abk.api.cache; import com.fujica.abk.utils.Log; import com.fujica.abk.utils.Toast; import com.fujica.abk.utils.api; import com.huawei.hms.accountsdk.constant.CommonConstant; import com.huawei.hms.accountsdk.exception.ApiException; import com.huawei.hms.accountsdk.support.account.AccountAuthManager; import com.huawei.hms.accountsdk.support.account.request.AccountAuthParams; import com.huawei.hms.accountsdk.support.account.request.AccountAuthParamsHelper; import com.huawei.hms.accountsdk.support.account.result.AuthAccount; import com.huawei.hms.accountsdk.support.account.service.AccountAuthService; import com.huawei.hms.accountsdk.support.account.tasks.OnFailureListener; import com.huawei.hms.accountsdk.support.account.tasks.OnSuccessListener; import com.huawei.hms.accountsdk.support.account.tasks.Task; import com.huawei.hms.maps.harmony.*; import com.huawei.hms.maps.harmony.model.CameraPosition; import com.huawei.hms.maps.harmony.model.LatLng; import com.huawei.hms.maps.harmony.model.Marker; import com.huawei.hms.maps.harmony.model.MarkerOptions; import ohos.aafwk.ability.AbilitySlice; import ohos.aafwk.ability.DataAbilityHelper; import ohos.aafwk.ability.IDataAbilityObserver; import ohos.aafwk.content.Intent; import ohos.account.AccountAbility; import ohos.agp.colors.RgbColor; import ohos.agp.colors.StateColor; import ohos.agp.components.*; import ohos.agp.components.element.ShapeElement; import ohos.agp.utils.Color; import ohos.agp.window.dialog.ToastDialog; import ohos.agp.window.service.Window; import ohos.agp.window.service.WindowManager; import ohos.global.resource.NotExistException; import ohos.global.resource.Resource; import ohos.location.Location; import ohos.location.Locator; import ohos.location.LocatorCallback; import ohos.location.RequestParam; import ohos.sysappcomponents.settings.AppSettings; import ohos.sysappcomponents.settings.SystemSettings; import java.io.IOException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; public class MainAbilitySlice extends AbilitySlice { // PageSlider相关 private PageSlider pageSlider; private PageSliderProvider pageSliderProvider; // 底部导航栏组件 private DirectionalLayout navMy; private DirectionalLayout navFindParking; private DirectionalLayout navReserveParking; private DirectionalLayout navCurrentLocation; // 底部导航栏文字和图标 private Text textMy; private Text textPark; private Text textFee; private Image iconPark; private Image iconPark1; private Image iconMy; private Image iconMy1; private Image iconFee; private Image iconFee1; // 当前选中的 tab private int currentTab = 1; // 0: 我的, 1: 找车位, 2: 预约停车 // 定位相关 private Locator locator; private LocatorCallback locatorCallback; private Location currentLocation; // 当前定位坐标 // 地图相关 - 完全按照 MarkerDemo 的方式 private HuaweiMap mHuaweiMap; /** * Declare a MapView object. */ private MapView mMapView; /** * Declare a Marker object. */ private Marker mMarker; /** * 当前位置标记 */ private Marker currentLocationMarker; DataAbilityHelper dataAbilityHelper; IDataAbilityObserver dataAbilityObserver; @Override public void onStart(Intent intent) { super.onStart(intent); cache.setToken(getContext(), "sdfdsfdsf11111111111"); String token = cache.getToken(getContext()); // api.http(getContext(), "http://www.baidu.com", "GET", null, null, null); api.http(getContext(), "/park/near/page?longitude=0&latitude=0", "GET", null, null, null); // 设置全屏显示 setFullScreen(); // 设置 CommonContext,华为地图需要 - 完全按照示例代码 CommonContext.setContext(this); // 设置布局 super.setUIContent(ResourceTable.Layout_ability_main); // 初始化组件 initComponents(); // 初始化地图 - 完全按照 MarkerDemo 的方式 initMap(); // 设置事件监听 setupListeners(); // 初始化定位 initLocation(); Button mBtnHuaweiIdSignIn = findComponentById(ResourceTable.Id_btn_hwid_sign_in); mBtnHuaweiIdSignIn.setClickedListener((Component c) -> { huaweiIdSignIn(); }); final String key = "car_license_plate_number"; // final String key = SystemSettings.Date.TIME_FORMAT; dataAbilityHelper = DataAbilityHelper.creator(this); dataAbilityObserver = () -> { String timeFormat = SystemSettings.getValue(dataAbilityHelper, key); setTimeFormat(timeFormat); }; dataAbilityHelper.registerObserver(SystemSettings.getUri(key), dataAbilityObserver); String timeFormat1 = SystemSettings.getValue(dataAbilityHelper, "car_license_plate_number"); String timeFormat = SystemSettings.getValue(dataAbilityHelper, key); } void setTimeFormat(String timeFormat) { String timeStr = "12"; if (timeStr.equals(timeFormat)) { // Display in 12-hour format } else { // Display in 24-hour format } } void huaweiIdSignIn() { AccountAuthService accountAuthService; // 1、配置登录请求参数AccountAuthParams,包括请求用户id(openid、unionid)、email、profile(昵称、头像)等。 // 2、DEFAULT_AUTH_REQUEST_PARAM默认包含了id和profile(昵称、头像)的请求。 // 3、如需要再获取用户邮箱,需要setEmail(); // 4、如需要获取其他受限信息,如国家和地区,则需要先申请scope,再设置请求参数。 AccountAuthParams accountAuthParams = new AccountAuthParamsHelper(AccountAuthParams.DEFAULT_AUTH_REQUEST_PARAM) .setEmail() .createParams(); try { accountAuthService = AccountAuthManager.getService(accountAuthParams); } catch (ApiException e) { // 处理初始化登录授权服务失败,status code标识了失败的原因,请参考API中的错误码参考了解详细错误原因 e.getStatusCode(); Toast.error(getContext(),"Init Huawei accountAuthService FAILED."); return; } Toast.info(getContext(),"Init Huawei accountAuthService SUCCESS"); if (accountAuthService == null) { Toast.error(getContext(),"获取不到账号信息"); return; } // 调用静默登录接口。 // 如果华为系统帐号已经登录,并且已经授权,会登录成功; // 否则静默登录失败,需要在失败监听中,显式地调用前台登录授权接口,完成登录授权。 Task taskSilentSignIn = accountAuthService.silentSignIn(); // Task taskSilentSignIn = accountAuthService.silentSignIn(); Toast.info(getContext(),"SilentSign START."); // 添加静默登录成功处理监听 taskSilentSignIn.addOnSuccessListener(authAccount -> updateUI(authAccount)); // 添加静默登录失败监听 taskSilentSignIn.addOnFailureListener(e -> { if (e instanceof ApiException) { ApiException apiException = (ApiException) e; Toast.error(getContext(),"SilentSignIn FAILED, status code: " + apiException.getStatusCode() + ". Need to foreground sign in" + "\r\n" + apiException.getStatusMessage() + "\r\n" + apiException.getMessage() + "\r\n" + apiException.getCause()); // 静默登录失败,显式地调用前台登录授权接口,完成登录授权。 Task taskSignIn = accountAuthService.signIn(); Toast.info(getContext(),"SignIn foreground START."); if (taskSignIn == null) { Toast.info(getContext(),"SignIn foreground task is null."); return; } taskSignIn.addOnSuccessListener(new OnSuccessListener() { @Override public void onSuccess(AuthAccount result) { Toast.info(getContext(),"SignIn foreground SUCCESS."); updateUI(result); } }); taskSignIn.addOnFailureListener(new OnFailureListener() { @Override public void onFailure(Exception e) { Toast.info(getContext(),"SignIn foreground FAILED."); if (e instanceof ApiException) { ApiException apiException = (ApiException) e; // 登录失败,status code标识了失败的原因,请参考API中的错误码参考了解详细错误原因 apiException.getStatusCode(); Toast.info(getContext(),"SignIn foreground FAILED. status code: " + apiException.getStatusCode() + "."); if (CommonConstant.RETCODE.SIGN_IN_CANCELLED == apiException.getStatusCode()) { Toast.info(getContext(),"Error message: User click CANCEL or Return, user cancel login in."); } } } }); } }); } private void updateUI(AuthAccount authAccount) { Toast.info(getContext(),authAccount.getOpenId() + " : " + authAccount.getUnionId()); } /** * 设置全屏显示 */ private void setFullScreen() { try { Window window = getWindow(); if (window != null) { WindowManager.LayoutConfig layoutConfig = window.getLayoutConfig().orElse(null); if (layoutConfig == null) { layoutConfig = new WindowManager.LayoutConfig(); } layoutConfig.type = WindowManager.LayoutConfig.MARK_FULL_SCREEN; window.setLayoutConfig(layoutConfig); } } catch (Exception e) { Log.error("设置全屏失败: " + e.getMessage()); } } /** * 初始化组件 */ private void initComponents() { // 初始化PageSlider pageSlider = (PageSlider) findComponentById(ResourceTable.Id_page_slider); if (pageSlider != null) { // 创建PageSliderProvider pageSliderProvider = new PageSliderProvider() { private List pages = new ArrayList<>(); @Override public int getCount() { return 3; // 三个页面:我的、找车位、预约停车 } @Override public Object createPageInContainer(ComponentContainer componentContainer, int position) { Component page = null; try { switch (position) { case 0: // 我的 page = LayoutScatter.getInstance(MainAbilitySlice.this) .parse(ResourceTable.Layout_layout_my, null, false); break; case 1: // 找车位 page = LayoutScatter.getInstance(MainAbilitySlice.this) .parse(ResourceTable.Layout_layout_find_parking, null, false); break; case 2: // 预约停车 page = LayoutScatter.getInstance(MainAbilitySlice.this) .parse(ResourceTable.Layout_layout_reserve_parking, null, false); break; } if (page != null) { componentContainer.addComponent(page); pages.add(page); } } catch (Exception e) { Log.error("创建页面失败: " + e.getMessage()); e.printStackTrace(); } return page; } @Override public void destroyPageFromContainer(ComponentContainer componentContainer, int position, Object object) { if (object instanceof Component) { componentContainer.removeComponent((Component) object); pages.remove(object); } } @Override public boolean isPageMatchToObject(Component component, Object object) { return component == object; } }; pageSlider.setProvider(pageSliderProvider); // 默认显示找车位页面(索引1) pageSlider.setCurrentPage(1); // 添加页面切换监听 pageSlider.addPageChangedListener(new PageSlider.PageChangedListener() { @Override public void onPageChosen(int index) { // 页面切换完成 currentTab = index; updateBottomNavState(index); Log.info("切换到页面: " + index); } @Override public void onPageSliding(int state, float v, int index) { } @Override public void onPageSlideStateChanged(int state) { // 滑动状态变化 } }); } // 初始化底部导航栏 initBottomNavigation(); } /** * 初始化底部导航栏 */ private void initBottomNavigation() { navMy = findComponentById(ResourceTable.Id_nav_my); navFindParking = findComponentById(ResourceTable.Id_nav_find_parking); navReserveParking = findComponentById(ResourceTable.Id_nav_reserve_parking); navCurrentLocation = findComponentById(ResourceTable.Id_nav_current_location); textMy = findComponentById(ResourceTable.Id_text_my); textPark = findComponentById(ResourceTable.Id_text_park); textFee = findComponentById(ResourceTable.Id_text_fee); iconPark = findComponentById(ResourceTable.Id_icon_park); iconPark1 = findComponentById(ResourceTable.Id_icon_park_1); iconMy = findComponentById(ResourceTable.Id_icon_my); iconMy1 = findComponentById(ResourceTable.Id_icon_my_1); iconFee = findComponentById(ResourceTable.Id_icon_fee); iconFee1 = findComponentById(ResourceTable.Id_icon_fee_1); // 设置点击事件 if (navMy != null) { navMy.setClickedListener(component -> switchToPage(0)); } if (navFindParking != null) { navFindParking.setClickedListener(component -> switchToPage(1)); } if (navReserveParking != null) { navReserveParking.setClickedListener(component -> switchToPage(2)); } if (navCurrentLocation != null) { navCurrentLocation.setClickedListener(component -> { Log.info("点击了当前位置按钮"); locateCurrentPosition(); }); } // 默认选中找车位 updateBottomNavState(1); } /** * 切换到指定页面 */ private void switchToPage(int index) { if (pageSlider != null && index >= 0 && index < 3) { pageSlider.setCurrentPage(index); } } /** * 更新底部导航栏状态 */ private void updateBottomNavState(int index) { // 重置所有导航项样式 Color grayColor = new Color(Color.getIntColor("#FF666666")); Color blueColor = new Color(Color.getIntColor("#FA6332")); if (textMy != null) { textMy.setTextColor(grayColor); } if (textPark != null) { textPark.setTextColor(grayColor); } if (textFee != null) { textFee.setTextColor(grayColor); } iconPark.setImageAndDecodeBounds(ResourceTable.Media_park); iconMy.setImageAndDecodeBounds(ResourceTable.Media_my); // iconReserveParking.setImageAndDecodeBounds(ResourceTable.Media_fee); // 设置选中状态 switch (index) { case 0: // 我的 textMy.setTextColor(blueColor); iconMy.setImageAndDecodeBounds(ResourceTable.Media_my_1); iconMy.setVisibility(Component.HIDE); iconMy1.setVisibility(Component.VISIBLE); iconFee.setVisibility(Component.VISIBLE); iconFee1.setVisibility(Component.HIDE); iconPark.setVisibility(Component.VISIBLE); iconPark1.setVisibility(Component.HIDE); break; case 1: // 找车位 textPark.setTextColor(blueColor); iconPark.setImageAndDecodeBounds(ResourceTable.Media_park_1); iconMy.setVisibility(Component.VISIBLE); iconMy1.setVisibility(Component.HIDE); iconFee.setVisibility(Component.VISIBLE); iconFee1.setVisibility(Component.HIDE); iconPark.setVisibility(Component.HIDE); iconPark1.setVisibility(Component.VISIBLE); break; case 2: // 预约停车 textFee.setTextColor(blueColor); iconMy.setVisibility(Component.VISIBLE); iconMy1.setVisibility(Component.HIDE); iconFee.setVisibility(Component.HIDE); iconFee1.setVisibility(Component.VISIBLE); iconPark.setVisibility(Component.VISIBLE); iconPark1.setVisibility(Component.HIDE); break; } } /** * 初始化地图 - 完全按照 MarkerDemo 的方式 */ private void initMap() { try { // Declaring and Initializing the HuaweiMapOptions Object - 完全按照 MarkerDemo HuaweiMapOptions huaweiMapOptions = new HuaweiMapOptions(); // Initialize Camera Properties CameraPosition cameraPosition = new CameraPosition(new LatLng(48.893478, 2.334595), 6, 0, 0); huaweiMapOptions // Set Camera Properties .camera(cameraPosition) // Enables or disables the zoom function. By default, the zoom function is enabled. .zoomControlsEnabled(false) // Sets whether the compass is available. The compass is available by default. .compassEnabled(true) // Specifies whether the zoom gesture is available. By default, the zoom gesture is available. .zoomGesturesEnabled(true) // Specifies whether to enable the scrolling gesture. By default, the scrolling gesture is enabled. .scrollGesturesEnabled(true) // Specifies whether the rotation gesture is available. By default, the rotation gesture is available. .rotateGesturesEnabled(false) // Specifies whether the tilt gesture is available. By default, the tilt gesture is available. .tiltGesturesEnabled(true) // Sets whether the map is in lite mode. The default value is No. .liteMode(false) // Set Preference Minimum Zoom Level .minZoomPreference(3) // Set Preference Maximum Zoom Level .maxZoomPreference(13); if (true) return; // Initialize MapView Object. - 完全按照 MarkerDemo mMapView = new MapView(this, huaweiMapOptions); mMapView.onCreate(); // Obtains the HuaweiMap object. - 完全按照 MarkerDemo mMapView.getMapAsync(huaweiMap -> { mHuaweiMap = huaweiMap; // If mHuaweiMap is null, the program stops running. - 完全按照 MarkerDemo if (null == mHuaweiMap) { Log.error("mHuaweiMap 为 null"); return; } Log.info("地图已就绪,开始获取定位"); mHuaweiMap.setOnMapClickListener(new OnMapClickListener() { @Override public void onMapClick(LatLng latLng) { new ToastDialog(CommonContext.getContext()).setText("onMapClick ").show(); } }); // If mMarker is not null, remove it from the map and then set it to null. - 完全按照 MarkerDemo if (null != mMarker) { mMarker.remove(); mMarker = null; } // Add a marker to the map. - 完全按照 MarkerDemo MarkerOptions options = new MarkerOptions() .position(new LatLng(48.893478, 2.334595)) .title("Hello Huawei Map") .snippet("This is a snippet!"); mMarker = mHuaweiMap.addMarker(options); // Set the marker title. - 完全按照 MarkerDemo if (mMarker != null) { mMarker.setTitle("Marker title"); } // Set whether the marker can be dragged. - 完全按照 MarkerDemo if (mMarker != null) { mMarker.setDraggable(true); } // Set the marker anchor point. - 完全按照 MarkerDemo if (mMarker != null) { mMarker.setMarkerAnchor(0.9F, 0.9F); } // Customizing the Marker Icon - 完全按照 MarkerDemo addCustomMarker(); mHuaweiMap.setOnMarkerClickListener(new OnMarkerClickListener() { @Override public boolean onMarkerClick(Marker marker) { new ToastDialog(CommonContext.getContext()).setText("onMarkerClick: " + marker.getTitle()).show(); return false; } }); mHuaweiMap.setOnInfoWindowClickListener(new OnInfoWindowClickListener() { @Override public void onInfoWindowClick(Marker marker) { new ToastDialog(CommonContext.getContext()).setText("onInfoWindowClick:").show(); } }); // 地图就绪后,自动获取当前位置 if (locator != null && locatorCallback != null) { locateCurrentPosition(); } }); // ComponentContainer.LayoutConfig config = new ComponentContainer.LayoutConfig(ComponentContainer.LayoutConfig.MATCH_PARENT, ComponentContainer.LayoutConfig.MATCH_PARENT); // PositionLayout myLayout = new PositionLayout(this); // myLayout.setLayoutConfig(config); PositionLayout myLayout = findComponentById(ResourceTable.Id_main_body); ShapeElement element = new ShapeElement(); element.setShape(ShapeElement.RECTANGLE); element.setRgbColor(new RgbColor(255, 255, 255)); // 加载MapView myLayout.addComponent(mMapView); } catch (Exception e) { Log.error("初始化地图失败: " + e.getMessage()); e.printStackTrace(); } } /** * addCustomMarker - 完全按照 MarkerDemo */ private void addCustomMarker() { Resource resource = null; try { resource = getResourceManager().getResource(ResourceTable.Media_icon); } catch (IOException e) { e.printStackTrace(); } catch (NotExistException e) { e.printStackTrace(); } if (resource != null && mHuaweiMap != null) { mHuaweiMap.addMarker(new MarkerOptions() .position(new LatLng(47.8333, 2.8333)) .icon(resource)); } } /** * 设置事件监听 */ private void setupListeners() { // 事件监听已在initBottomNavigation中设置 } /** * 初始化定位服务 */ private void initLocation() { try { locator = new Locator(this); locatorCallback = new LocatorCallback() { @Override public void onLocationReport(Location location) { // 保存当前位置坐标 currentLocation = location; double latitude = location.getLatitude(); double longitude = location.getLongitude(); Log.info("定位成功: " + latitude + ", " + longitude); // 将坐标传递给地图 updateMapWithLocation(location); } @Override public void onStatusChanged(int type) { Log.info("定位状态变化: " + type); } @Override public void onErrorReport(int errorCode) { Log.error("定位错误: " + errorCode); new ToastDialog(CommonContext.getContext()) .setText("定位失败,错误码: " + errorCode) .show(); } }; } catch (Exception e) { Log.error("初始化定位服务失败: " + e.getMessage()); } } /** * 定位到当前位置 */ private void locateCurrentPosition() { if (locator == null || locatorCallback == null) { Log.error("定位服务未初始化"); return; } try { // 请求定位 RequestParam requestParam = new RequestParam(RequestParam.PRIORITY_ACCURACY, 0, 0); locator.startLocating(requestParam, locatorCallback); Log.info("开始定位..."); } catch (Exception e) { Log.error("定位失败: " + e.getMessage()); } } /** * 将定位坐标传递给地图并更新地图显示 */ private void updateMapWithLocation(Location location) { if (mHuaweiMap == null) { Log.warn("地图未初始化完成,等待地图就绪"); return; } try { double latitude = location.getLatitude(); double longitude = location.getLongitude(); Log.info("更新地图位置: " + latitude + ", " + longitude); // 创建坐标点 LatLng latLng = new LatLng(latitude, longitude); // 移除旧的当前位置标记 if (currentLocationMarker != null) { currentLocationMarker.remove(); currentLocationMarker = null; } // 在地图上添加当前位置标记 MarkerOptions currentLocationOptions = new MarkerOptions() .position(latLng) .title("当前位置") .snippet("纬度: " + latitude + ", 经度: " + longitude); currentLocationMarker = mHuaweiMap.addMarker(currentLocationOptions); // Method 8: Set the center point and zoom level of the camera. - 完全按照示例代码 float zoom = 15.0f; CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, zoom); // move camera - 完全按照示例代码 mHuaweiMap.moveCamera(cameraUpdate); Log.info("地图已更新到当前位置"); // 显示提示 new ToastDialog(CommonContext.getContext()) .setText("已定位到当前位置") .show(); } catch (Exception e) { Log.error("更新地图位置失败: " + e.getMessage()); e.printStackTrace(); } } /** * 移动地图到当前位置 - 完全按照 MapViewCameraDemo 的方式 */ private void moveToCurrentLocation(Location location) { updateMapWithLocation(location); } // 生命周期管理 - 完全按照示例代码 MapViewDemo.java 的方式 @Override protected void onActive() { super.onActive(); if (mMapView != null) { mMapView.onResume(); } } @Override protected void onInactive() { super.onInactive(); if (mMapView != null) { mMapView.onPause(); } } @Override protected void onBackground() { super.onBackground(); if (mMapView != null) { mMapView.onStop(); } } @Override protected void onForeground(Intent intent) { super.onForeground(intent); if (mMapView != null) { mMapView.onStart(); } } @Override protected void onStop() { super.onStop(); // 停止定位 if (locator != null && locatorCallback != null) { try { locator.stopLocating(locatorCallback); } catch (Exception e) { Log.error("停止定位失败: " + e.getMessage()); } } // 销毁地图 - 完全按照示例代码 if (mMapView != null) { mMapView.onDestroy(); } if (dataAbilityHelper != null) { } dataAbilityHelper.unregisterObserver(SystemSettings.getUri(SystemSettings.Date.TIME_FORMAT), dataAbilityObserver); } }