【Android】程序崩溃错误为Android.widget,textView cannot be cast to android.widget.button

在Ubuntu环境下使用ADTeclipse进行编程时,遇到改动布局后程序崩溃的问题。通过清理项目的方法成功解决,前提是确保程序本身没有问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

昨天开始学习的时候就遇到这个问题,本来程序好好的,结果一改动布局之类的立马就崩溃,开始以为是Ubuntu下的ADT eclipse有Bug,上stackoverflow得到答案如下:


 Project -> Clean 


清理一下项目即可。



当然这个方法管用的前提是你的程序真的没有问题!!!

package com.example.kucun2.ui.jinhuo; import static android.content.ContentValues.TAG; import android.app.AlertDialog; import android.app.DatePickerDialog; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.MultiAutoCompleteTextView; import android.widget.RadioGroup; import android.widget.SearchView; import android.widget.Spinner; import android.widget.TextView; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; import com.example.kucun2.R; import com.example.kucun2.entity.*; import com.example.kucun2.entity.data.Data; import com.example.kucun2.function.Adapter; import com.google.android.material.textfield.TextInputEditText; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.Locale; import java.util.Objects; import java.util.Random; public class AddInventoryFragment extends Fragment { private Spinner spinnerDingdan, spinnerChanpin, spinnerZujian, spinnerBancai; private EditText etShuliang; private RadioGroup rgType; private Dingdan selectedDingdan; private Chanpin selectedChanpin; private Zujian selectedZujian; private Bancai selectedBancai; // 创建新订单产品组件按钮 private Button btnNewDingdan, btnAddChanpin, btnAddZujian; // 日期格式化 private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()); /** * 初始化 * @param inflater The LayoutInflater object that can be used to inflate * any views in the fragment, * @param container If non-null, this is the parent view that the fragment's * UI should be attached to. The fragment should not add the view itself, * but this can be used to generate the LayoutParams of the view. * @param savedInstanceState If non-null, this fragment is being re-constructed * from a previous saved state as given here. * * @return */ @Override public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_add_inventory, container, false); // 初始化UI组件 spinnerDingdan = view.findViewById(R.id.spinner_dingdan); spinnerChanpin = view.findViewById(R.id.spinner_chanpin); spinnerZujian = view.findViewById(R.id.spinner_zujian); spinnerBancai = view.findViewById(R.id.spinner_bancai); etShuliang = view.findViewById(R.id.et_shuliang); rgType = view.findViewById(R.id.rg_type); Button btnSubmit = view.findViewById(R.id.btn_submit); // 初始化新按钮 btnNewDingdan = view.findViewById(R.id.btn_new_dingdan); btnAddChanpin = view.findViewById(R.id.btn_add_chanpin); btnAddZujian = view.findViewById(R.id.btn_add_zujian); // 设置按钮点击事件 btnNewDingdan.setOnClickListener(v -> createNewDingdan()); btnAddChanpin.setOnClickListener(v -> showAddChanpinDialog()); btnAddZujian.setOnClickListener(v -> addZujianToChanpin()); // 设置订单选择器 setupDingdanSpinner(); // 提交按钮点击事件 btnSubmit.setOnClickListener(v -> addInventoryRecord()); return view; } private void setupDingdanSpinner() { Adapter.setupDingdanSpinner(spinnerDingdan,Data.dingdans,getContext()); spinnerDingdan.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { selectedDingdan = (Dingdan) parent.getItemAtPosition(position); setupChanpinSpinner(selectedDingdan); } @Override public void onNothingSelected(AdapterView<?> parent) {} }); } private void setupChanpinSpinner(Dingdan dingdan) { // 获取该订单的产品列表 List<Chanpin> chanpins = new ArrayList<>(); if (dingdan != null && dingdan.getDingdanChanpin() != null) { for (Dingdan_Chanpin dc : dingdan.getDingdanChanpin()) { if (dc != null && dc.getChanpin() != null) { chanpins.add(dc.getChanpin()); } } } // 设置产品下拉框适配器 Adapter.setupChanpinSpinner(spinnerChanpin, chanpins, getContext()); // 设置产品选择监听器 spinnerChanpin.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { selectedChanpin = (Chanpin) parent.getItemAtPosition(position); if (selectedChanpin != null) { setupZujianSpinner(selectedChanpin); } } @Override public void onNothingSelected(AdapterView<?> parent) {} }); } /** * 组件下拉框刷新 * @param chanpin */ private void setupZujianSpinner(Chanpin chanpin) { // 获取该产品的组件列表 List<Zujian> zujians = new ArrayList<>(); for (Chanpin_Zujian cz : chanpin.getChanpinZujian()) { zujians.add(cz.getZujian()); } Adapter.setupZujianSpinner(spinnerZujian,zujians,getContext()); spinnerZujian.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { selectedZujian = (Zujian) parent.getItemAtPosition(position); setupBancaiSpinner(selectedChanpin, selectedZujian); } @Override public void onNothingSelected(AdapterView<?> parent) {} }); } /** * 板材刷新 * @param chanpin * @param zujian */ private void setupBancaiSpinner(Chanpin chanpin, Zujian zujian) { // 获取该组件关联的板材 List<Bancai> bancais = new ArrayList<>(); for (Chanpin_Zujian cz : chanpin.getChanpinZujian()) { if (cz.getZujian().getId().equals(zujian.getId())) { bancais.add(cz.getBancai()); } } Adapter.setupBancaiSpinners(spinnerBancai,bancais,getContext()); spinnerBancai.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { selectedBancai = (Bancai) parent.getItemAtPosition(position); } @Override public void onNothingSelected(AdapterView<?> parent) {} }); } // ... addInventoryRecord和createRecord方法保持不变 ... private void addInventoryRecord() { // 验证必填项 if (selectedDingdan == null || selectedChanpin == null || selectedZujian == null || selectedBancai == null) { Toast.makeText(getContext(), "请选择订单、产品、组件和板材", Toast.LENGTH_SHORT).show(); return; } String shuliangStr = etShuliang.getText().toString().trim(); if (shuliangStr.isEmpty()) { Toast.makeText(getContext(), "请输入数量", Toast.LENGTH_SHORT).show(); return; } // 解析数量 int shuliang; try { shuliang = Integer.parseInt(shuliangStr); } catch (NumberFormatException e) { Toast.makeText(getContext(), "请输入有效的数量", Toast.LENGTH_SHORT).show(); return; } // 确定操作类型(进货或消耗) boolean isJinhuo = rgType.getCheckedRadioButtonId() == R.id.rb_jinhuo; // 实际开发中应从登录信息获取当前用户 User currentUser = new User(1, "当前用户", "user", "password",1); // 创建记录 createRecord(selectedDingdan, selectedChanpin, selectedZujian, selectedBancai, shuliang, isJinhuo, currentUser); Toast.makeText(getContext(), "记录添加成功", Toast.LENGTH_SHORT).show(); etShuliang.setText(""); // 清空输入框 } private void createRecord(Dingdan dingdan, Chanpin chanpin, Zujian zujian, Bancai bancai, int shuliang, boolean isJinhuo, User user) { if (isJinhuo) { // 创建进货记录 Jinhuo jinhuo = new Jinhuo(); jinhuo.setId(Data.jinhuoList.size() + 1); jinhuo.setDingdan(dingdan); jinhuo.setChanpin(chanpin); jinhuo.setZujian(zujian); jinhuo.setBancai(bancai); jinhuo.setShuliang(shuliang); jinhuo.setDate(new Date()); jinhuo.setUser(user); Data.jinhuoList.add(jinhuo); } else { // 消耗数量转为负数 shuliang = -shuliang; } // 更新库存 updateKucun(bancai, shuliang); } private void updateKucun(Bancai bancai, int changeAmount) { // 查找现有库存记录 for (Kucun k : Data.kucuns) { if (k.getBancai().getId().equals(bancai.getId())) { k.setShuliang(k.getShuliang() + changeAmount); return; } } // 如果没有找到库存记录,创建新的 Kucun newKucun = new Kucun(); newKucun.setId(Data.kucuns.size() + 1); newKucun.setBancai(bancai); newKucun.setShuliang(Math.max(changeAmount, 0)); // 确保不为负 Data.kucuns.add(newKucun); } // 新建订单方法 private void createNewDingdan() { showNewDingdanDialog(); } /** * 向订单添加产品 * @param chanpin */ private void addChanpinToDingdan(Chanpin chanpin) { if (selectedDingdan == null||chanpin==null) { Toast.makeText(getContext(), "请先选择订单", Toast.LENGTH_SHORT).show(); return; } Log.d(TAG, "addChanpinToDingdan: "); // 检查产品是否已在订单中 for (Dingdan_Chanpin dc : selectedDingdan.getDingdanChanpin()) { if (dc.getChanpin().getId().equals(chanpin.getId())) { Toast.makeText(getContext(), "该产品已添加到订单", Toast.LENGTH_SHORT).show(); return; } } // 添加到当前订单的产品列表 Dingdan_Chanpin dc = new Dingdan_Chanpin(); //dc.setId(selectedDingdan.getDingdanChanpin().size() + 1); dc.setChanpin(chanpin); dc.setDingdan(selectedDingdan); selectedDingdan.getDingdanChanpin().add(dc); // 刷新产品下拉框 setupChanpinSpinner(selectedDingdan); // 选中新添加的产品 spinnerChanpin.setSelection(selectedDingdan.getDingdanChanpin().size() - 1); Toast.makeText(getContext(), "产品添加成功", Toast.LENGTH_SHORT).show(); } // 为当前产品添加组件 private void addZujianToChanpin() { if (selectedChanpin == null) { Toast.makeText(getContext(), "请先选择产品", Toast.LENGTH_SHORT).show(); return; } // // 创建新组件(示例) // Zujian newZujian = new Zujian(); // newZujian.setId( (Data.zujians.size() + 1)); // newZujian.setName("新组件" + System.currentTimeMillis()); // // // 添加到全局列表 // Data.zujians.add(newZujian); // // // 添加到当前产品的组件列表 // Chanpin_Zujian cz = new Chanpin_Zujian(); // cz.setId(selectedChanpin.getZujians().size() + 1); // cz.setZujian(newZujian); // cz.setChanpin(selectedChanpin); // selectedChanpin.getZujians().add(cz); // // // 刷新组件下拉框 // setupZujianSpinner(selectedChanpin); // spinnerZujian.setSelection(selectedChanpin.getZujians().size() - 1); // // Toast.makeText(getContext(), "组件添加成功", Toast.LENGTH_SHORT).show(); showCreateZujianDialog(); } // 新建订单对话框 /*** * 新建订单对话框 */ private void showNewDingdanDialog() { AlertDialog.Builder builder = new AlertDialog.Builder(requireContext()); builder.setTitle("新建订单"); // 加载布局 View dialogView = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_new_dingdan, null); EditText etOrderNumber = dialogView.findViewById(R.id.et_order_number); EditText etOrderDate = dialogView.findViewById(R.id.et_order_date); EditText etDeliveryDate = dialogView.findViewById(R.id.et_delivery_date); Button btnPickOrderDate = dialogView.findViewById(R.id.btn_pick_order_date); Button btnPickDeliveryDate = dialogView.findViewById(R.id.btn_pick_delivery_date); // 设置今日日期作为默认值 Date today = new Date(); etOrderDate.setText(dateFormat.format(today)); // 日期选择监听器 DatePickerDialog.OnDateSetListener orderDateListener = (view, year, month, dayOfMonth) -> { Calendar cal = Calendar.getInstance(); cal.set(year, month, dayOfMonth); etOrderDate.setText(dateFormat.format(cal.getTime())); }; DatePickerDialog.OnDateSetListener deliveryDateListener = (view, year, month, dayOfMonth) -> { Calendar cal = Calendar.getInstance(); cal.set(year, month, dayOfMonth); etDeliveryDate.setText(dateFormat.format(cal.getTime())); }; // 下单日期选择按钮 btnPickOrderDate.setOnClickListener(v -> { Calendar cal = Calendar.getInstance(); new DatePickerDialog(requireContext(), orderDateListener, cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH)) .show(); }); /** * / 出货日期选择按钮 */ btnPickDeliveryDate.setOnClickListener(v -> { Calendar cal = Calendar.getInstance(); new DatePickerDialog(requireContext(), deliveryDateListener, cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH)) .show(); }); builder.setView(dialogView); builder.setPositiveButton("创建", (dialog, which) -> { String orderNumber = etOrderNumber.getText().toString().trim(); String orderDateStr = etOrderDate.getText().toString(); String deliveryDateStr = etDeliveryDate.getText().toString(); for (Dingdan dingdan:Data.dingdans ) { if (dingdan.getNumber()==null||orderNumber==null){ Log.d(TAG, "showNewDingdanDialog: "); return; } if(dingdan.getNumber().equals(orderNumber)){ Toast.makeText(getContext(), "已有该订单号", Toast.LENGTH_SHORT).show(); return; } } // 验证输入 if (orderNumber.isEmpty()) { Toast.makeText(getContext(), "请输入订单号", Toast.LENGTH_SHORT).show(); return; } try { // 解析日期 Date orderDate = dateFormat.parse(orderDateStr); Date deliveryDate = deliveryDateStr.isEmpty() ? null : dateFormat.parse(deliveryDateStr); // 创建订单 createAndSaveDingdan(orderNumber, orderDate, deliveryDate); } catch (ParseException e) { Toast.makeText(getContext(), "日期格式错误", Toast.LENGTH_SHORT).show(); } }); builder.setNegativeButton("取消", null); builder.show(); } /** * 创建并保存订单 */ private void createAndSaveDingdan(String orderNumber, Date orderDate, Date deliveryDate) { Dingdan newDingdan = new Dingdan(); newDingdan.setId(Data.dingdans.size() + 1); newDingdan.setNumber(orderNumber); newDingdan.setXiadan(orderDate); newDingdan.setJiaohuo(deliveryDate); newDingdan.setDingdanChanpin(new ArrayList<>()); newDingdan.setDingdanChanpinZujian(new ArrayList<>()); Data.dingdans.add(newDingdan); // 刷新下拉框 setupDingdanSpinner(); spinnerDingdan.setSelection(Data.dingdans.size() - 1); Toast.makeText(getContext(), "新建订单成功", Toast.LENGTH_SHORT).show(); } /** * 显示添加产品弹窗 */ private void showAddChanpinDialog() { AlertDialog.Builder builder = new AlertDialog.Builder(requireContext()); builder.setTitle("添加产品到订单"); // 加载布局 View dialogView = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_add_chanpin, null); Spinner spinnerChanpinSelection = dialogView.findViewById(R.id.spinner_chanpin_selection); Button btnNewChanpin = dialogView.findViewById(R.id.btn_new_chanpin); // 设置产品下拉框 if (Data.chanpins == null || Data.chanpins.isEmpty()) { Toast.makeText(getContext(), "没有可用的产品,请先创建产品", Toast.LENGTH_SHORT).show(); return; } Adapter.setupChanpinSpinner(spinnerChanpinSelection, Data.chanpins, getContext()); // 新建产品按钮点击事件 btnNewChanpin.setOnClickListener(v -> { showNewChanpinDialog(() -> { // 新建产品后刷新下拉框 Adapter.setupChanpinSpinner(spinnerChanpinSelection, Data.chanpins, getContext()); // 默认选中新建的产品 spinnerChanpinSelection.setSelection(Data.chanpins.size() - 1); }); }); builder.setView(dialogView); builder.setPositiveButton("添加", (dialog, which) -> { Chanpin selectedChanpin = (Chanpin) spinnerChanpinSelection.getSelectedItem(); if (selectedChanpin == null) { Toast.makeText(getContext(), "请选择一个产品", Toast.LENGTH_SHORT).show(); return; } // 将选中的产品添加到当前订单 addChanpinToDingdan(selectedChanpin); }); builder.setNegativeButton("取消", null); builder.show(); } /** * 显示新建产品弹窗 * @param refreshCallback 新建后的回调,用于刷新产品列表 */ private void showNewChanpinDialog(Runnable refreshCallback) { AlertDialog.Builder builder = new AlertDialog.Builder(requireContext()); builder.setTitle("新建产品"); View dialogView = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_new_chanpin, null); EditText etChanpinName = dialogView.findViewById(R.id.et_chanpin_name); builder.setView(dialogView); builder.setPositiveButton("创建", (dialog, which) -> { String chanpinName = etChanpinName.getText().toString().trim(); if (chanpinName.isEmpty()) { Toast.makeText(getContext(), "请输入产品名称", Toast.LENGTH_SHORT).show(); return; } // 检查名称是否重复 for (Chanpin cp : Data.chanpins) { if (cp.getBianhao().equals(chanpinName)) { Toast.makeText(getContext(), "产品名称重复", Toast.LENGTH_SHORT).show(); return; } } // 创建新产品 Chanpin newChanpin = new Chanpin(); newChanpin.setId(Data.chanpins.size() + 1); newChanpin.setBianhao(chanpinName); newChanpin.setChanpinZujian(new ArrayList<>()); Data.chanpins.add(newChanpin); refreshCallback.run(); Toast.makeText(getContext(), "产品创建成功", Toast.LENGTH_SHORT).show(); }); builder.setNegativeButton("取消", null); builder.show(); } /** * 添加新组件 */ private void showCreateZujianDialog() { AlertDialog.Builder builder = new AlertDialog.Builder(requireContext()); builder.setTitle("添加新组件"); // 创建自定义布局 View dialogView = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_create_zujian_bancai, null); EditText etZujianName = dialogView.findViewById(R.id.et_zujian_name); Spinner spinnerbancai = dialogView.findViewById(R.id.spinner_bancai); SearchView searchBancai = dialogView.findViewById(R.id.search_bancai); Button btnAddBancai = dialogView.findViewById(R.id.btn_add_bancai); // 设置添加板材按钮点击事件 btnAddBancai.setOnClickListener(v -> { // 弹出添加板材的弹窗,并传入当前Spinner用于刷新 showCreateBancaiDialog(spinnerbancai); }); // 板材适配器 Adapter.setupBancaiSpinners(spinnerbancai,Data.bancais,getContext()); // 设置搜索功能 searchBancai.setOnQueryTextListener(new SearchView.OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String query) { return false; } @Override public boolean onQueryTextChange(String newText) { // 过滤板材列表 List<Bancai> filteredList = new ArrayList<>(); for (Bancai bancai : Data.bancais) { if ( bancai.TableText().toLowerCase().contains(newText.toLowerCase())) { filteredList.add(bancai); } } // 板材适配器 Adapter.setupBancaiSpinners(spinnerbancai,filteredList,getContext()); return true; } }); // 添加木皮预览标签 builder.setView(dialogView); builder.setPositiveButton("创建", (dialog, which) -> { // 获取用户输入 String zujianName = etZujianName.getText().toString().trim(); Bancai selectedBancai = (Bancai) spinnerbancai.getSelectedItem(); if (zujianName.isEmpty()) { Toast.makeText(getContext(), "请输入组件名称", Toast.LENGTH_SHORT).show(); return; } // 创建新组件 Zujian newZujian = new Zujian(); newZujian.setId(Data.zujians.size() + 1); newZujian.setName(zujianName); // 创建新板材 // 添加到全局列表 Data.zujians.add(newZujian); // 添加到当前产品的组件列表 Chanpin_Zujian cz = new Chanpin_Zujian(); cz.setZujian(newZujian); cz.setBancai(selectedBancai); // 关联新创建的板材 cz.setChanpin(selectedChanpin); selectedChanpin.getChanpinZujian().add(cz); // 刷新组件下拉框 setupZujianSpinner(selectedChanpin); spinnerZujian.setSelection(selectedChanpin.getChanpinZujian().size() - 1); Toast.makeText(getContext(), "组件和板材添加成功", Toast.LENGTH_SHORT).show(); }); builder.setNegativeButton("取消", null); builder.show(); } // 显示创建板材的弹窗 private void showCreateBancaiDialog(Spinner spinnerToRefresh) { AlertDialog.Builder builder = new AlertDialog.Builder(requireContext()); builder.setTitle("添加新板材"); // 加载布局 View dialogView = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_create_bancai, null); Spinner spinnerCaizhi = dialogView.findViewById(R.id.spinner_caizhi); Spinner spinnerMupi1 = dialogView.findViewById(R.id.spinner_mupi1); Spinner spinnerMupi2 = dialogView.findViewById(R.id.spinner_mupi2); EditText TextInputEditTextHoudu=dialogView.findViewById(R.id.edittext_houdu); TextInputEditTextHoudu.setTextIsSelectable(true); // 绑定新建材质按钮 Button btnNewCaizhi = dialogView.findViewById(R.id.btn_new_caizhi); btnNewCaizhi.setOnClickListener(v -> { showNewOptionDialog("材质", option -> { // 避免重复添加 for (Caizhi caizhi : Data.caizhis) { if (caizhi.getName().equals(option)) return; } // 创建新材质 Caizhi newCaizhi = new Caizhi(); newCaizhi.setName(option); newCaizhi.setId(Data.caizhis.size() + 1); newCaizhi.setBancai(new ArrayList<>()); Data.caizhis.add(newCaizhi); // 刷新下拉框 Adapter.setupCaizhiSpinner(spinnerCaizhi, Data.caizhis, requireContext()); spinnerCaizhi.setSelection(Data.caizhis.size() - 1); }); }); // 绑定新建木皮按钮 Button btnNewMupi = dialogView.findViewById(R.id.btn_new_mupi); btnNewMupi.setOnClickListener(v -> { // 弹出新建木皮对话框 showNewMupiDialog(() -> { // 回调中刷新木皮下拉框 Adapter.setupMupiSpinner(spinnerMupi1, Data.mupis, requireContext()); Adapter.setupMupiSpinner(spinnerMupi2, Data.mupis, requireContext()); }); }); // 获取所有材质选项(从现有板材中提取) List<Caizhi> allCaizhi = Data.caizhis; List<Mupi> allMupi = Data.mupis; // 设置下拉框适配器 Adapter.setupCaizhiSpinner(spinnerCaizhi, allCaizhi, requireContext()); Adapter.setupMupiSpinner(spinnerMupi1, allMupi, requireContext()); Adapter.setupMupiSpinner(spinnerMupi2, allMupi, requireContext()); builder.setView(dialogView); builder.setPositiveButton("创建", (dialog, which) -> { Caizhi caizhi = (Caizhi)spinnerCaizhi.getSelectedItem() ; Mupi mupi1 = (Mupi)spinnerMupi1.getSelectedItem() ; Mupi mupi2 = (Mupi) spinnerMupi2.getSelectedItem() ; // 获取 TextInputEditText 的内容并进行校验 String houduText = TextInputEditTextHoudu.getText().toString().trim(); Double houdu = null; try { if (!houduText.isEmpty()) { // 检查输入是否为空 houdu = Double.valueOf(houduText); // 尝试将字符串转换为 Double } } catch (NumberFormatException e) { // 捕获转换异常并提示用户 Toast.makeText(getContext(), "厚度输入无效,请输入数字", Toast.LENGTH_SHORT).show(); return; } // 校验 caizhi 和 houdu 是否均有效 if (caizhi == null || houdu == null) { Toast.makeText(getContext(), "请选择材质并输入有效的厚度", Toast.LENGTH_SHORT).show(); return; } // 创建新板材 Bancai newBancai = new Bancai(); newBancai.setId(Data.bancais.size() + 1); newBancai.setCaizhi(caizhi); newBancai.setMupi1(mupi1); newBancai.setMupi2(mupi2); newBancai.setHoudu(houdu); caizhi.getBancai().add(newBancai); if (mupi1 != null) { mupi1.getBancais().add(newBancai); } if (mupi2 != null) { mupi2.getBancais().add(newBancai); } // 添加到全局列表 Data.bancais.add(newBancai); // 刷新Spinner(如果传入) if (spinnerToRefresh != null) { Adapter.setupBancaiSpinners(spinnerToRefresh, Data.bancais, getContext()); spinnerToRefresh.setSelection(Data.bancais.size() - 1); } Toast.makeText(getContext(), "板材添加成功", Toast.LENGTH_SHORT).show(); }); builder.setNegativeButton("取消", null); builder.show(); } // 显示新建选项的弹窗 /** * 显示新建选项的弹窗 * @param type 新建什么 * @param listener 反回 */ private void showNewOptionDialog(String type, OnOptionCreatedListener listener) { AlertDialog.Builder builder = new AlertDialog.Builder(requireContext()); builder.setTitle("新建" + type); final EditText input = new EditText(requireContext()); input.setHint("请输入" + type); builder.setView(input); builder.setPositiveButton("确定", (dialog, which) -> { String option = input.getText().toString().trim(); if (!option.isEmpty()) { listener.onOptionCreated(option); } }); builder.setNegativeButton("取消", null); builder.show(); } // 回调接口 interface OnOptionCreatedListener { void onOptionCreated(String option); } // 新建木皮对话框 private void showNewMupiDialog(Runnable refreshCallback) { AlertDialog.Builder builder = new AlertDialog.Builder(requireContext()); builder.setTitle("新建木皮"); View view = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_new_mupi, null); EditText etName = view.findViewById(R.id.et_mupi_name); RadioGroup rgFinish = view.findViewById(R.id.rg_finish); builder.setView(view); builder.setPositiveButton("创建", (dialog, which) -> { String name = etName.getText().toString().trim(); if (name.isEmpty()) { Toast.makeText(getContext(), "请输入木皮名称", Toast.LENGTH_SHORT).show(); return; } // 避免重复添加 for (Mupi m : Data.mupis) { if (m.getName().equals(name)) return; } // 创建木皮对象 Mupi newMupi = new Mupi(); newMupi.setId(Data.mupis.size() + 1); newMupi.setName(name); newMupi.setYou(rgFinish.getCheckedRadioButtonId() == R.id.rb_painted); newMupi.setBancais(new ArrayList<>()); Data.mupis.add(newMupi); refreshCallback.run(); }); builder.setNegativeButton("取消", null); builder.show(); } }<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="16dp"> <!-- 板材选择标题 --> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="组件选择" android:textStyle="bold" android:layout_marginTop="8dp"/> <!-- 板材选择区 --> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <!-- 组件名称输入 --> <Spinner android:id="@+id/et_zujian_name" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:padding="8dp"/> <!-- 添加板材按钮 --> <Button android:id="@+id/btn_add_zujian" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="+" android:layout_marginLeft="8dp"/> </LinearLayout> <!-- 板材搜索框 --> <SearchView android:id="@+id/search_bancai" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="16dp" android:queryHint="搜索板材..." android:iconifiedByDefault="false" android:layout_marginBottom="8dp"/> <!-- 板材选择标题 --> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="板材选择" android:textStyle="bold" android:layout_marginTop="8dp"/> <!-- 板材选择区 --> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Spinner android:id="@+id/spinner_bancai" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:padding="8dp"/> <!-- 添加板材按钮 --> <Button android:id="@+id/btn_add_bancai" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="+" android:layout_marginLeft="8dp"/> </LinearLayout> </LinearLayout><?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:fillViewport="true"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="16dp"> <!-- 订单选择 --> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="选择订单" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:weightSum="4"> <Spinner android:id="@+id/spinner_dingdan" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="3" android:prompt="@string/select_dingdan" /> <Button android:id="@+id/btn_new_dingdan" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="新建订单" /> </LinearLayout> <!-- 产品选择 --> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="选择产品" android:layout_marginTop="16dp"/> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:weightSum="4"> <Spinner android:id="@+id/spinner_chanpin" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="3" android:prompt="@string/select_chanpin" /> <Button android:id="@+id/btn_add_chanpin" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="添加产品" /> </LinearLayout> <!-- 组件选择 --> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="选择组件" android:layout_marginTop="16dp"/> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:weightSum="4"> <Spinner android:id="@+id/spinner_zujian" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="3" android:prompt="@string/select_zujian" /> <Button android:id="@+id/btn_add_zujian" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="添加组件" /> </LinearLayout> <!-- 板材选择 --> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="选择板材" android:layout_marginTop="16dp"/> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:weightSum="4"> <Spinner android:id="@+id/spinner_bancai" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="3" android:prompt="@string/select_bancai" /> </LinearLayout> <!-- 数量输入 --> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="数量" android:layout_marginTop="16dp"/> <EditText android:id="@+id/et_shuliang" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="number" /> <!-- 类型选择 --> <RadioGroup android:id="@+id/rg_type" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="16dp" android:orientation="horizontal"> <RadioButton android:id="@+id/rb_jinhuo" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="进货" android:checked="true"/> <RadioButton android:id="@+id/rb_xiaohao" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="消耗" /> </RadioGroup> <!-- 提交按钮 --> <Button android:id="@+id/btn_submit" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="24dp" android:text="提交" /> </LinearLayout> </ScrollView>E FATAL EXCEPTION: main Process: com.example.kucun2, PID: 15672 java.lang.ClassCastException: androidx.appcompat.widget.AppCompatSpinner cannot be cast to android.widget.EditText at com.example.kucun2.ui.jinhuo.AddInventoryFragment.showCreateZujianDialog(AddInventoryFragment.java:565) at com.example.kucun2.ui.jinhuo.AddInventoryFragment.addZujianToChanpin(AddInventoryFragment.java:344) at com.example.kucun2.ui.jinhuo.AddInventoryFragment.lambda$onCreateView$2(AddInventoryFragment.java:90) at com.example.kucun2.ui.jinhuo.AddInventoryFragment.$r8$lambda$g7ZiJT_Sfp7Zl8Vt7clUdS_KcN8(Unknown Source:0) at com.example.kucun2.ui.jinhuo.AddInventoryFragment$$ExternalSyntheticLambda2.onClick(D8$$SyntheticClass:0) at android.view.View.performClick(View.java:8166) at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:1218) at android.view.View.performClickInternal(View.java:8143) at android.view.View.-$$Nest$mperformClickInternal(Unknown Source:0) at android.view.View$PerformClick.run(View.java:32198)
06-12
logcat:2025-06-23 15:10:40.037 1491-3220 ActivityTrigger system_server E activityStartTrigger: not whiteListedcom.hik.netsdk.SimpleDemo/com.hik.netsdk.SimpleDemo.View.MainActivity/11 2025-06-23 15:10:40.038 1491-3220 ActivityTrigger system_server E activityResumeTrigger: not whiteListedcom.hik.netsdk.SimpleDemo/com.hik.netsdk.SimpleDemo.View.MainActivity/11 2025-06-23 15:10:40.044 1491-3220 ActivityTrigger system_server E activityResumeTrigger: not whiteListedcom.hik.netsdk.SimpleDemo/com.hik.netsdk.SimpleDemo.View.MainActivity/11 ---------------------------- PROCESS STARTED (15498) for package com.hik.netsdk.SimpleDemo ---------------------------- 2025-06-23 15:10:40.330 15498-15498 ResourceType com.hik.netsdk.SimpleDemo W No package identifier when getting name for resource number 0x00000000 2025-06-23 15:10:40.366 15498-15498 ResourceType com.hik.netsdk.SimpleDemo W No package identifier when getting name for resource number 0x00000000 2025-06-23 15:10:40.399 15498-15498 NetworkSecurityConfig com.hik.netsdk.SimpleDemo D No Network Security Config specified, using platform default 2025-06-23 15:10:40.406 15498-15498 ResourceType com.hik.netsdk.SimpleDemo W No package identifier when getting name for resource number 0x00000000 2025-06-23 15:10:40.412 15498-15498 ResourceType com.hik.netsdk.SimpleDemo W No package identifier when getting name for resource number 0x00000000 2025-06-23 15:10:40.446 15498-15533 ResourceType com.hik.netsdk.SimpleDemo W No package identifier when getting name for resource number 0x00000000 2025-06-23 15:10:40.450 15498-15498 AccessibilityManager com.hik.netsdk.SimpleDemo D AccessibilityManager status: mPackageName = com.hik.netsdk.SimpleDemo, mOptimizeEnabled = true, mIsEnabled = false, mIsUiAutomationEnabled = false, mIsInterestedPackage =false 2025-06-23 15:10:40.461 15498-15533 ViewContentFactory com.hik.netsdk.SimpleDemo D initViewContentFetcherClass 2025-06-23 15:10:40.461 15498-15533 ViewContentFactory com.hik.netsdk.SimpleDemo D getInterceptorPackageInfo 2025-06-23 15:10:40.462 15498-15533 ViewContentFactory com.hik.netsdk.SimpleDemo D getInitialApplication took 1ms 2025-06-23 15:10:40.462 15498-15533 ViewContentFactory com.hik.netsdk.SimpleDemo D packageInfo.packageName: com.miui.catcherpatch 2025-06-23 15:10:40.464 15498-15533 ResourceType com.hik.netsdk.SimpleDemo W No package identifier when getting name for resource number 0x00000000 2025-06-23 15:10:40.471 15498-15503 zygote64 com.hik.netsdk.SimpleDemo I Do partial code cache collection, code=30KB, data=19KB 2025-06-23 15:10:40.471 15498-15503 zygote64 com.hik.netsdk.SimpleDemo I After code cache collection, code=30KB, data=19KB 2025-06-23 15:10:40.471 15498-15503 zygote64 com.hik.netsdk.SimpleDemo I Increasing code cache capacity to 128KB 2025-06-23 15:10:40.477 15498-15533 ViewContentFactory com.hik.netsdk.SimpleDemo D initViewContentFetcherClass took 16ms 2025-06-23 15:10:40.477 15498-15533 ContentCatcher com.hik.netsdk.SimpleDemo I ViewContentFetcher : ViewContentFetcher 2025-06-23 15:10:40.478 15498-15533 ViewContentFactory com.hik.netsdk.SimpleDemo D createInterceptor took 16ms 2025-06-23 15:10:40.670 15498-15503 zygote64 com.hik.netsdk.SimpleDemo I Do partial code cache collection, code=39KB, data=37KB 2025-06-23 15:10:40.670 15498-15503 zygote64 com.hik.netsdk.SimpleDemo I After code cache collection, code=39KB, data=37KB 2025-06-23 15:10:40.670 15498-15503 zygote64 com.hik.netsdk.SimpleDemo I Increasing code cache capacity to 256KB 2025-06-23 15:10:40.670 15498-15503 zygote64 com.hik.netsdk.SimpleDemo I Compiler allocated 4MB to compile void android.view.View.<init>(android.content.Context, android.util.AttributeSet, int, int) 2025-06-23 15:10:40.772 15498-15498 AndroidRuntime com.hik.netsdk.SimpleDemo D Shutting down VM 2025-06-23 15:10:40.774 15498-15498 AndroidRuntime com.hik.netsdk.SimpleDemo E FATAL EXCEPTION: main Process: com.hik.netsdk.SimpleDemo, PID: 15498 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.hik.netsdk.SimpleDemo/com.hik.netsdk.SimpleDemo.View.MainActivity}: java.lang.ClassCastException: androidx.appcompat.widget.AppCompatTextView cannot be cast to androidx.appcompat.widget.Toolbar at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2856) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2931) at android.app.ActivityThread.-wrap11(Unknown Source:0) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1620) at android.os.Handler.dispatchMessage(Handler.java:105) at android.os.Looper.loop(Looper.java:173) at android.app.ActivityThread.main(ActivityThread.java:6698) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:782) Caused by: java.lang.ClassCastException: androidx.appcompat.widget.AppCompatTextView cannot be cast to androidx.appcompat.widget.Toolbar at com.hik.netsdk.SimpleDemo.View.MainActivity.initUIComponents(MainActivity.java:137) at com.hik.netsdk.SimpleDemo.View.MainActivity.onCreate(MainActivity.java:117) at android.app.Activity.performCreate(Activity.java:7040) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1214) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2809) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2931)  at android.app.ActivityThread.-wrap11(Unknown Source:0)  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1620)  at android.os.Handler.dispatchMessage(Handler.java:105)  at android.os.Looper.loop(Looper.java:173)  at android.app.ActivityThread.main(ActivityThread.java:6698)  at java.lang.reflect.Method.invoke(Native Method)  at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:782)  2025-06-23 15:10:40.804 15498-15498 Process com.hik.netsdk.SimpleDemo I Sending signal. PID: 15498 SIG: 9 依据上述logcat日志解决在VideoListActivity中实现通过用户在设备列表选择Videolist播放通道后传递参数跨应用ysy1.apk中实现已经云接入萤石开放平台的75台摄像头实现实时预览(即摄像头实时监控,现在只需要实现最基础的实时预览)的功能 VideoListActivity:package com.jd.projects.wlw.video; import android.annotation.SuppressLint; import android.app.Activity; import android.app.AlertDialog; import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.AssetManager; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.Message; import android.support.v4.content.FileProvider; import android.view.View; import android.view.View.OnClickListener; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.Button; import android.widget.ListView; import android.widget.Toast; import com.jd.projects.wlw.DeviceMapActivity; import com.jd.projects.wlw.R; import com.jd.projects.wlw.adapter.VideoDevAdapter; import com.jd.projects.wlw.dialog.CreateLoadingDialog; import com.jd.projects.wlw.hkdemo.HkMainActivity; import com.jd.projects.wlw.units.FileUtils; import com.jd.projects.wlw.units.NetHelper; import com.jd.projects.wlw.xmvideo.DahuaVideoActicity; import org.json.JSONObject; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; public class VideoListActivity extends Activity { private ArrayList<Map<String, String>> mvideolist; private Context context; public static Map<String, String> map; public Button curve3; private String aliasname = "";//站点别名 public static final String package_name = "com.hik.netsdk.SimpleDemo"; public static final String package_name2 = "com.example.funsdkdemo"; public static final String APK_NAME = "ysy1.apk"; public static final String APK_NAME2 = "zxcv.apk"; private int curersioncode = 11;//萤石云插件apk最新版本号。 private int curersioncode2 = 5;//雄迈插件apk最新版本号。 //private String Appkey = "05381ff665c843c398a0a3b6d6e341ac"; private String Appkey = ""; private String devserial = ""; private String VerifyCode = ""; private int channelName = 1; private String accessToken = ""; Map<String, String> mmap; private String response = ""; private CreateLoadingDialog loadingDialg = new CreateLoadingDialog(); private String user_control_power, site_control_power; private String netmode = ""; private String xmip = ""; private String xmport = ""; private String xmusername = ""; private String xmpassword = ""; private String devSn = ""; private String xmmark = ""; private double intentLat = 0.0; private double intentLng = 0.0; @SuppressLint("HandlerLeak") Handler mHandler = new Handler() { public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case 0: loadingDialg.dismissLoadingDialog(); System.out.println("--访问令牌接口返回--" + response); try { JSONObject object = new JSONObject(response); String code = object.get("code").toString(); String mmsg = object.get("msg").toString(); if (code.equals("200")) { JSONObject object2 = (JSONObject) object.get("data"); accessToken = object2.get("accessToken").toString(); System.out.println("--访问令牌为:--" + accessToken); openAPK(); } else { Toast.makeText(context, mmsg, Toast.LENGTH_SHORT).show(); } } catch (Exception e) { // TODO: handle exception } break; default: break; } } ; }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.avtivity_videolist); intentLat = getIntent().getDoubleExtra("intentLat", 0.0); intentLng = getIntent().getDoubleExtra("intentLng", 0.0); context = this; initData(); initView(); } private void initView() { ListView listView = (ListView) findViewById(R.id.Videolist); curve3 = (Button) findViewById(R.id.curve3); VideoDevAdapter adapter = new VideoDevAdapter(mvideolist, context); listView.setAdapter(adapter); listView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { map = mvideolist.get(position); String mark = map.get("mark"); if (mark.equals("yiwei")) { SerializableMap myMap = new SerializableMap(); myMap.setMap(map); Bundle bundle = new Bundle(); bundle.putSerializable("map", myMap); bundle.putString("user_control_power", user_control_power); bundle.putString("site_control_power", site_control_power); bundle.putString("netmode", netmode); Intent intent = new Intent(); intent.putExtras(bundle); intent.setClass(getApplicationContext(), YwVideoPlayerActivity.class); startActivity(intent); } else if (mark.equals("haikang")) { // 跳转海康页面 String strIP = map.get("serverUrl").trim(); String nPort = map.get("serverPort").trim(); String strUser = map.get("userName").trim(); String strPsd = map.get("userPwd").trim(); Bundle bundle = new Bundle(); bundle.putString("ip", strIP); bundle.putString("port", nPort); bundle.putString("username", strUser); bundle.putString("password", strPsd); bundle.putString("user_control_power", user_control_power); bundle.putString("site_control_power", site_control_power); bundle.putString("netmode", netmode); Intent intent2 = new Intent(); intent2.putExtras(bundle); intent2.setClass(getApplicationContext(), HkMainActivity.class); startActivity(intent2); } else if (mark.equals("dahua")) { // 跳转大华页面 String strIP = map.get("serverUrl").trim(); String nPort = map.get("serverPort").trim(); String strUser = map.get("userName").trim(); String strPsd = map.get("userPwd").trim(); Bundle bundle = new Bundle(); bundle.putString("ip", strIP); bundle.putString("port", nPort); bundle.putString("username", strUser); bundle.putString("password", strPsd); bundle.putString("user_control_power", user_control_power); bundle.putString("site_control_power", site_control_power); bundle.putString("netmode", netmode); Intent intent2 = new Intent(); intent2.putExtras(bundle); intent2.setClass(getApplicationContext(), DahuaVideoActicity.class); startActivity(intent2); } else if (mark.equals("xiongmai") || mark.equals("4Gxiongmai")) { xmip = map.get("serverUrl").trim(); xmport = map.get("serverPort").trim(); xmusername = map.get("userName").trim(); xmpassword = map.get("userPwd").trim(); devSn = map.get("devSn").trim();//雄迈4G球机序列号 xmmark = mark; openAPK2(); } else if (mark.equals("HK4GIPC01")) { // 海康4G摄像机---公司现在暂无使用 String strIP = map.get("serverUrl");//设备序列号 String strUser = map.get("userName");//设备验证名 String strPsd = map.get("userPwd"); Bundle bundle = new Bundle(); bundle.putString("ip", strIP.trim()); bundle.putString("username", strUser.trim()); bundle.putString("password", strPsd.trim()); Intent intent2 = new Intent(); intent2.putExtras(bundle); intent2.setClass(getApplicationContext(), Hk4GVideoMain.class); startActivity(intent2); } else if (mark.equals("HK4GIPC02")) { // 萤石云平台摄像机 devserial = map.get("serverUrl").trim();// 设备序列号 VerifyCode = map.get("serverPort").trim();// 设备验证码 Appkey = map.get("userName").trim();// AppKey channelName = Integer.parseInt(map.get("channelNum").trim());// channelName String secret = map.get("userPwd").trim();// Secret //System.out.println("---测试参数--"+appkey+"---"+secret); if (accessToken.equals("")) { loadingDialg.createLoadingDialog(context, "访问令牌获取中...").show(); // 获取访问令牌 mmap = new HashMap<>(); mmap.put("appKey", Appkey); mmap.put("appSecret", secret); new Thread(new Runnable() { @Override public void run() { response = NetHelper.submitPostData("https://open.ys7.com/api/lapp/token/get", mmap, "utf-8");//encode mHandler.sendEmptyMessage(0); } }).start(); } else { openAPK(); } } } }); findViewById(R.id.back).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO 自动生成的方法存根 VideoListActivity.this.finish(); } }); curve3.setOnClickListener(view -> { Intent intent = new Intent(VideoListActivity.this, DeviceMapActivity.class); intent.putExtra("intentLat",intentLat); intent.putExtra("intentLng",intentLng); intent.putExtra("isShowTitle",true); startActivity(intent); }); } private void initData() { //mvideolist = VideoActivity.videolist; Bundle bundle = getIntent().getExtras(); mvideolist = (ArrayList<Map<String, String>>) bundle.get("list"); aliasname = bundle.getString("aliasname"); user_control_power = bundle.getString("user_control_power"); site_control_power = bundle.getString("site_control_power"); netmode = bundle.getString("netmode"); } protected void openAPK() { // 首先判断SD卡是否可用 if (!FileUtils.getSDcard()) { Toast.makeText(this, "外部存储不可用,此功能禁用", Toast.LENGTH_SHORT).show(); } // 判断SD卡是否已安装 else if (!FileUtils.checkInstall(getApplicationContext(), package_name)) { AlertDialog.Builder builder = new AlertDialog.Builder(VideoListActivity.this); builder.setTitle("提示").setMessage("未安装视频插件,是否安装?") .setPositiveButton("安装", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { // 读取APK readApk(); } }).setNegativeButton("取消", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { } }); AlertDialog dialog = builder.create(); dialog.show(); } else { //已安装应用,直接打开应用 //判断是否需要更新 PackageManager pm = context.getPackageManager(); try { //通过包名获取已安装应用的信息,然后获取版本号。在与最新版本号对比是否需要进行更新。 PackageInfo info = pm.getPackageInfo(package_name, 1); int code = info.versionCode; if (curersioncode > code) { //有新版本需要跟新 AlertDialog.Builder builder = new AlertDialog.Builder(VideoListActivity.this); builder.setTitle("提示").setMessage("视频插件需要更新,请点击安装!") .setPositiveButton("安装", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { // 读取APK readApk(); } }).setNegativeButton("取消", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { } }); AlertDialog dialog = builder.create(); dialog.show(); } else { //不需要更新,直接打开APK startApk2(); } } catch (NameNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } protected void openAPK2() { // 首先判断SD卡是否可用 if (!FileUtils.getSDcard()) { Toast.makeText(this, "外部存储不可用,此功能禁用", Toast.LENGTH_SHORT).show(); } // 判断SD卡是否已安装 else if (!FileUtils.checkInstall(getApplicationContext(), package_name2)) { AlertDialog.Builder builder = new AlertDialog.Builder(VideoListActivity.this); builder.setTitle("提示").setMessage("未安装视频插件,是否安装?") .setPositiveButton("安装", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { // 读取APK readApk2(); } }).setNegativeButton("取消", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { } }); AlertDialog dialog = builder.create(); dialog.show(); } else { //已安装应用,直接打开应用 //判断是否需要更新 PackageManager pm = context.getPackageManager(); try { //通过包名获取已安装应用的信息,然后获取版本号。在与最新版本号对比是否需要进行更新。 PackageInfo info = pm.getPackageInfo(package_name2, 1); int code = info.versionCode; if (curersioncode2 > code) { //有新版本需要跟新 AlertDialog.Builder builder = new AlertDialog.Builder(VideoListActivity.this); builder.setTitle("提示").setMessage("视频插件需要更新,请点击安装!") .setPositiveButton("安装", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { // 读取APK readApk2(); } }).setNegativeButton("取消", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { } }); AlertDialog dialog = builder.create(); dialog.show(); } else { //不需要更新,直接打开APK startApk3(); } } catch (NameNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } protected void readApk() { InputStream in1 = null; OutputStream out; FileUtils fileUtils = new FileUtils(); AssetManager am = getAssets(); byte[] buffer = new byte[1024]; int read; try { in1 = am.open(APK_NAME); File file = new File(fileUtils.getSDPATH() + APK_NAME); file.createNewFile(); out = new FileOutputStream(file); while ((read = in1.read(buffer)) != -1) { out.write(buffer, 0, read); } out.flush(); in1.close(); out.close(); } catch (IOException e) { } finally { try { in1.close(); } catch (IOException e) { } } installApk(APK_NAME); } protected void readApk2() { InputStream in1 = null; InputStream in2 = null; InputStream in3 = null; InputStream in4 = null; InputStream in5 = null; OutputStream out = null; FileUtils fileUtils = new FileUtils(); AssetManager am = getAssets(); byte[] buffer = new byte[1024]; int read = 0; try { in1 = am.open("zxcv1.apk"); in2 = am.open("zxcv2.apk"); in3 = am.open("zxcv3.apk"); in4 = am.open("zxcv4.apk"); in5 = am.open("zxcv5.apk"); if (!fileUtils.isFileExist(APK_NAME2) && new File(fileUtils.getSDPATH() + APK_NAME2).length() < 1) { File file = new File(fileUtils.getSDPATH() + APK_NAME2); file.createNewFile(); out = new FileOutputStream(file); while ((read = in1.read(buffer)) != -1) { out.write(buffer, 0, read); } while ((read = in2.read(buffer)) != -1) { out.write(buffer, 0, read); } while ((read = in3.read(buffer)) != -1) { out.write(buffer, 0, read); } while ((read = in4.read(buffer)) != -1) { out.write(buffer, 0, read); } while ((read = in5.read(buffer)) != -1) { out.write(buffer, 0, read); } out.flush(); in1.close(); in2.close(); in3.close(); in4.close(); in5.close(); out.close(); } } catch (IOException e) { } finally { try { in1.close(); in2.close(); in3.close(); in4.close(); in5.close(); } catch (IOException e) { } } installApk(APK_NAME2); } protected void installApk(String apkName) { //得到了Android外部存储目录 String fileName = Environment.getExternalStorageDirectory() + "/" + apkName; Intent intent = new Intent(Intent.ACTION_VIEW); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); Uri uri = FileProvider.getUriForFile(context, context.getPackageName() + ".fileProvider", new File(fileName)); intent.setDataAndType(uri, "application/vnd.android.package-archive"); this.startActivity(intent); } protected void startApk2() { ComponentName componentName = new ComponentName("com.hik.netsdk.SimpleDemo", "com.hik.netsdk.SimpleDemo.View.MainActivity"); Intent intent = new Intent(); // Intent intent = new Intent("chroya.foo"); Bundle bundle = new Bundle(); /* bundle.putString("serial", "811729242");//摄像机序列号 bundle.putString("VerifyCode", "CFEJRH");//摄像机验证码 bundle.putString("accessToken", "at.13zoz9dj48txpxtmbtdbxyp86yppa0kv-8377rzprmz-1ga3ixh-2csonzo9x");//访问令牌,7天过期。 */ bundle.putString("appkey", Appkey);//Appkey bundle.putString("serial", devserial);//摄像机序列号 bundle.putString("VerifyCode", VerifyCode);//摄像机验证码 bundle.putString("accessToken", accessToken);//访问令牌 bundle.putInt("cameraNo", channelName);//通道号 intent.putExtras(bundle); intent.setComponent(componentName); startActivity(intent); } protected void startApk3() { ComponentName componentName = new ComponentName("com.example.funsdkdemo", "com.example.funsdkdemo.Xm4GSDKActivity"); Intent intent = new Intent(); // Intent intent = new Intent("chroya.foo"); Bundle bundle = new Bundle(); /* bundle.putString("serial", "811729242");//摄像机序列号 bundle.putString("VerifyCode", "CFEJRH");//摄像机验证码 bundle.putString("accessToken", "at.13zoz9dj48txpxtmbtdbxyp86yppa0kv-8377rzprmz-1ga3ixh-2csonzo9x");//访问令牌,7天过期。 */ bundle.putString("xmip", xmip); bundle.putString("xmport", xmport); bundle.putString("xmusername", xmusername); bundle.putString("xmpassword", xmpassword); bundle.putString("devSn", devSn); bundle.putString("xmmark", xmmark); //System.out.println("---aaa---"+xmip+"--"+xmport+"--"+xmusername+"--"+xmpassword+"--"+devSn+"--"+xmmark); intent.putExtras(bundle); intent.setComponent(componentName); startActivity(intent); } } 跨应用ysy1.apk的MainActivity:package com.hik.netsdk.SimpleDemo.View; import android.annotation.SuppressLint; import android.app.AlertDialog; import android.content.Intent; import android.graphics.PixelFormat; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.widget.ImageButton; import android.widget.ProgressBar; import android.widget.RelativeLayout; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; import androidx.core.view.GravityCompat; import androidx.drawerlayout.widget.DrawerLayout; // 添加 UnstableApi 注解支持 import androidx.media3.common.util.UnstableApi; import androidx.media3.common.MediaItem; import androidx.media3.common.Player; import androidx.media3.common.PlaybackException; import androidx.media3.datasource.DataSource; import androidx.media3.datasource.DefaultHttpDataSource; import androidx.media3.exoplayer.ExoPlayer; import androidx.media3.exoplayer.hls.HlsMediaSource; import androidx.media3.exoplayer.source.MediaSource; import com.hik.netsdk.SimpleDemo.R; import com.videogo.openapi.EZConstants; import com.videogo.openapi.EZOpenSDK; import org.json.JSONException; import org.json.JSONObject; import java.io.IOException; import java.util.concurrent.TimeUnit; import okhttp3.Call; import okhttp3.MediaType; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; // 在类级别添加 @UnstableApi 注解 @UnstableApi public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback { // 核心参数 private String mDeviceSerial; private String mVerifyCode; private int mCameraNo = 1; private boolean isEzDevice = false; // 萤石云相关参数 private String mAppKey = "a794d58c13154caeb7d2fbb5c3420c65"; private String mAccessToken = ""; // UI组件 private SurfaceView mPreviewSurface; private SurfaceHolder mSurfaceHolder; private Toolbar m_toolbar; private ProgressBar mProgressBar; private RelativeLayout mControlLayout; private ImageButton mRotateButton; // 播放器相关 private ExoPlayer mExoPlayer; private String mPlaybackUrl; private final OkHttpClient mHttpClient = new OkHttpClient.Builder() .connectTimeout(15, TimeUnit.SECONDS) .readTimeout(15, TimeUnit.SECONDS) .build(); // 播放器状态监听器 private final Player.Listener mPlayerListener = new Player.Listener() { @Override public void onPlaybackStateChanged(int state) { switch (state) { case Player.STATE_READY: mProgressBar.setVisibility(View.GONE); Log.d("ExoPlayer", "播放准备就绪"); break; case Player.STATE_BUFFERING: mProgressBar.setVisibility(View.VISIBLE); Log.d("ExoPlayer", "缓冲中..."); break; case Player.STATE_ENDED: Log.d("ExoPlayer", "播放结束"); break; case Player.STATE_IDLE: Log.d("ExoPlayer", "空闲状态"); break; } } @Override public void onPlayerError(PlaybackException error) { Log.e("ExoPlayer", "播放错误: " + error.getMessage()); handleError("播放错误: " + error.getMessage(), -1); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activitymain); // 初始化UI组件 initUIComponents(); // 获取启动参数 parseIntentParams(); // 初始化SDK initSDK(); // 参数校验 if (mDeviceSerial == null || mDeviceSerial.isEmpty()) { showErrorAndFinish("设备序列号不能为空"); return; } Log.d("MainActivity", "onCreate完成: isEzDevice=" + isEzDevice); } @SuppressLint("WrongViewCast") private void initUIComponents() { // 基础UI m_toolbar = findViewById(R.id.titlename); setSupportActionBar(m_toolbar); // 预览相关UI mPreviewSurface = findViewById(R.id.realplay_sv); mSurfaceHolder = mPreviewSurface.getHolder(); mSurfaceHolder.addCallback(this); mSurfaceHolder.setFormat(PixelFormat.TRANSLUCENT); mProgressBar = findViewById(R.id.liveProgressBar); mControlLayout = findViewById(R.id.rl_control); mRotateButton = findViewById(R.id.ib_rotate2); // 设置旋转按钮点击事件 mRotateButton.setOnClickListener(v -> changeScreen()); if (m_toolbar != null) { m_toolbar.setVisibility(View.GONE); } // 初始化控制按钮 initControlButtons(); Log.d("UI", "UI组件初始化完成"); } private void parseIntentParams() { // 获取Intent参数 Intent intent = getIntent(); isEzDevice = true; // 只支持萤石设备 mAccessToken = intent.getStringExtra("accessToken"); // 优先使用bundle Bundle bundle = intent.getExtras(); if (bundle != null) { mDeviceSerial = bundle.getString("devSn"); mVerifyCode = bundle.getString("verifyCode"); mCameraNo = bundle.getInt("cameraNo", 1); } // 兼容直接Extra方式 if (mDeviceSerial == null) mDeviceSerial = intent.getStringExtra("devSn"); if (mVerifyCode == null) mVerifyCode = intent.getStringExtra("verifyCode"); if (mCameraNo == 0) mCameraNo = intent.getIntExtra("cameraNo", 1); Log.d("Params", "设备序列号: " + mDeviceSerial + ", 通道号: " + mCameraNo); } private void initSDK() { try { // 使用反射检查初始化状态 boolean isInitialized = false; try { EZOpenSDK instance = EZOpenSDK.getInstance(); if (instance != null) { isInitialized = true; } } catch (Exception e) { isInitialized = false; } // 未初始化时进行初始化 if (!isInitialized) { EZOpenSDK.initLib(getApplication(), mAppKey); Log.d("EZSDK", "萤石SDK初始化完成"); } // 设置AccessToken if (mAccessToken != null && !mAccessToken.isEmpty()) { EZOpenSDK.getInstance().setAccessToken(mAccessToken); Log.d("EZToken", "AccessToken设置成功"); } else { Log.w("EZToken", "AccessToken缺失!"); } } catch (Exception e) { Log.e("EZSDK", "萤石SDK初始化失败", e); handleError("萤石SDK初始化失败: " + e.getMessage(), -1); } } private void initControlButtons() { // 云台控制按钮 findViewById(R.id.ptz_top_btn).setOnClickListener(v -> controlPTZ("UP")); findViewById(R.id.ptz_bottom_btn).setOnClickListener(v -> controlPTZ("DOWN")); findViewById(R.id.ptz_left_btn).setOnClickListener(v -> controlPTZ("LEFT")); findViewById(R.id.ptz_right_btn).setOnClickListener(v -> controlPTZ("RIGHT")); // 变焦控制 findViewById(R.id.focus_add).setOnClickListener(v -> controlZoom("ZOOM_IN")); findViewById(R.id.foucus_reduce).setOnClickListener(v -> controlZoom("ZOOM_OUT")); // 水平布局控制按钮 findViewById(R.id.ptz_top_btn2).setOnClickListener(v -> controlPTZ("UP")); findViewById(R.id.ptz_bottom_btn2).setOnClickListener(v -> controlPTZ("DOWN")); findViewById(R.id.ptz_left_btn2).setOnClickListener(v -> controlPTZ("LEFT")); findViewById(R.id.ptz_right_btn2).setOnClickListener(v -> controlPTZ("RIGHT")); Log.d("Controls", "控制按钮初始化完成"); } @Override public void surfaceCreated(SurfaceHolder holder) { Log.d("Surface", "Surface created"); // 获取播放地址并开始播放 new Thread(this::fetchPlaybackUrl).start(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { Log.d("Surface", "Surface changed: " + width + "x" + height); if (mExoPlayer != null) { mExoPlayer.setVideoSurfaceHolder(holder); } } @Override public void surfaceDestroyed(SurfaceHolder holder) { Log.d("Surface", "Surface destroyed"); stopPreview(); } // ======================== 播放地址获取与播放 ======================== private void fetchPlaybackUrl() { try { // 构建请求参数 JSONObject params = new JSONObject(); params.put("accessToken", mAccessToken); params.put("deviceSerial", mDeviceSerial); params.put("channelNo", mCameraNo); params.put("protocol", 2); // 使用HLS协议 if (mVerifyCode != null && !mVerifyCode.isEmpty()) { params.put("code", mVerifyCode); } params.put("expireTime", 7200); // 2小时有效期 // 创建请求体 RequestBody body = RequestBody.create( MediaType.parse("application/json"), params.toString() ); // 创建请求 Request request = new Request.Builder() .url("https://open.ys7.com/api/lapp/v2/live/address/get") .post(body) .build(); // 执行请求 try (Response response = mHttpClient.newCall(request).execute()) { if (!response.isSuccessful()) { handleError("获取播放地址失败: " + response.code(), response.code()); return; } // 解析响应 String responseBody = response.body().string(); JSONObject json = new JSONObject(responseBody); if ("200".equals(json.getString("code"))) { JSONObject data = json.getJSONObject("data"); mPlaybackUrl = data.getString("url"); Log.d("PlaybackURL", "获取到播放地址: " + mPlaybackUrl); // 在主线程初始化播放器 runOnUiThread(this::initExoPlayer); } else { handleError("API错误: " + json.getString("msg"), json.getInt("code")); } } } catch (JSONException | IOException e) { Log.e("FetchURL", "获取播放地址异常", e); handleError("获取播放地址异常: " + e.getMessage(), -1); } } private void initExoPlayer() { // 释放现有播放器 if (mExoPlayer != null) { mExoPlayer.release(); } // 创建播放器 mExoPlayer = new ExoPlayer.Builder(this).build(); mExoPlayer.addListener(mPlayerListener); // 设置视频渲染器 mExoPlayer.setVideoSurfaceHolder(mSurfaceHolder); // 创建媒体源 DataSource.Factory dataSourceFactory = new DefaultHttpDataSource.Factory(); MediaSource mediaSource = new HlsMediaSource.Factory(dataSourceFactory) .createMediaSource(MediaItem.fromUri(Uri.parse(mPlaybackUrl))); // 准备播放 mExoPlayer.setMediaSource(mediaSource); mExoPlayer.prepare(); mExoPlayer.setPlayWhenReady(true); mProgressBar.setVisibility(View.VISIBLE); Log.d("ExoPlayer", "播放器初始化完成,开始播放"); } // ======================== 萤石云控制方法 ======================== private int mapDirection(String direction) { switch (direction) { default: return -1; } } private void controlPTZ(String direction) { int directionCode = mapDirection(direction); if (directionCode == -1) return; // 控制逻辑实现 } private void controlZoom(String command) { String direction = "ZOOM_IN".equals(command) ? "ZOOM_IN" : "ZOOM_OUT"; controlPTZ(direction); } // ======================== 通用功能方法 ======================== public void changeScreen(View view) { changeScreen(); } private void changeScreen() { if (mControlLayout.getVisibility() == View.VISIBLE) { mControlLayout.setVisibility(View.GONE); } else { mControlLayout.setVisibility(View.VISIBLE); } } private void handleError(String message, int errorCode) { String fullMessage = message + " (错误: " + errorCode + ")"; // 萤石云特有错误码处理 switch (errorCode) { case 400001: fullMessage = "AccessToken无效"; break; case 400002: fullMessage = "设备不存在"; break; case 400007: fullMessage = "设备不在线"; break; case 400034: fullMessage = "验证码错误"; break; case 400035: fullMessage = "设备已被自己添加"; break; case 400036: fullMessage = "设备已被别人添加"; break; default: fullMessage = "萤石云错误: " + errorCode; } new AlertDialog.Builder(this) .setTitle("预览失败") .setMessage(fullMessage) .setPositiveButton("确定", (d, w) -> finish()) .setCancelable(false) .show(); } private void showErrorAndFinish(String message) { Toast.makeText(this, message, Toast.LENGTH_LONG).show(); new Handler().postDelayed(this::finish, 3000); } private void stopPreview() { if (mExoPlayer != null) { mExoPlayer.release(); mExoPlayer = null; Log.d("Preview", "预览已停止"); } } @Override protected void onDestroy() { super.onDestroy(); stopPreview(); Log.d("Lifecycle", "onDestroy"); } @Override protected void onPause() { super.onPause(); if (mExoPlayer != null) { mExoPlayer.setPlayWhenReady(false); Log.d("Lifecycle", "暂停播放"); } } @Override protected void onResume() { super.onResume(); if (mExoPlayer != null) { mExoPlayer.setPlayWhenReady(true); Log.d("Lifecycle", "恢复播放"); } } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_main_opt, menu); return true; } }
06-24
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值