service Intent "com.baidu.location.f"错误解决

本文介绍了一个在使用百度地图SDK时遇到的定位服务未找到的问题,并提供了具体的解决方案,即在AndroidManifest.xml文件中正确声明对应的服务组件。

1。 详细错误:

       在进行百度地图开发时,定位功能总是报错,如下:

Unable to start service Intent { cmp=com.actionbarsherlock.sample.fragments/com.baidu.location.f }: not found


2。 分析与解决:

     service没有找到,那么,去manifest文件中看一下,果然没有加入这个internt,

解决:将对应的internt加到manifest文件中,如下:

<service
            android:name="com.baidu.location.f"
            android:enabled="true"
            android:process=":remote" >
        </service>

问题解决。

package com.ahjswy.cn.ui; import android.Manifest; import android.app.ActionBar; import android.app.Activity; import android.app.Notification; import android.app.PendingIntent; import android.content.Intent; import android.content.pm.PackageManager; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.util.Log; import android.view.KeyEvent; import android.view.MenuItem; import android.widget.Toast; import com.ahjswy.cn.R; import com.ahjswy.cn.app.MyApplication; import com.ahjswy.cn.app.RequestHelper; import com.ahjswy.cn.app.SystemState; import com.ahjswy.cn.baiduservice.JobWakeUpService; import com.ahjswy.cn.baiduservice.MyService; import com.ahjswy.cn.baiduservice.NotificationUtils; import com.ahjswy.cn.service.ServiceUser; import com.ahjswy.cn.ui.outgoods.OutDocEditActivity; import com.ahjswy.cn.utils.PDH; import com.ahjswy.cn.utils.ServiceUtil; import com.ahjswy.cn.utils.SpeechUtils; import com.baidu.location.BDAbstractLocationListener; import com.baidu.location.BDLocation; import com.baidu.location.LocationClient; import com.baidu.location.LocationClientOption; import com.baidu.mapapi.map.MapStatus; import com.baidu.mapapi.map.MapStatusUpdateFactory; import com.baidu.mapapi.map.MyLocationData; import com.baidu.mapapi.model.LatLng; import java.util.ArrayList; public class BaseActivity extends Activity { private ActionBar actionBar; public boolean isModify = true; protected Handler mHandler; public void actionBarClickBack() { getActionBar().setDisplayOptions(4); } public void exit() { MyApplication.getInstance().exit(); } public void onBackPressed() { super.onBackPressed(); MyApplication.getInstance().getActivityManager().popActivity(this); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); SystemState.enableStrictMode(); MyApplication.getInstance().getActivityManager().pushActivity(this); this.mHandler = new Handler(); // if(!ServiceUtil.isServiceExisted(this,MyService.class.getName())) { // location(); // } } protected void onDestroy() { MyApplication.getInstance().getActivityManager().popActivity(this); super.onDestroy(); } public boolean onOptionsItemSelected(MenuItem menu) { switch (menu.getItemId()) { case android.R.id.home: finish(); break; } return super.onOptionsItemSelected(menu); } protected void onResume() { super.onResume(); this.actionBar = getActionBar(); if (this.actionBar != null) { this.actionBar.setHomeButtonEnabled(true); setActionBarText(); } } public void refreshUI() { } public void setActionBarText() { // getActionBar().setTitle("打印模版编辑"); } public void setActionBarIcon() { getActionBar().setIcon(R.drawable.menu_btn_back); } protected void showError(final String showError) { this.mHandler.post(new Runnable() { public void run() { PDH.showError(showError); } }); } protected void showSuccess(final String showSuccess) { this.mHandler.post(new Runnable() { public void run() { PDH.showSuccess(showSuccess); } }); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if ((keyCode == KeyEvent.KEYCODE_BACK)) { setResult(RESULT_FIRST_USER, new Intent()); finish(); return false; } return super.onKeyDown(keyCode, event); } /** * 绑定service,实现定位 */ private void location() { Intent intent = new Intent(this, MyService.class); startService(intent); if(Build.VERSION.SDK_INT >=Build.VERSION_CODES.LOLLIPOP) { //版本必须大于5.0 startService(new Intent(this, JobWakeUpService.class)); } } /** * 映美蓝牙打印 */ }
09-09
用户同意权限后没有dismiss ,加个背景圆角吧 好丑,再加点边距 package com.kmilesaway.golfbat.ui.home; import android.Manifest; import android.app.ActivityManager; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.location.LocationManager; import android.os.Handler; import android.os.Looper; import android.provider.Settings; import android.text.TextUtils; import android.util.Log; import android.view.Gravity; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.PopupWindow; import android.widget.TextView; import android.widget.Toast; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.amap.api.maps.MapsInitializer; import com.amap.api.services.core.ServiceSettings; import com.azhon.appupdate.config.UpdateConfiguration; import com.azhon.appupdate.listener.OnButtonClickListener; import com.azhon.appupdate.listener.OnDownloadListenerAdapter; import com.azhon.appupdate.manager.DownloadManager; import com.blankj.utilcode.util.LogUtils; import com.bumptech.glide.Glide; import com.chad.library.adapter.base.BaseQuickAdapter; import com.kmilesaway.golfbat.R; import com.kmilesaway.golfbat.adapter.ScheduleFragmentAdapter; import com.kmilesaway.golfbat.base.BaseApplication; import com.kmilesaway.golfbat.base.BaseMvpFragment; import com.kmilesaway.golfbat.bean.BagStorageBean; import com.kmilesaway.golfbat.bean.CutCaddieBean; import com.kmilesaway.golfbat.bean.HotUpdateBean; import com.kmilesaway.golfbat.bean.MsgWs; import com.kmilesaway.golfbat.bean.ScheduleServiceBean; import com.kmilesaway.golfbat.bean.UserBean; import com.kmilesaway.golfbat.bean.WsSetBean; import com.kmilesaway.golfbat.contract.ScheduleContract; import com.kmilesaway.golfbat.net.MainConstant; import com.kmilesaway.golfbat.presenter.SchedulePresenter; import com.kmilesaway.golfbat.service.BackService; import com.kmilesaway.golfbat.service.DaemonService; import com.kmilesaway.golfbat.ui.dialog.ServiceHintDialog; import com.kmilesaway.golfbat.ui.home.ballaffirm.BallAffirmActivity; import com.kmilesaway.golfbat.ui.home.balloffice.RangingScoringActivity; import com.kmilesaway.golfbat.ui.match.MatchSelectListActivity; import com.kmilesaway.golfbat.utils.AppUtils; import com.kmilesaway.golfbat.utils.DateUtils; import com.kmilesaway.golfbat.utils.EventBusUtils; import com.kmilesaway.golfbat.utils.EventCode; import com.kmilesaway.golfbat.utils.EventMessage; import com.kmilesaway.golfbat.utils.RegexUtils; import com.kmilesaway.golfbat.utils.SPUtils; import com.kmilesaway.golfbat.utils.ToastUtils; import com.kmilesaway.golfbat.utils.UiUtils; import com.kmilesaway.golfbat.weight.MyDialog; import com.kmilesaway.golfbat.weight.NavigationDialog; import com.kmilesaway.golfbat.weight.RoundImageView; import com.kmilesaway.golfbat.weight.SpacesItemDecoration; import com.kmilesaway.golfbat.weight.calender.GetDateBean; import com.kmilesaway.golfbat.weight.calender.MNCalendar; import com.kmilesaway.golfbat.weight.listener.OnCalendarChangeListener; import com.lxj.xpopup.XPopup; import com.permissionx.guolindev.PermissionX; import com.permissionx.guolindev.callback.ExplainReasonCallback; import com.permissionx.guolindev.callback.ForwardToSettingsCallback; import com.permissionx.guolindev.callback.RequestCallback; import com.permissionx.guolindev.request.ExplainScope; import com.permissionx.guolindev.request.ForwardScope; import com.scwang.smart.refresh.header.ClassicsHeader; import com.scwang.smart.refresh.layout.SmartRefreshLayout; import com.scwang.smart.refresh.layout.api.RefreshLayout; import com.scwang.smart.refresh.layout.listener.OnRefreshListener; import java.io.Serializable; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import butterknife.BindView; import butterknife.OnClick; /** * @author lisong * @date 2022/2/8. * GitHub: * Email: * Description:日程 */ public class ScheduleFragment extends BaseMvpFragment<SchedulePresenter> implements ScheduleContract.View, OnButtonClickListener { @BindView(R.id.rcy) RecyclerView rcy; @BindView(R.id.refreshLayout) SmartRefreshLayout refreshLayout; /*下线*/ @BindView(R.id.Offline) TextView Offline; /*上线*/ @BindView(R.id.goonline) TextView goonline; /*姓名*/ @BindView(R.id.name) TextView name; @BindView(R.id.roundimagview) RoundImageView roundimagview; /*工号*/ @BindView(R.id.jobnumber) TextView jobnumber; /*任务数量*/ @BindView(R.id.task_number) TextView taskNumber; @BindView(R.id.tvSchedulingPlan) TextView tvSchedulingPlan; private ScheduleFragmentAdapter adapter; private int status;// 1-上线 0-下线 private int userId; private DownloadManager manager; private boolean is_force_update; private int pos; private boolean isOnResume; private NavigationDialog timebottomSheetDialog; private List<GetDateBean.MonthBean> monthList = new ArrayList<>(); private String date, time; private MNCalendar mnCalendar; private List<ScheduleServiceBean> scheduleList = new ArrayList<>(); @Override protected int getLayoutId() { return R.layout.fragment_schedule; } @Override protected void initView(View view) { date = DateUtils.getSystemTimes(); time = DateUtils.dataY_M_D(date); ServiceSettings.updatePrivacyShow(getActivity(), true, true); ServiceSettings.updatePrivacyAgree(getActivity(), true); // EventBusUtils.post(new EventMessage<>(EventCode.EVENT_SOCKET, "refresh")); rcy.setLayoutManager(new LinearLayoutManager(getActivity())); adapter = new ScheduleFragmentAdapter(); View emptyView = LayoutInflater.from(getContext()).inflate(R.layout.no_data, null, false); adapter.setEmptyView(emptyView); rcy.setAdapter(adapter); rcy.addItemDecoration(new SpacesItemDecoration(UiUtils.dip2px(getActivity(), 6))); adapter.setOnItemChildClickListener(new BaseQuickAdapter.OnItemChildClickListener() { @Override public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) { switch (view.getId()) { case R.id.entergame: permissionMain(position); // if (!isLocServiceEnable()) { // MyDialog dialog = new MyDialog(getActivity(), R.style.mdialog, // new MyDialog.OncloseListener() { // @Override // public void onClick(boolean confirm) { // if (confirm) { // Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS); // startActivity(intent); // } // } // }).setTitle("提示").setContent("请开启定位服务").setNegativeButton("取消").setPositiveButton("开启"); // dialog.show(); // } else { // requestPermission(position); // } break; case R.id.bag_check: // ToastUtils.show(getActivity(),"功能暂未开放"); saveBag(position, 0, ScheduleFragment.this.adapter.getData().get(position).getAppointment_id()); break; case R.id.bag_check1: // ToastUtils.show(getActivity(),"功能暂未开放"); saveBag(position, 1, ScheduleFragment.this.adapter.getData().get(position).getAppointment_id()); break; case R.id.bag_check2: // ToastUtils.show(getActivity(),"功能暂未开放"); saveBag(position, 2, ScheduleFragment.this.adapter.getData().get(position).getAppointment_id()); break; case R.id.bag_check3: // ToastUtils.show(getActivity(),"功能暂未开放"); saveBag(position, 3, ScheduleFragment.this.adapter.getData().get(position).getAppointment_id()); break; case R.id.take_away: confirmGan(position, 0); break; case R.id.take_away1: confirmGan(position, 1); break; case R.id.take_away2: confirmGan(position, 2); break; case R.id.take_away3: confirmGan(position, 3); break; } } }); refreshLayout.setRefreshHeader(new ClassicsHeader(getActivity())); refreshLayout.setOnRefreshListener(new OnRefreshListener() { @Override public void onRefresh(RefreshLayout refreshlayout) { mPresenter.scheduleService(); mPresenter.user(); refreshLayout.finishRefresh(1000); } }); } private void permissionMain(int position) { PermissionX.init(this) .permissions( Manifest.permission.ACCESS_NETWORK_STATE) .request((allGranted, grantedList, deniedList) -> { Log.e("Tag=======", "allGranted====="+allGranted); if (allGranted) { if (!isLocServiceEnable()) { MyDialog dialog = new MyDialog(getActivity(), R.style.mdialog, new MyDialog.OncloseListener() { @Override public void onClick(boolean confirm) { if (confirm) { Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS); startActivity(intent); } } }).setTitle("提示").setContent("请开启定位服务").setNegativeButton("取消").setPositiveButton("开启"); dialog.show(); } else { requestPermission(position); } // Toast.makeText(this, "所有申请的权限都已通过", Toast.LENGTH_SHORT).show(); } else { // Toast.makeText(this, "您拒绝了如下权限:$deniedList", Toast.LENGTH_SHORT).show(); // permissionMain(position); } }); } // 修改权限请求流程 private void requestPermission(int position) { // 先显示提示弹窗 showLocationPermissionHint(); // 立即请求系统权限 requestSystemLocationPermission(position); } // 修改系统权限请求方法 private void requestSystemLocationPermission(int position) { PermissionX.init(this).permissions(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION) .onExplainRequestReason(new ExplainReasonCallback() { @Override public void onExplainReason(ExplainScope explainScope, List<String> list) { // 系统解释弹窗显示时,关闭我们的提示弹窗 if (locationPermissionPopup != null && locationPermissionPopup.isShowing()) { locationPermissionPopup.dismiss(); } explainScope.showRequestReasonDialog(list, "您已拒绝了定位权限,为了您更好的使用应用,请重新打开", "去开启", "取消"); } }).onForwardToSettings(new ForwardToSettingsCallback() { @Override public void onForwardToSettings(ForwardScope forwardScope, List<String> list) { forwardScope.showForwardToSettingsDialog(list, "您需要去应用程序设置当中手动开启定位权限", "去开启", "取消"); } }).request(new RequestCallback() { @Override public void onResult(boolean allGranted, List<String> list, List<String> list1) { // 权限请求完成,关闭提示弹窗 if (locationPermissionPopup != null && locationPermissionPopup.isShowing()) { locationPermissionPopup.dismiss(); } if (allGranted) { ArrayList<Integer> ids = new ArrayList<>(); for (ScheduleServiceBean.PersonDataBean item : scheduleList.get(position).getPerson_data()) { ids.add(item.getPerson_id()); } mPresenter.existTeeTime(scheduleList.get(position).getAppointment_id(), ids); } } }); } // 在onDestroy中清理资源 @Override public void onDestroy() { super.onDestroy(); if (locationPermissionPopup != null && locationPermissionPopup.isShowing()) { locationPermissionPopup.dismiss(); } locationPermissionPopup = null; } /** * 是否打开定位服务 * * @return */ private boolean isLocServiceEnable() { LocationManager locationManager = (LocationManager) BaseApplication.getApplication() .getSystemService(Context.LOCATION_SERVICE); boolean gps = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); boolean network = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER); return gps || network; } private void saveBag(int position, int index, int appId) { ScheduleServiceBean.PersonDataBean personDataBean = adapter.getData().get(position).getPerson_data().get(index); if (personDataBean.getPerson_state() == 0) { ToastUtils.show(getActivity(), "请先确认球杆,再进行存包"); return; } if (personDataBean.getBag() != null) { if (TextUtils.equals(personDataBean.getBag(), "0") || TextUtils.equals(personDataBean.getBag(), "存包")) { showCheckDialog(personDataBean.getName(), personDataBean.getTel(), personDataBean.getPerson_id(), adapter.getData().get(position).getClient_id(), appId); } else { //展示取包提示框 showFetchingBag(personDataBean.getBag_num() + "", personDataBean.getPerson_id(), personDataBean.getName(), personDataBean.getTel(), appId); } } else { showCheckDialog(personDataBean.getName(), personDataBean.getTel(), personDataBean.getPerson_id(), adapter.getData().get(position).getClient_id(), appId); } } private void confirmGan(int position, int index) { try { int bagType = 0; startActivity(new Intent(getActivity(), BallAffirmActivity.class).putExtra("person_id", adapter.getData().get(position).getPerson_data().get(index).getPerson_id()) .putExtra("app_id", adapter.getData().get(position).getAppointment_id()) .putExtra("bagType", bagType) .putExtra("phone", adapter.getData().get(position).getPerson_data().get(index).getTel())); } catch (Exception e) { e.printStackTrace(); } } private void setRefreshDate() { refreshLayout.autoRefresh(); } @Override protected void loadNetData() { //进入到当前Fragment mPresenter = new SchedulePresenter(); mPresenter.attachView(this); mPresenter.user(); mPresenter.scheduleService(); // mPresenter.hotUpdate(); // mPresenter.getWsSetting(); } @Override public void onError(String errMessage, int errCode) { // super.onError(errMessage, errCode); if (errCode == 999) { new MyDialog(requireActivity(),false, R.style.mdialog, new MyDialog.OncloseListener() { @Override public void onClick(boolean confirm) { mPresenter.scheduleService(); } }).setTitle("提示").setContent("服务单信息已变更,请重新进入服务单").setPositiveButton("知道了").show(); } } @Override public void onSwitchStateSuccess(int errno) { if (status == 0) { ToastUtils.show(getActivity(), "下线成功"); EventBusUtils.post(new EventMessage<>(EventCode.EVENT_SERVICE_STOP, "refresh")); } else { ToastUtils.show(getActivity(), "上线成功"); //EventBusUtils.post(new EventMessage<>(EventCode.EVENT_SERVICE_START, "refresh")); } onLine(status); } @Override public void onScheduleServiceSuccess(List<ScheduleServiceBean> bean) { refreshLayout.finishRefresh(); scheduleList.clear(); if (bean != null) { scheduleList.addAll(bean); } adapter.setNewData(scheduleList); taskNumber.setText("今日日程(" + scheduleList.size() + ")"); } @Override public void onHistoryTripSuccess(List<ScheduleServiceBean> list) { } @Override public void onUserSuccess(UserBean bean) { LogUtils.d("ScheduleFragment.onUserSuccess: " + bean.getClient_id()); MainConstant.BESE_CLIENT_ID = bean.getClient_id() + ""; SPUtils.getInstance().put(MainConstant.CLIENT_ID, bean.getClient_id()); SPUtils.getInstance().put(MainConstant.ID, bean.getId()); SPUtils.getInstance().put(MainConstant.JOB_NUM, bean.getJob_num()); SPUtils.getInstance().put(MainConstant.CADDIE_HEAD_IMAGE, bean.getImage()); SPUtils.getInstance().put(MainConstant.CADDIE_NAME, bean.getCaddie_name()); SPUtils.getInstance().put(MainConstant.WHETHER_ONLINE, bean.getWhether_online()); Glide.with(getActivity()) .load(bean.getImage()) .placeholder(R.mipmap.user_logo) .error(R.mipmap.user_logo) .into(roundimagview); name.setText(bean.getCaddie_name()); jobnumber.setText(String.format("球童号: %s", bean.getCaddie_num())); userId = bean.getId(); status = bean.getWhether_online(); if (bean.getCaddie_name().startsWith("[车]") || bean.getCaddie_name().startsWith("[船]")) { SPUtils.getInstance().put(MainConstant.MAP, true); if (!isServiceWork(getActivity(), "com.kmilesaway.golfbat.service.DaemonService")) { getActivity().stopService(new Intent(getActivity(), DaemonService.class)); if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { getActivity().startForegroundService(new Intent(getActivity(), DaemonService.class)); } else { getActivity().startService(new Intent(getActivity(), DaemonService.class)); } } } } @Override public void onHotUpdateSuccess(HotUpdateBean bean) { if (AppUtils.getVersionName(getActivity()).compareTo(bean.getVersion_name()) < 0) { startUpdate(bean); } } @Override public void onCutCaddieSuccess(CutCaddieBean bean) { SPUtils.getInstance().put(MainConstant.MAP, true); if (!isServiceWork(getActivity(), "com.kmilesaway.golfbat.service.DaemonService")) { getActivity().stopService(new Intent(getActivity(), DaemonService.class)); if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { getActivity().startForegroundService(new Intent(getActivity(), DaemonService.class)); } else { getActivity().startService(new Intent(getActivity(), DaemonService.class)); } } MapsInitializer.updatePrivacyShow(getContext(), true, true); MapsInitializer.updatePrivacyAgree(getContext(), true); ScheduleServiceBean scheduleServiceBean = adapter.getData().get(pos); Intent intent = new Intent(getContext(), RangingScoringActivity.class); intent.putExtra("orderRef", scheduleServiceBean.getOrder_ref()); intent.putExtra("clientId", scheduleServiceBean.getClient_id()); String updatedAt = scheduleServiceBean.getUpdated_at(); String datePart = updatedAt; SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// HH:mm:ss try { Date date = formatter.parse(updatedAt); SimpleDateFormat dateOnlyFormatter = new SimpleDateFormat("yyyy-MM-dd"); datePart = dateOnlyFormatter.format(date); datePart = datePart + " " + scheduleServiceBean.getOut_time(); } catch (ParseException ignored) { } intent.putExtra("play_time", datePart); intent.putExtra("group_num", scheduleServiceBean.getGroup_id()); intent.putExtra("app_id", scheduleServiceBean.getAppointment_id()); intent.putExtra("name", scheduleServiceBean.getClient_name()); intent.putExtra("state", bean.getStatus()); intent.putExtra("person_list", (Serializable) scheduleServiceBean.getPerson_data()); startActivity(intent); } @Override public void onBagStorageSuccess(BagStorageBean bean) { if (bean != null) { showNumDialog(bean.getStatus(), bean.getBag_num() + ""); } } @Override public void onWsSettingSuccess(WsSetBean bean) { SPUtils.getInstance().put("IP", bean.getWs_ip()); SPUtils.getInstance().put("Host", bean.getWs_port()); getActivity().stopService(new Intent(getActivity(), BackService.class)); if (!isServiceWork(getActivity(), "com.kmilesaway.golfbat.service.BackService")) { getActivity().startService(new Intent(getActivity(), BackService.class)); } } @Override public void getBallBagAwaySuccess(Object bean) { } @Override public void getLayoutPlanSuccess(List<String> data) { if (mnCalendar != null) { mnCalendar.addEventDates(data); } } @Override public void showSaveBagErrorDialog(String msg) { showNumDialog(2, msg); } @Override public void onFetchingBagSuccess() { setRefreshDate(); } @Override public void onExistTeeTimeSuccess() { SPUtils.getInstance().put(MainConstant.APPOINTMENT_ID, ScheduleFragment.this.adapter.getData().get(pos).getAppointment_id()); mPresenter.cutCaddie(ScheduleFragment.this.adapter.getData().get(pos).getAppointment_id()); } @Override public void onEndPersonBallByCaddySuccess() { } @Override public void onRestoreServiceSuccess() { } @Override public void onMsgWsSuccess(MsgWs bean) { } @OnClick({R.id.Offline, R.id.goonline, R.id.tvSchedulingPlan, R.id.tvMatchScoring}) public void onViewClicked(View view) { switch (view.getId()) { /*下线*/ case R.id.Offline: status = 0; //onLine(status); mPresenter.switchState(status, userId); break; /*上线*/ case R.id.goonline: status = 1; //onLine(status); mPresenter.switchState(status, userId); break; case R.id.tvMatchScoring: Intent intent = new Intent(getContext(), MatchSelectListActivity.class); startActivity(intent); break; case R.id.tvSchedulingPlan: // startActivity(new Intent(getContext(), ClickToPurchaseActivity.class)); if (timebottomSheetDialog != null) { timebottomSheetDialog.dismiss(); } timebottomSheetDialog = new NavigationDialog(getContext(), R.style.BottomDialog); //设置退出速度 timebottomSheetDialog.outDuration(100); timebottomSheetDialog.inDuration(100); //设置铺满 timebottomSheetDialog.heightParam(ViewGroup.LayoutParams.WRAP_CONTENT); //解析视图 View contentView = LayoutInflater.from(getContext()).inflate(R.layout.dialog_mncalendar, null); /*日历*/ mnCalendar = contentView.findViewById(R.id.mnCalendar); mnCalendar.setOnCalendarChangeListener(new OnCalendarChangeListener() { @Override public void onPageChange(int year, int month) { mPresenter.getLayoutPlan(year, month); } }); mnCalendar.setCurrentPager(); monthList.clear(); GetDateBean.MonthBean monthBean = new GetDateBean.MonthBean(); monthBean.setDay(date); monthBean.setStatus(99); monthList.add(monthBean); try { mnCalendar.setEventDatas(monthList); } catch (ParseException e) { e.printStackTrace(); } timebottomSheetDialog.setOnDismissListener(new DialogInterface.OnDismissListener() { @Override public void onDismiss(DialogInterface dialog) { mnCalendar = null; } }); //设置视图 timebottomSheetDialog.setContentView(contentView); //百度 timebottomSheetDialog.show(); break; default: break; } } @Override protected boolean isRegisteredEventBus() { return true; } private void onLine(int status) { switch (status) { case 1: goonline.setBackgroundResource(R.drawable.translucent_6_328e8e); Offline.setBackground(null); goonline.setTextColor(getActivity().getResources().getColor(R.color.white)); Offline.setTextColor(getActivity().getResources().getColor(R.color.translucent_50_white)); break; case 0: Offline.setBackgroundResource(R.drawable.translucent_6_328e8e); goonline.setBackground(null); Offline.setTextColor(getActivity().getResources().getColor(R.color.white)); goonline.setTextColor(getActivity().getResources().getColor(R.color.translucent_50_white)); getActivity().stopService(new Intent(getActivity(), DaemonService.class)); break; } } @Override public void onButtonClick(int id) { } private void startUpdate(HotUpdateBean bean) { if (bean.getIs_force_update() == 0) { is_force_update = false; } else { is_force_update = true; } /* * 整个库允许配置的内容 * 非必选 */ UpdateConfiguration configuration = new UpdateConfiguration() //输出错误日志 .setEnableLog(true) //设置自定义的下载 //.setHttpManager() //下载完成自动跳动安装页面 .setJumpInstallPage(true) //设置对话框背景图片 (图片规范参照demo中的示例图) .setDialogImage(R.drawable.ic_dialog_default) // 设置按钮的颜色 .setDialogButtonColor(Color.parseColor("#1DBCA1")) //// 设置对话框强制更新时进度条和文字的颜色 // .setDialogProgressBarColor(Color.parseColor("#E743DA")) //设置按钮的文字颜色 .setDialogButtonTextColor(Color.WHITE) //设置是否显示通知栏进度 .setShowNotification(true) //设置是否提示后台下载toast .setShowBgdToast(true) //设置是否上报数据 .setUsePlatform(true) //设置强制更新 .setForcedUpgrade(is_force_update) //设置对话框按钮的点击监听 .setButtonClickListener(this) //设置下载过程的监听 .setOnDownloadListener(listenerAdapter); manager = DownloadManager.getInstance(getActivity()); manager.setApkName("golfbat.apk") .setApkUrl(bean.getUrl()) .setSmallIcon(R.mipmap.login_logo) .setShowNewerToast(true) .setConfiguration(configuration) .setApkVersionCode(2) .setApkVersionName(bean.getVersion_name()) .setApkSize(bean.getSize()) .setApkDescription(bean.getMsg()) // .setApkMD5("db18e57e01e5bb2408116c1689f25ca7") .download(); } private OnDownloadListenerAdapter listenerAdapter = new OnDownloadListenerAdapter() { /** * 下载中 * * @param max 总进度 * @param progress 当前进度 */ @Override public void downloading(int max, int progress) { int curr = (int) (progress / (double) max * 100.0); Log.d(">>>>>>>>>>>>>>>", "downloading: " + curr); } }; /** * @param mContext * @param serviceName 是包名+服务的类名(例如:net.loonggg.testbackstage.TestService) * @return true代表正在运行,false代表服务没有正在运行 */ public boolean isServiceWork(Context mContext, String serviceName) { boolean isWork = false; ActivityManager myAM = (ActivityManager) mContext .getSystemService(Context.ACTIVITY_SERVICE); List<ActivityManager.RunningServiceInfo> myList = myAM.getRunningServices(40); if (myList.size() <= 0) { return false; } for (int i = 0; i < myList.size(); i++) { String mName = myList.get(i).service.getClassName().toString(); if (mName.equals(serviceName)) { isWork = true; break; } } return isWork; } //存包对应用户信息 private void showCheckDialog(String name, String phone, int person_id, int client_id, int appId) { View view = LayoutInflater.from(getActivity()).inflate(R.layout.pop_bag_check, null, false); final AlertDialog dialog = new AlertDialog.Builder(getActivity(), R.style.mdialog).setView(view).create(); EditText tvName = view.findViewById(R.id.tv_name); EditText tvPhone = view.findViewById(R.id.tv_phone); tvName.setFocusable(false); tvName.setEnabled(false); if (!TextUtils.isEmpty(name)) { tvName.setText(name); tvName.setSelection(tvName.getText().length()); } if (!TextUtils.isEmpty(phone)) { tvPhone.setText(phone); tvPhone.setSelection(tvPhone.getText().length()); } TextView submit = view.findViewById(R.id.tv_commit); submit.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { HideKeyboard(v); if (tvPhone.getText().toString() == null || tvPhone.getText().toString().equals("")) { ToastUtils.show(getActivity(), "请输入手机号"); return; } if (!RegexUtils.isMobileExact(tvPhone.getText().toString().trim())) { ToastUtils.showShort("请输入正确的手机号"); return; } mPresenter.bagStorage(person_id, client_id, tvName.getText().toString().trim(), tvPhone.getText().toString().trim(), appId + ""); dialog.dismiss(); } }); dialog.setCanceledOnTouchOutside(true);// 设置点击屏幕Dialog不消失 dialog.setOnKeyListener(keylistener);//设置点击返回键Dialog不消失 dialog.show(); //此处设置位置窗体大小,我这里设置为了手机屏幕宽度的3/4 注意一定要在show方法调用后再写设置窗口大小的代码,否则不起效果会 dialog.getWindow().setLayout((UiUtils.getScreenWidth(getActivity()) / 4 * 3), LinearLayout.LayoutParams.WRAP_CONTENT); } private void showFetchingBag(String bag_num, int person_id, String person_name, String person_tel, int app_id) { View view = LayoutInflater.from(getActivity()).inflate(R.layout.pop_bag_fetching, null, false); final AlertDialog dialog = new AlertDialog.Builder(getActivity(), R.style.mdialog).setView(view).create(); view.findViewById(R.id.cancel).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { dialog.dismiss(); } }); view.findViewById(R.id.submit).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mPresenter.fetchingBag(bag_num, person_id, person_name, person_tel, app_id); dialog.dismiss(); } }); dialog.setCanceledOnTouchOutside(true);// 设置点击屏幕Dialog不消失 dialog.setOnKeyListener(keylistener);//设置点击返回键Dialog不消失 dialog.show(); //此处设置位置窗体大小,我这里设置为了手机屏幕宽度的3/4 注意一定要在show方法调用后再写设置窗口大小的代码,否则不起效果会 dialog.getWindow().setLayout((UiUtils.getScreenWidth(getActivity()) / 4 * 3), LinearLayout.LayoutParams.WRAP_CONTENT); } //显示存包位置 private void showNumDialog(int status, String num) { View view = LayoutInflater.from(getActivity()).inflate(R.layout.dialog_bag_check, null, false); final AlertDialog dialog = new AlertDialog.Builder(getActivity(), R.style.mdialog).setView(view).create(); TextView title = view.findViewById(R.id.tv_title); TextView tvNum = view.findViewById(R.id.tv_num); TextView tvContent = view.findViewById(R.id.tv_content); EventBusUtils.post(new EventMessage<>(EventCode.EVENT_SCHEDULE_REFRESH, "refresh")); if (status == 1) { title.setText("存包成功"); tvNum.setText(num); setRefreshDate(); } else if (status == 0) { title.setText("存包失败"); tvNum.setText(num); tvContent.setText("球包已放至指定位置"); } else if (status == 3) { title.setText("球包位置"); tvNum.setText(num); tvContent.setText("请您到指定位置取包"); } else if (status == 4) { title.setText("存包失败"); tvNum.setText(num); tvContent.setText("该手机号已有球包,请更换手机号进行存包"); } else { title.setText("存包失败"); tvNum.setVisibility(View.GONE); tvContent.setText(num); } TextView submit = view.findViewById(R.id.submit); submit.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { dialog.dismiss(); } }); dialog.setCanceledOnTouchOutside(true);// 设置点击屏幕Dialog不消失 dialog.setOnKeyListener(keylistener);//设置点击返回键Dialog不消失 dialog.show(); //此处设置位置窗体大小,我这里设置为了手机屏幕宽度的3/4 注意一定要在show方法调用后再写设置窗口大小的代码,否则不起效果会 dialog.getWindow().setLayout((UiUtils.getScreenWidth(getActivity()) / 4 * 3), LinearLayout.LayoutParams.WRAP_CONTENT); } //取包 private void showTakeAwayDialog() { View view = LayoutInflater.from(getActivity()).inflate(R.layout.dialog_take_away, null, false); final AlertDialog dialog = new AlertDialog.Builder(getActivity(), R.style.mdialog).setView(view).create(); TextView submit = view.findViewById(R.id.submit); submit.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { dialog.dismiss(); } }); TextView cancel = view.findViewById(R.id.cancel); cancel.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { dialog.dismiss(); } }); dialog.setCanceledOnTouchOutside(true);// 设置点击屏幕Dialog不消失 dialog.setOnKeyListener(keylistener);//设置点击返回键Dialog不消失 dialog.show(); //此处设置位置窗体大小,我这里设置为了手机屏幕宽度的3/4 注意一定要在show方法调用后再写设置窗口大小的代码,否则不起效果会 dialog.getWindow().setLayout((UiUtils.getScreenWidth(getActivity()) / 4 * 3), LinearLayout.LayoutParams.WRAP_CONTENT); } DialogInterface.OnKeyListener keylistener = new DialogInterface.OnKeyListener() { public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) { return true; } else { return false; } } }; //隐藏虚拟键盘 public static void HideKeyboard(View v) { InputMethodManager imm = (InputMethodManager) v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); if (imm.isActive()) { imm.hideSoftInputFromWindow(v.getApplicationWindowToken(), 0); } } /** * 接收到分发的事件 * * @param event 事件 */ @Override protected void receiveEvent(EventMessage event) { switch (event.getCode()) { case EventCode.EVENT_SCHEDULE_REFRESH: mPresenter.scheduleService(); break; } } @Override public void onHiddenChanged(boolean hidden) { super.onHiddenChanged(hidden); Log.d("yanjin", "hidden = " + hidden); } @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); if (isOnResume && isVisibleToUser) { refreshLayout.autoRefresh(); Log.d("yanjin", "isVisibleToUser = " + isVisibleToUser); } } @Override public void onResume() { super.onResume(); isOnResume = true; } public void onRestart() { refreshLayout.autoRefresh(); Log.d("yanjin", "onRestart = "); } // 在类顶部添加变量 private PopupWindow locationPermissionPopup; // 添加显示权限提示弹窗的方法 private void showLocationPermissionHint() { if (locationPermissionPopup != null && locationPermissionPopup.isShowing()) { locationPermissionPopup.dismiss(); } View popupView = LayoutInflater.from(getActivity()).inflate(R.layout.popup_location_permission_hint, null); locationPermissionPopup = new PopupWindow( popupView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT ); // 设置PopupWindow属性 locationPermissionPopup.setFocusable(false); locationPermissionPopup.setOutsideTouchable(false); locationPermissionPopup.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); // 显示在顶部 View rootView = getActivity().getWindow().getDecorView(); locationPermissionPopup.showAtLocation(rootView, Gravity.TOP, 0, UiUtils.dip2px(getActivity(), 16)); } }
09-23
现在,我的MapFragment代码如下:package com.example.bus.ui.map; import android.Manifest; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.text.Editable; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.inputmethod.InputMethodManager; import android.widget.ArrayAdapter; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.LinearLayoutManager; // 用于动态修改约束 import androidx.constraintlayout.widget.ConstraintSet; // 用于设置 Marker 颜色 import com.amap.api.maps.model.BitmapDescriptorFactory; import com.amap.api.maps.AMap; import com.amap.api.maps.CameraUpdateFactory; import com.amap.api.maps.MapView; import com.amap.api.maps.UiSettings; import com.amap.api.maps.model.LatLng; import com.amap.api.maps.model.Marker; import com.amap.api.maps.model.MarkerOptions; import com.amap.api.maps.model.MyLocationStyle; import com.amap.api.services.core.LatLonPoint; import com.amap.api.services.core.PoiItem; import com.amap.api.services.poisearch.PoiResult; import com.amap.api.services.poisearch.PoiSearch; import com.amap.api.services.geocoder.GeocodeSearch; import com.amap.api.services.geocoder.RegeocodeQuery; import com.amap.api.services.geocoder.RegeocodeResult; import com.example.bus.R; import com.example.bus.RealTimePoiSuggestHelper; import com.example.bus.RoutePlanActivity; import com.example.bus.ResultAdapter; import com.example.bus.databinding.FragmentMapBinding; import java.util.ArrayList; import java.util.List; // ✅ 新增导入 import android.view.inputmethod.EditorInfo; public class MapFragment extends Fragment implements PoiSearch.OnPoiSearchListener, GeocodeSearch.OnGeocodeSearchListener { private FragmentMapBinding binding; private MapView mapView; private AMap aMap; // 数据 private List<PoiItem> poiList = new ArrayList<>(); private ResultAdapter adapter; private PoiSearch poiSearch; // 当前阶段:1=选择起点, 2=选择终点 private int selectionStage = 0; // 缓存已选 POI private PoiItem selectedStartPoi = null; private PoiItem selectedEndPoi = null; private Marker startMarker = null; private Marker endMarker = null; // 缓存关键词 private String lastStartKeyword = ""; private String lastEndKeyword = ""; // ✅ 当前城市 private String currentCity = "全国"; private static final int LOCATION_PERMISSION_REQUEST_CODE = 1001; // ✅ 标记是否已居中我的位置 private boolean userHasInteracted = false; // ✅ 反地理编码 private GeocodeSearch geocodeSearch; // 【关键新增】保存定位得到的“我的位置” private double myCurrentLat = 0; private double myCurrentLng = 0; private boolean isLocationReady = false; // 定位是否完成 @Override public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { binding = FragmentMapBinding.inflate(inflater, container, false); View root = binding.getRoot(); mapView = binding.mapView; mapView.onCreate(savedInstanceState); initViews(); setupMap(savedInstanceState); setupSearchSuggestion(); // 包含输入建议、防抖、回车事件 return root; } private void initViews() { adapter = new ResultAdapter(poiList, this::onPoiItemSelected); binding.resultList.setLayoutManager(new LinearLayoutManager(requireContext())); binding.resultList.setAdapter(adapter); binding.mapSearch.setOnClickListener(v -> performSearch()); binding.btnSwitchTarget.setOnClickListener(v -> { if (selectionStage == 1) { showEndpointSelection(binding.mapInput2.getText().toString().trim()); } else if (selectionStage == 2) { showStartpointSelection(binding.mapInput1.getText().toString().trim()); } }); binding.btnGoTo.setOnClickListener(v -> { if (selectedStartPoi != null && selectedEndPoi != null) { Intent intent = new Intent(requireContext(), RoutePlanActivity.class); intent.putExtra(RoutePlanActivity.EXTRA_SOURCE, RoutePlanActivity.SOURCE_FROM_MAP_DIRECT); intent.putExtra("start_lat", selectedStartPoi.getLatLonPoint().getLatitude()); intent.putExtra("start_lng", selectedStartPoi.getLatLonPoint().getLongitude()); intent.putExtra("target_lat", selectedEndPoi.getLatLonPoint().getLatitude()); intent.putExtra("target_lng", selectedEndPoi.getLatLonPoint().getLongitude()); intent.putExtra("target_title", selectedEndPoi.getTitle()); startActivity(intent); } else { Toast.makeText(requireContext(), "请完成起点和终点的选择", Toast.LENGTH_SHORT).show(); } }); } private void performSearch() { String startKeyword = binding.mapInput1.getText().toString().trim(); String endKeyword = binding.mapInput2.getText().toString().trim(); if (startKeyword.isEmpty()) { Toast.makeText(requireContext(), "请输入起点", Toast.LENGTH_SHORT).show(); return; } if (endKeyword.isEmpty()) { Toast.makeText(requireContext(), "请输入终点", Toast.LENGTH_SHORT).show(); return; } // 智能判断跳过搜索 if (startKeyword.equals(lastStartKeyword) && endKeyword.equals(lastEndKeyword) && selectedStartPoi != null && selectedEndPoi != null) { binding.btnGoTo.performClick(); return; } // 展示 UI binding.containerResultList.setVisibility(View.VISIBLE); binding.buttonGroup.setVisibility(View.VISIBLE); // 动态压缩地图区域 ConstraintSet constraintSet = new ConstraintSet(); constraintSet.clone(binding.getRoot()); constraintSet.connect( R.id.map_view, ConstraintSet.BOTTOM, R.id.container_result_list, ConstraintSet.TOP, 0 ); constraintSet.clone(binding.getRoot()); userHasInteracted = true; // 隐藏软键盘 View currentFocus = requireActivity().getCurrentFocus(); if (currentFocus != null) { currentFocus.clearFocus(); InputMethodManager imm = (InputMethodManager) requireContext().getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(currentFocus.getWindowToken(), 0); } // 执行搜索 if (!startKeyword.equals(lastStartKeyword)) { lastStartKeyword = startKeyword; lastEndKeyword = endKeyword; showStartpointSelection(startKeyword); } else if (!endKeyword.equals(lastEndKeyword)) { lastEndKeyword = endKeyword; showEndpointSelection(endKeyword); } else if (selectedStartPoi == null) { showStartpointSelection(startKeyword); } else { showEndpointSelection(endKeyword); } } // ✅ 显示“搜索起点中...” private void showStartpointSelection(String keyword) { selectionStage = 1; binding.btnSwitchTarget.setText("前往选择终点"); binding.btnGoTo.setEnabled(false); binding.emptyView.setText("🔍 搜索起点中..."); binding.emptyView.setVisibility(View.VISIBLE); binding.resultList.setVisibility(View.GONE); doSearch(keyword); } // ✅ 显示“搜索终点中...” private void showEndpointSelection(String keyword) { selectionStage = 2; binding.btnSwitchTarget.setText("回到选择起点"); binding.btnGoTo.setEnabled(false); binding.emptyView.setText("🔍 搜索终点中..."); binding.emptyView.setVisibility(View.VISIBLE); binding.resultList.setVisibility(View.GONE); doSearch(keyword); } private void doSearch(String keyword) { if (keyword.isEmpty()) return; PoiSearch.Query query = new PoiSearch.Query(keyword, "", currentCity); query.setPageSize(20); query.setPageNum(0); // ✅ 使用缓存的位置(仅当真实定位完成后) if (isLocationReady) { LatLonPoint lp = new LatLonPoint(myCurrentLat, myCurrentLng); query.setLocation(lp); // 让高德根据“我在哪”智能排序 } try { poiSearch = new PoiSearch(requireContext(), query); poiSearch.setOnPoiSearchListener(this); poiSearch.searchPOIAsyn(); } catch (Exception e) { e.printStackTrace(); Toast.makeText(requireContext(), "搜索失败", Toast.LENGTH_SHORT).show(); } } private void onPoiItemSelected(PoiItem item) { LatLng latLng = new LatLng(item.getLatLonPoint().getLatitude(), item.getLatLonPoint().getLongitude()); if (selectionStage == 1) { if (startMarker != null) { startMarker.remove(); startMarker = null; } startMarker = aMap.addMarker(new MarkerOptions() .position(latLng) .title("起点:" + item.getTitle()) .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN))); selectedStartPoi = item; aMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 14f)); updateGoToButtonState(); } else if (selectionStage == 2) { if (endMarker != null) { endMarker.remove(); endMarker = null; } endMarker = aMap.addMarker(new MarkerOptions() .position(latLng) .title("终点:" + item.getTitle()) .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED))); selectedEndPoi = item; aMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 14f)); updateGoToButtonState(); } userHasInteracted = true; } private void updateGoToButtonState() { binding.btnGoTo.setEnabled(selectedStartPoi != null && selectedEndPoi != null); } @Override public void onPoiSearched(PoiResult result, int rCode) { if (rCode == 1000 && result != null && result.getPois() != null && !result.getPois().isEmpty()) { List<PoiItem> newPoiList = result.getPois(); poiList.clear(); poiList.addAll(newPoiList); if (adapter == null) { adapter = new ResultAdapter(poiList, this::onPoiItemSelected); binding.resultList.setLayoutManager(new LinearLayoutManager(requireContext())); binding.resultList.setAdapter(adapter); } else { adapter.notifyDataSetChanged(); binding.resultList.scrollToPosition(0); } binding.emptyView.setVisibility(View.GONE); binding.resultList.setVisibility(View.VISIBLE); // 先设置 Adapter 的选中状态(触发 UI 高亮) adapter.setSelected(0); // 自动选中第一个 onPoiItemSelected(poiList.get(0)); } else { handleSearchError(rCode); if (selectionStage == 1) { binding.emptyView.setText("⚠️ 未找到相关起点"); } else if (selectionStage == 2) { binding.emptyView.setText("⚠️ 未找到相关终点"); } binding.emptyView.setVisibility(View.VISIBLE); binding.resultList.setVisibility(View.GONE); } } @Override public void onPoiItemSearched(PoiItem item, int rCode) { // 必须实现 } private void setupMap(Bundle savedInstanceState) { mapView.onCreate(savedInstanceState); aMap = mapView.getMap(); if (aMap != null) { initMapSettings(); } else { new Handler(Looper.getMainLooper()).post(() -> { aMap = mapView.getMap(); if (aMap != null) { initMapSettings(); } else { waitAMapReady(); } }); } try { geocodeSearch = new GeocodeSearch(requireContext()); geocodeSearch.setOnGeocodeSearchListener(this); } catch (Exception e) { e.printStackTrace(); } } private void waitAMapReady() { new Handler(Looper.getMainLooper()).postDelayed(new Runnable() { int retry = 0; @Override public void run() { if (mapView == null) return; aMap = mapView.getMap(); if (aMap != null) { initMapSettings(); } else if (retry++ < 30) { new Handler(Looper.getMainLooper()).postDelayed(this, 100); } } }, 100); } private void initMapSettings() { UiSettings uiSettings = aMap.getUiSettings(); uiSettings.setZoomControlsEnabled(true); uiSettings.setCompassEnabled(true); uiSettings.setScrollGesturesEnabled(true); uiSettings.setMyLocationButtonEnabled(true); new Handler(Looper.getMainLooper()).post(() -> aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(39.909186, 116.397411), 10f)) ); enableMyLocationLayer(); } private void enableMyLocationLayer() { if (aMap == null) return; if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { MyLocationStyle myLocationStyle = new MyLocationStyle(); myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE_NO_CENTER); aMap.setMyLocationStyle(myLocationStyle); aMap.setMyLocationEnabled(true); AMap.OnMyLocationChangeListener listener = location -> { if (location != null && !userHasInteracted) { LatLng curLatlng = new LatLng(location.getLatitude(), location.getLongitude()); // ✅ 记录真实位置 myCurrentLat = location.getLatitude(); myCurrentLng = location.getLongitude(); isLocationReady = true; aMap.animateCamera(CameraUpdateFactory.newLatLngZoom(curLatlng, 16f)); userHasInteracted = true; // 获取城市 LatLonPoint point = new LatLonPoint(myCurrentLat, myCurrentLng); RegeocodeQuery query = new RegeocodeQuery(point, 200, GeocodeSearch.AMAP); try { geocodeSearch.getFromLocationAsyn(query); } catch (Exception e) { e.printStackTrace(); } aMap.setOnMyLocationChangeListener(null); } }; aMap.setOnMyLocationChangeListener(listener); } else { ActivityCompat.requestPermissions(requireActivity(), new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, LOCATION_PERMISSION_REQUEST_CODE); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if (requestCode == LOCATION_PERMISSION_REQUEST_CODE) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { if (aMap != null) { MyLocationStyle myLocationStyle = new MyLocationStyle(); myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE_NO_CENTER); aMap.setMyLocationStyle(myLocationStyle); aMap.setMyLocationEnabled(true); AMap.OnMyLocationChangeListener listener = location -> { if (location != null && !userHasInteracted) { LatLng curLatlng = new LatLng(location.getLatitude(), location.getLongitude()); // ✅ 同步记录位置 myCurrentLat = location.getLatitude(); myCurrentLng = location.getLongitude(); isLocationReady = true; aMap.animateCamera(CameraUpdateFactory.newLatLngZoom(curLatlng, 16f)); userHasInteracted = true; LatLonPoint point = new LatLonPoint(myCurrentLat, myCurrentLng); RegeocodeQuery query = new RegeocodeQuery(point, 200, GeocodeSearch.AMAP); try { geocodeSearch.getFromLocationAsyn(query); } catch (Exception e) { e.printStackTrace(); } aMap.setOnMyLocationChangeListener(null); } }; aMap.setOnMyLocationChangeListener(listener); } } else { Toast.makeText(requireContext(), "定位权限被拒绝,部分功能受限", Toast.LENGTH_LONG).show(); currentCity = "全国"; } } } @Override public void onRegeocodeSearched(RegeocodeResult result, int rCode) { if (rCode == 1000 && result != null && result.getRegeocodeAddress() != null) { String city = result.getRegeocodeAddress().getCity(); currentCity = (city != null && !city.isEmpty()) ? city : result.getRegeocodeAddress().getProvince(); } else { currentCity = "全国"; } } @Override public void onGeocodeSearched(com.amap.api.services.geocoder.GeocodeResult geocodeResult, int i) { // 忽略 } @Override public void onResume() { super.onResume(); mapView.onResume(); if (!userHasInteracted) { enableMyLocationLayer(); } } @Override public void onPause() { super.onPause(); mapView.onPause(); } @Override public void onDestroyView() { super.onDestroyView(); mapView.onDestroy(); geocodeSearch = null; binding = null; } @Override public void onSaveInstanceState(@NonNull Bundle outState) { super.onSaveInstanceState(outState); mapView.onSaveInstanceState(outState); } // ✅ 完整保留原始的 setupSearchSuggestion 实现 private void setupSearchSuggestion() { // 创建实时 POI 建议助手 RealTimePoiSuggestHelper suggestHelper = new RealTimePoiSuggestHelper(requireContext()); suggestHelper.setCurrentCity(currentCity); suggestHelper.setCallback(suggestions -> { if (suggestions.length > 0) { ArrayAdapter<String> adapter = new ArrayAdapter<>( requireContext(), android.R.layout.simple_dropdown_item_1line, suggestions ); new Handler(Looper.getMainLooper()).post(() -> { binding.mapInput1.setAdapter(adapter); binding.mapInput2.setAdapter(adapter); if (requireActivity().getCurrentFocus() == binding.mapInput1) { binding.mapInput1.showDropDown(); } else if (requireActivity().getCurrentFocus() == binding.mapInput2) { binding.mapInput2.showDropDown(); } }); } }); Handler handler = new Handler(Looper.getMainLooper()); Runnable[] pending1 = {null}, pending2 = {null}; // 使用 SimpleTextWatcher 简化注册 binding.mapInput1.addTextChangedListener(new SimpleTextWatcher(s -> { if (pending1[0] != null) handler.removeCallbacks(pending1[0]); if (s.length() == 0) { binding.mapInput1.setAdapter(null); return; } pending1[0] = () -> suggestHelper.requestSuggestions(s.toString()); handler.postDelayed(pending1[0], 300); })); binding.mapInput2.addTextChangedListener(new SimpleTextWatcher(s -> { if (pending2[0] != null) handler.removeCallbacks(pending2[0]); if (s.length() == 0) { binding.mapInput2.setAdapter(null); return; } pending2[0] = () -> suggestHelper.requestSuggestions(s.toString()); handler.postDelayed(pending2[0], 300); })); // 回车事件保持不变 binding.mapInput1.setOnEditorActionListener((v, actionId, event) -> { if ((actionId & EditorInfo.IME_MASK_ACTION) == EditorInfo.IME_ACTION_SEARCH) { performSearch(); return true; } return false; }); binding.mapInput2.setOnEditorActionListener((v, actionId, event) -> { if ((actionId & EditorInfo.IME_MASK_ACTION) == EditorInfo.IME_ACTION_SEARCH) { performSearch(); return true; } return false; }); } private void handleSearchError(int rCode) { String msg; switch (rCode) { case 12: msg = "API Key 错误"; break; case 27: msg = "网络连接失败"; break; case 30: msg = "SHA1 或包名错误"; break; case 33: msg = "请求频繁"; break; default: msg = "搜索失败: " + rCode; break; } Toast.makeText(requireContext(), msg, Toast.LENGTH_SHORT).show(); } // ✅ 自定义 TextWatcher 类,保留原始写法 private static class SimpleTextWatcher implements android.text.TextWatcher { private final java.util.function.Consumer<CharSequence> onTextChanged; public SimpleTextWatcher(java.util.function.Consumer<CharSequence> onTextChanged) { this.onTextChanged = onTextChanged; } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {} @Override public void afterTextChanged(Editable s) {} @Override public void onTextChanged(CharSequence s, int start, int before, int count) { onTextChanged.accept(s); } } } SearchResultActivity代码如下:package com.example.bus; import android.Manifest; import android.content.Intent; import android.content.pm.PackageManager; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.view.View; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.amap.api.maps.AMap; import com.amap.api.maps.CameraUpdateFactory; import com.amap.api.maps.MapView; import com.amap.api.maps.UiSettings; import com.amap.api.maps.model.LatLng; import com.amap.api.maps.model.Marker; import com.amap.api.maps.model.MarkerOptions; import com.amap.api.maps.model.MyLocationStyle; import com.amap.api.services.core.LatLonPoint; import com.amap.api.services.core.PoiItem; import com.amap.api.services.poisearch.PoiResult; import com.amap.api.services.poisearch.PoiSearch; import com.amap.api.services.geocoder.GeocodeSearch; import com.amap.api.services.geocoder.RegeocodeQuery; import com.amap.api.services.geocoder.RegeocodeResult; import android.text.Editable; import android.text.TextWatcher; import android.widget.ArrayAdapter; import java.util.ArrayList; import java.util.List; import android.view.inputmethod.EditorInfo; public class SearchResultActivity extends AppCompatActivity implements PoiSearch.OnPoiSearchListener, GeocodeSearch.OnGeocodeSearchListener { private Button searchBtn, goToBtn; private RecyclerView resultListView; private List<PoiItem> poiList = new ArrayList<>(); private ResultAdapter adapter; private PoiSearch poiSearch; // 地图相关 private MapView mapView; private AMap aMap; private Marker selectedMarker; // 终点标记 // 输入提示 private GeocodeSearch geocodeSearch; // 当前城市 private String currentCity = "全国"; // 是否已与地图交互(防止重复居中) private boolean userHasInteracted = false; private static final int LOCATION_PERMISSION_REQUEST_CODE = 1001; // 空状态提示视图 private TextView emptyView; // 【关键新增】保存定位得到的“我的位置” private double myCurrentLat = 0; private double myCurrentLng = 0; private boolean isLocationReady = false; // 定位是否完成 // 缓存从 HomeFragment 传来的关键词,等待定位完成后使用 private String pendingKeyword = null; // ✅ 新增:将搜索输入框提升为成员变量 private android.widget.AutoCompleteTextView searchInput; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_search_result); if (getSupportActionBar() != null) { getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setTitle("搜索地点"); } initViews(); setupMap(savedInstanceState); setupSearchSuggestion(); try { geocodeSearch = new GeocodeSearch(this); geocodeSearch.setOnGeocodeSearchListener(this); } catch (Exception e) { e.printStackTrace(); } // ✅ 只缓存 keyword,不再尝试提前搜索 pendingKeyword = getIntent().getStringExtra("keyword"); } private void initViews() { searchBtn = findViewById(R.id.search_btn); resultListView = findViewById(R.id.result_list); goToBtn = findViewById(R.id.btn_go_to); emptyView = findViewById(R.id.empty_view); searchInput = findViewById(R.id.search_input); // ✅ 初始化成员变量 goToBtn.setEnabled(false); adapter = new ResultAdapter(poiList, this::onPoiItemSelected); resultListView.setLayoutManager(new LinearLayoutManager(this)); resultListView.setAdapter(adapter); resultListView.setVisibility(View.GONE); emptyView.setVisibility(View.GONE); // 修改:传递真实定位点 goToBtn.setOnClickListener(v -> { if (selectedMarker == null) { Toast.makeText(this, "请先选择一个位置", Toast.LENGTH_SHORT).show(); return; } LatLng targetPos = selectedMarker.getPosition(); // 确保定位已完成 if (!isLocationReady) { Toast.makeText(this, "正在获取您的位置,请稍后再试", Toast.LENGTH_SHORT).show(); return; } Intent intent = new Intent(SearchResultActivity.this, RoutePlanActivity.class); intent.putExtra("start_lat", myCurrentLat); intent.putExtra("start_lng", myCurrentLng); intent.putExtra("target_lat", targetPos.latitude); intent.putExtra("target_lng", targetPos.longitude); intent.putExtra(RoutePlanActivity.EXTRA_SOURCE, RoutePlanActivity.SOURCE_FROM_SEARCH_RESULT); startActivity(intent); finish(); }); } private void setupMap(Bundle savedInstanceState) { mapView = findViewById(R.id.map_view); mapView.onCreate(savedInstanceState); aMap = mapView.getMap(); if (aMap != null) { initMapSettings(); } else { new Handler(Looper.getMainLooper()).post(() -> { aMap = mapView.getMap(); if (aMap != null) { initMapSettings(); } else { waitAMapReady(); } }); } } private void waitAMapReady() { new Handler(Looper.getMainLooper()).postDelayed(new Runnable() { int retry = 0; @Override public void run() { if (mapView == null) return; aMap = mapView.getMap(); if (aMap != null) { initMapSettings(); } else if (retry++ < 30) { new Handler(Looper.getMainLooper()).postDelayed(this, 100); } } }, 100); } private void initMapSettings() { UiSettings uiSettings = aMap.getUiSettings(); uiSettings.setZoomControlsEnabled(true); uiSettings.setCompassEnabled(true); uiSettings.setScrollGesturesEnabled(true); uiSettings.setMyLocationButtonEnabled(true); aMap.setOnMapClickListener(latLng -> onCustomLocationSelected(latLng)); // 初始视野:中国中心 new Handler(Looper.getMainLooper()).post(() -> aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(35.8617, 104.1954), 4f)) ); enableMyLocationLayer(); } private void enableMyLocationLayer() { if (aMap == null) return; if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { MyLocationStyle myLocationStyle = new MyLocationStyle(); myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE_NO_CENTER); aMap.setMyLocationStyle(myLocationStyle); aMap.setMyLocationEnabled(true); AMap.OnMyLocationChangeListener listener = location -> { if (location != null && !userHasInteracted) { LatLng curLatlng = new LatLng(location.getLatitude(), location.getLongitude()); // 记录真实“我的位置” myCurrentLat = location.getLatitude(); myCurrentLng = location.getLongitude(); isLocationReady = true; // ✅ 先居中地图 aMap.animateCamera(CameraUpdateFactory.newLatLngZoom(curLatlng, 16f), 500, null); userHasInteracted = true; // 获取当前城市 LatLonPoint point = new LatLonPoint(myCurrentLat, myCurrentLng); RegeocodeQuery query = new RegeocodeQuery(point, 200, GeocodeSearch.AMAP); try { geocodeSearch.getFromLocationAsyn(query); } catch (Exception e) { e.printStackTrace(); } // ✅ 关键修改:延迟 800ms 再触发搜索,给地图留出渲染时间 new Handler(Looper.getMainLooper()).postDelayed(() -> { if (pendingKeyword != null && !pendingKeyword.isEmpty()) { performSearchWithKeyword(pendingKeyword); } }, 800); // 防止重复触发 aMap.setOnMyLocationChangeListener(null); } }; aMap.setOnMyLocationChangeListener(listener); } else { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, LOCATION_PERMISSION_REQUEST_CODE); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == LOCATION_PERMISSION_REQUEST_CODE) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { enableMyLocationLayer(); } else { Toast.makeText(this, "定位权限被拒绝,部分功能受限", Toast.LENGTH_LONG).show(); currentCity = "全国"; } } } private void setupSearchSuggestion() { RealTimePoiSuggestHelper suggestHelper = new RealTimePoiSuggestHelper(this); suggestHelper.setCurrentCity(currentCity); suggestHelper.setLocationBias(myCurrentLat, myCurrentLng); // 使用定位偏置 suggestHelper.setCallback(suggestions -> { if (suggestions.length > 0) { ArrayAdapter<String> adapter = new ArrayAdapter<>( this, android.R.layout.simple_dropdown_item_1line, suggestions ); searchInput.setAdapter(adapter); searchInput.showDropDown(); } }); Handler handler = new Handler(Looper.getMainLooper()); Runnable[] pendingRunnable = {null}; searchInput.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {} @Override public void onTextChanged(CharSequence s, int start, int before, int count) { if (pendingRunnable[0] != null) { handler.removeCallbacks(pendingRunnable[0]); } if (s.length() == 0) { searchInput.setAdapter(null); return; } pendingRunnable[0] = () -> suggestHelper.requestSuggestions(s.toString()); handler.postDelayed(pendingRunnable[0], 300); } @Override public void afterTextChanged(Editable s) {} }); searchInput.setOnEditorActionListener((v, actionId, event) -> { if ((actionId & EditorInfo.IME_MASK_ACTION) == EditorInfo.IME_ACTION_SEARCH) { searchBtn.performClick(); return true; } return false; }); searchBtn.setOnClickListener(v -> { String keyword = searchInput.getText().toString().trim(); if (!keyword.isEmpty()) { performSearch(keyword); } else { Toast.makeText(this, "请输入关键词", Toast.LENGTH_SHORT).show(); } }); } // ✅ 修改:先设置文本,再模拟点击按钮(等价于用户操作) private void performSearchWithKeyword(String keyword) { searchInput.setText(keyword); searchInput.clearFocus(); searchBtn.performClick(); // ✅ 触发完整 UI 搜索流程 } private void performSearch(String keyword) { emptyView.setText("🔍 搜索中..."); emptyView.setVisibility(View.VISIBLE); resultListView.setVisibility(View.GONE); PoiSearch.Query query = new PoiSearch.Query(keyword, "", currentCity); query.setPageSize(20); query.setPageNum(0); if (isLocationReady) { LatLonPoint lp = new LatLonPoint(myCurrentLat, myCurrentLng); query.setLocation(lp); // 告诉高德“我在哪”,让它自行加权 } try { poiSearch = new PoiSearch(this, query); poiSearch.setOnPoiSearchListener(this); poiSearch.searchPOIAsyn(); } catch (Exception e) { Toast.makeText(this, "搜索失败", Toast.LENGTH_SHORT).show(); emptyView.setText("⚠️ 未找到相关地点"); } } private void onPoiItemSelected(PoiItem item) { LatLng latLng = new LatLng(item.getLatLonPoint().getLatitude(), item.getLatLonPoint().getLongitude()); if (selectedMarker != null) { selectedMarker.remove(); selectedMarker = null; } selectedMarker = aMap.addMarker(new MarkerOptions() .position(latLng) .title("终点:" + item.getTitle()) .icon(com.amap.api.maps.model.BitmapDescriptorFactory.defaultMarker( com.amap.api.maps.model.BitmapDescriptorFactory.HUE_RED))); aMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 14f)); goToBtn.setEnabled(true); } private void onCustomLocationSelected(LatLng latLng) { if (selectedMarker != null) { selectedMarker.remove(); } selectedMarker = aMap.addMarker(new MarkerOptions() .position(latLng) .title("终点:自定义位置") .icon(com.amap.api.maps.model.BitmapDescriptorFactory.defaultMarker( com.amap.api.maps.model.BitmapDescriptorFactory.HUE_RED))); goToBtn.setEnabled(true); } @Override public void onPoiSearched(PoiResult result, int rCode) { if (rCode == 1000 && result != null && result.getPois() != null && !result.getPois().isEmpty()) { List<PoiItem> newPoiList = result.getPois(); poiList.clear(); poiList.addAll(newPoiList); adapter.notifyDataSetChanged(); resultListView.scrollToPosition(0); resultListView.setVisibility(View.VISIBLE); emptyView.setVisibility(View.GONE); // 先设置 Adapter 的选中状态 adapter.setSelected(0); // 再执行业务逻辑 onPoiItemSelected(poiList.get(0)); } else { emptyView.setText("⚠️ 未找到相关地点"); emptyView.setVisibility(View.VISIBLE); resultListView.setVisibility(View.GONE); } } @Override public void onPoiItemSearched(PoiItem item, int rCode) { // 必须实现 } @Override public void onRegeocodeSearched(RegeocodeResult result, int rCode) { if (rCode == 1000 && result != null && result.getRegeocodeAddress() != null) { String city = result.getRegeocodeAddress().getCity(); currentCity = (city != null && !city.isEmpty()) ? city : result.getRegeocodeAddress().getProvince(); } else { currentCity = "全国"; } } @Override public void onGeocodeSearched(com.amap.api.services.geocoder.GeocodeResult geocodeResult, int i) { // 忽略 } @Override protected void onResume() { super.onResume(); mapView.onResume(); } @Override protected void onPause() { super.onPause(); mapView.onPause(); } @Override protected void onDestroy() { super.onDestroy(); mapView.onDestroy(); geocodeSearch = null; } @Override protected void onSaveInstanceState(@NonNull Bundle outState) { super.onSaveInstanceState(outState); mapView.onSaveInstanceState(outState); } @Override public boolean onSupportNavigateUp() { onBackPressed(); return true; } } 目前我的位置在广州市,但是我要搜索一个比较偏门的地方,比如像什么卡利欧tcg·宝可梦·洛卡纳·原神·海贼王,他就搜不到了。这个地方我查了,在北京市,我要加上一个前缀北京市卡利欧tcg·宝可梦·洛卡纳·原神·海贼王他才能搜得到。但是我又希望保持像搜索麦当劳这些能够由近到远展示结果,目前这个功能是有的。而刚刚说的这个卡利欧tcg·宝可梦·洛卡纳·原神·海贼王,全国也就只有北京才有一个同名的地方,即使在高德地图中搜索,他也会优先展示这个结果
最新发布
12-02
package xgpushdemo.qt.an.appmap; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import com.baidu.location.BDLocation; import com.baidu.location.BDLocationListener; import com.baidu.location.LocationClient; import com.baidu.location.LocationClientOption; import com.baidu.mapapi.SDKInitializer; import com.baidu.mapapi.map.BaiduMap; import com.baidu.mapapi.map.MapView; import com.baidu.mapapi.map.MyLocationData; /*** * 百度定位、导航 * */ public class MainActivity extends Activity { private Button clickbtn; private TextView txt1; private TextView txt2; private MapView mMapView = null; private BaiduMap mBaiduMap=null; //定位相关申明 private LocationClient locationClient; //是否第一次定位 private Boolean isFirstloc=true; //是否开启 private Boolean isStart=true; private String la; private String lo; private String city; public BDLocationListener myListener=new BDLocationListener() { @Override public void onReceiveLocation(BDLocation bdLocation) { if(bdLocation==null||mMapView==null) return; MyLocationData myLocationData= new MyLocationData.Builder().accuracy(bdLocation.getRadius()).direction(100). latitude(bdLocation.getLatitude()).longitude(bdLocation.getLongitude()).build(); mBaiduMap.setMyLocationData(myLocationData); city= bdLocation.getCity(); la=bdLocation.getLatitude()+""; lo=bdLocation.getLongitude()+""; // if(isFirstloc){ // isFirstloc=false; // LatLng ll=new LatLng(bdLocation.getLatitude(),bdLocation.getLongitude()); // MapStatusUpdate mapStatusUpdate= MapStatusUpdateFactory.newLatLngZoom(ll,16); // mBaiduMap.animateMapStatus(mapStatusUpdate); // } } };
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

liranke

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值