电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

Android集成zxing掃碼框架功能

瀏覽:111日期:2022-09-24 15:52:53

我們知道zxing是一個強大的處理二維碼和條形碼等的開源庫,本篇文章記錄一下自己在項目中集成zxing開源庫的過程。

導入依賴

implementation ’com.google.zxing:core:3.3.3’

申請權限

在AndroidManifest中申請相應權限:

<!--相機--><uses-permission android:name='android.permission.CAMERA' /><!--震動--><uses-permission android:name='android.permission.VIBRATE' /><!--存儲--><uses-permission android:name='android.permission.WRITE_EXTERNAL_STORAGE' /><uses-permission android:name='android.permission.READ_EXTERNAL_STORAGE' />

導入相關代碼和資源文件

導入的代碼文件如下(源碼在末尾):

Android集成zxing掃碼框架功能

相關的資源文件:

1、在res/values下新建ids.xml文件,引入下面id:

<!--二維碼/條形碼掃描相關--><item name='auto_focus' type='id' /><item name='decode' type='id' /><item name='decode_failed' type='id' /><item name='decode_succeeded' type='id' /><item name='encode_failed' type='id' /><item name='encode_succeeded' type='id' /><item name='launch_product_query' type='id' /><item name='quit' type='id' /><item name='restart_preview' type='id' /><item name='return_scan_result' type='id' /><item name='search_book_contents_failed' type='id' /><item name='search_book_contents_succeeded' type='id' />

2、在res/values下新建attrs.xml文件,加入掃碼框的屬性,主要是ViewfinderView在使用:

<!--掃碼框屬性--><declare-styleable name='ViewfinderView'> <attr name='corner_color' format='color' /> <attr name='corner_size' format='dimension' /> <attr name='corner_stroke_width' format='dimension' /> <attr name='corner_position' format='enum'> <enum name='inside' value='1' /> <enum name='outside' value='2' /> </attr> <attr name='line_color' format='color' /> <attr name='line_height' format='dimension' /> <attr name='line_move_distance' format='dimension' /> <attr name='frame_width' format='dimension' /> <attr name='frame_height' format='dimension' /> <attr name='frame_centerX' format='dimension' /> <attr name='frame_centerY' format='dimension' /> <attr name='frame_color' format='color' /> <attr name='frame_stroke_width' format='dimension' /> <attr name='mask_color' format='color' /> <attr name='result_point_color' format='color' /> <attr name='label_text' format='string' /> <attr name='label_text_color' format='color' /> <attr name='label_text_size' format='dimension' /> <attr name='label_text_margin' format='dimension' /></declare-styleable>

3、在res下新建raw目錄,導入beep.mp3,實現掃碼成功的滴滴音效,BeepManager在使用

上面是一些比較重要的資源。

然后介紹一下幾個主要的類:

1、ViewfinderView:自定義掃描框,代碼如下,因為有注釋,就不多說明了。

public final class ViewfinderView extends View { private static final long ANIMATION_DELAY = 10L; private static final int OPAQUE = 1; private static final int CORNER_INSIDE = 1; //四個邊角在掃描區內 private static final int CORNER_OUTSIDE = 2; //四個邊角在掃描區外 private Paint paint; //掃描區四個邊角的顏色 private int cornerColor; //掃描區邊角的大小 private float cornerSize; //掃描區邊角的寬度 private float cornerStrokeWidth; //邊角的方向,在掃描區域內還是掃描區域外 private int cornerPosition; //掃描線顏色 private int lineColor; //掃描線高度 private float lineHeight; //掃描線移動距離 private float lineMoveDistance; //掃描區域寬度度 private float frameWidth; //掃描區域高度 private float frameHeight; //掃描區域中心位置的X坐標,默認正中間,在onLayout中設置 private float frameCenterX; //掃描區域中心位置的Y坐標,默認正中間,在onLayout中設置 private float frameCenterY; //掃描區域邊框顏色 private int frameColor; //掃描區域邊框寬度 private float frameStrokeWidth; //模糊區域顏色 private int maskColor; //掃描點的顏色 private int resultPointColor; //掃描區域提示文本 private String labelText; //掃描區域提示文本顏色 private int labelTextColor; //掃描區域提示文本字體大小 private float labelTextSize; //掃描區域提示文本的邊距 private float labelTextMargin; public static int scannerStart = 0; public static int scannerEnd = 0; private Collection<ResultPoint> possibleResultPoints; private Collection<ResultPoint> lastPossibleResultPoints; // This constructor is used when the class is built from an XML resource. public ViewfinderView(Context context, AttributeSet attrs) { super(context, attrs); //初始化自定義屬性信息 TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ViewfinderView); cornerColor = ta.getColor(R.styleable.ViewfinderView_corner_color, getResources().getColor(R.color.colorPrimary)); cornerSize = ta.getDimension(R.styleable.ViewfinderView_corner_size, dp2px(context, 28)); cornerStrokeWidth = ta.getDimension(R.styleable.ViewfinderView_corner_stroke_width, dp2px(context, 4)); cornerPosition = ta.getInt(R.styleable.ViewfinderView_corner_position, CORNER_INSIDE); lineColor = ta.getColor(R.styleable.ViewfinderView_line_color, getResources().getColor(R.color.colorPrimary)); lineHeight = ta.getDimension(R.styleable.ViewfinderView_line_height, dp2px(context, 3)); lineMoveDistance = ta.getDimension(R.styleable.ViewfinderView_line_move_distance, dp2px(context, 2)); frameWidth = ta.getDimension(R.styleable.ViewfinderView_frame_width, dp2px(context, 220)); frameHeight = ta.getDimension(R.styleable.ViewfinderView_frame_height, dp2px(context, 220)); frameCenterX = ta.getDimension(R.styleable.ViewfinderView_frame_centerX, -1); frameCenterY = ta.getDimension(R.styleable.ViewfinderView_frame_centerY, -1); frameColor = ta.getColor(R.styleable.ViewfinderView_frame_color, Color.parseColor('#90FFFFFF')); frameStrokeWidth = ta.getDimension(R.styleable.ViewfinderView_frame_stroke_width, dp2px(context, 0.2f)); maskColor = ta.getColor(R.styleable.ViewfinderView_mask_color, Color.parseColor('#60000000')); resultPointColor = ta.getColor(R.styleable.ViewfinderView_result_point_color, Color.TRANSPARENT); labelText = ta.getString(R.styleable.ViewfinderView_label_text); labelTextColor = ta.getColor(R.styleable.ViewfinderView_label_text_color, Color.WHITE); labelTextSize = ta.getDimension(R.styleable.ViewfinderView_label_text_size, sp2px(context, 15)); labelTextMargin = ta.getDimension(R.styleable.ViewfinderView_label_text_margin, dp2px(context, 18)); ta.recycle(); paint = new Paint(); paint.setAntiAlias(true); possibleResultPoints = new HashSet<ResultPoint>(5); } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); //如果沒有設置frameCenterX和frameCenterY默認布局正中間的X、Y坐標 frameCenterX = (frameCenterX == -1) ? getWidth() / 2f : frameCenterX; frameCenterY = (frameCenterY == -1) ? getHeight() / 2f : frameCenterY; //設置掃描區域位置 int leftOffset = (int) (frameCenterX - frameWidth / 2f); int topOffset = (int) (frameCenterY - frameHeight / 2f); //設置掃描區不超過屏幕 leftOffset = leftOffset > 0 ? leftOffset : 0; topOffset = topOffset > 0 ? topOffset : 0; Rect rect = new Rect(); rect.left = leftOffset; rect.top = topOffset; rect.right = (int) (leftOffset + frameWidth); rect.bottom = (int) (topOffset + frameHeight); CameraManager.get().setFramingRect(rect); } @Override public void onDraw(Canvas canvas) { Rect frame = CameraManager.get().getFramingRect(); if (frame == null) { return; } if (scannerStart == 0 || scannerEnd == 0) { scannerStart = frame.top; scannerEnd = frame.bottom; } int width = canvas.getWidth(); int height = canvas.getHeight(); //繪制模糊區域 drawExterior(canvas, frame, width, height); //繪制掃描區邊框 drawFrame(canvas, frame); //繪制邊角 drawCorner(canvas, frame); //繪制提示信息 drawTextInfo(canvas, frame); //繪制掃描線 drawScanLine(canvas, frame); //繪制閃爍點 drawResultPoint(canvas, frame); // Request another update at the animation interval, but only repaint the laser line, // not the entire viewfinder mask. //指定重繪區域,該方法會在子線程中執行 postInvalidateDelayed(ANIMATION_DELAY, frame.left, frame.top, frame.right, frame.bottom); } // 繪制模糊區域 Draw the exterior (i.e. outside the framing rect) darkened private void drawExterior(Canvas canvas, Rect frame, int width, int height) { paint.setColor(maskColor); canvas.drawRect(0, 0, width, frame.top, paint); canvas.drawRect(0, frame.top, frame.left, frame.bottom, paint); canvas.drawRect(frame.right, frame.top, width, frame.bottom, paint); canvas.drawRect(0, frame.bottom, width, height, paint); } // 繪制掃描區邊框 Draw a two pixel solid black border inside the framing rect private void drawFrame(Canvas canvas, Rect frame) { if (frameStrokeWidth > 0) { paint.setColor(frameColor); if (cornerPosition == CORNER_INSIDE) { //邊角在掃描區內 //左邊 canvas.drawRect(frame.left, frame.top, frame.left + frameStrokeWidth, frame.bottom, paint); //上邊 canvas.drawRect(frame.left, frame.top, frame.right, frame.top + frameStrokeWidth, paint); //右邊 canvas.drawRect(frame.right - frameStrokeWidth, frame.top, frame.right, frame.bottom, paint); //下邊 canvas.drawRect(frame.left, frame.bottom - frameStrokeWidth, frame.right, frame.bottom, paint); } else { //邊角在掃描區外 //左邊 canvas.drawRect(frame.left - frameStrokeWidth, frame.top - frameStrokeWidth, frame.left, frame.bottom + frameStrokeWidth, paint); //上邊 canvas.drawRect(frame.left - frameStrokeWidth, frame.top - frameStrokeWidth, frame.right + frameStrokeWidth, frame.top, paint); //右邊 canvas.drawRect(frame.right, frame.top - frameStrokeWidth, frame.right + frameStrokeWidth, frame.bottom + frameStrokeWidth, paint); //下邊 canvas.drawRect(frame.left - frameStrokeWidth, frame.bottom, frame.right + frameStrokeWidth, frame.bottom + frameStrokeWidth, paint); } } } //繪制邊角 private void drawCorner(Canvas canvas, Rect frame) { if (cornerSize > 0 && cornerStrokeWidth > 0) { paint.setColor(cornerColor); if (cornerPosition == CORNER_INSIDE) { //繪制在掃描區域內區 //左上 canvas.drawRect(frame.left, frame.top, frame.left + cornerSize, frame.top + cornerStrokeWidth, paint); canvas.drawRect(frame.left, frame.top, frame.left + cornerStrokeWidth, frame.top + cornerSize, paint); //右上 canvas.drawRect(frame.right - cornerSize, frame.top, frame.right, frame.top + cornerStrokeWidth, paint); canvas.drawRect(frame.right - cornerStrokeWidth, frame.top, frame.right, frame.top + cornerSize, paint); //左下 canvas.drawRect(frame.left, frame.bottom - cornerSize, frame.left + cornerStrokeWidth, frame.bottom, paint); canvas.drawRect(frame.left, frame.bottom - cornerStrokeWidth, frame.left + cornerSize, frame.bottom, paint); //右下 canvas.drawRect(frame.right - cornerSize, frame.bottom - cornerStrokeWidth, frame.right, frame.bottom, paint); canvas.drawRect(frame.right - cornerStrokeWidth, frame.bottom - cornerSize, frame.right, frame.bottom, paint); } else { //繪制在掃描區域外區 //左上 canvas.drawRect(frame.left - cornerStrokeWidth, frame.top - cornerStrokeWidth, frame.left - cornerStrokeWidth + cornerSize, frame.top, paint); canvas.drawRect(frame.left - cornerStrokeWidth, frame.top - cornerStrokeWidth, frame.left, frame.top - cornerStrokeWidth + cornerSize, paint); //右上 canvas.drawRect(frame.right + cornerStrokeWidth - cornerSize, frame.top - cornerStrokeWidth, frame.right + cornerStrokeWidth, frame.top, paint); canvas.drawRect(frame.right, frame.top - cornerStrokeWidth, frame.right + cornerStrokeWidth, frame.top - cornerStrokeWidth + cornerSize, paint); //左下 canvas.drawRect(frame.left - cornerStrokeWidth, frame.bottom, frame.left - cornerStrokeWidth + cornerSize, frame.bottom + cornerStrokeWidth, paint); canvas.drawRect(frame.left - cornerStrokeWidth, frame.bottom + cornerStrokeWidth - cornerSize, frame.left, frame.bottom + cornerStrokeWidth, paint); //右下 canvas.drawRect(frame.right + cornerStrokeWidth - cornerSize, frame.bottom, frame.right + cornerStrokeWidth, frame.bottom + cornerStrokeWidth, paint); canvas.drawRect(frame.right, frame.bottom + cornerStrokeWidth - cornerSize, frame.right + cornerStrokeWidth, frame.bottom + cornerStrokeWidth, paint); } } } //繪制文本 private void drawTextInfo(Canvas canvas, Rect frame) { if (!TextUtils.isEmpty(labelText)) { paint.setColor(labelTextColor); paint.setTextSize(labelTextSize); paint.setTextAlign(Paint.Align.CENTER); Paint.FontMetrics fm = paint.getFontMetrics(); float baseY = frame.bottom + labelTextMargin - fm.ascent; canvas.drawText(labelText, frame.left + frame.width() / 2, baseY, paint); } } //繪制掃描線 private void drawScanLine(Canvas canvas, Rect frame) { if (lineHeight > 0) { paint.setColor(lineColor); RadialGradient radialGradient = new RadialGradient( (float) (frame.left + frame.width() / 2), (float) (scannerStart + lineHeight / 2), 360f, lineColor, shadeColor(lineColor), Shader.TileMode.MIRROR); paint.setShader(radialGradient); if (scannerStart <= scannerEnd) { //橢圓 RectF rectF = new RectF(frame.left + 2 * lineHeight, scannerStart, frame.right - 2 * lineHeight, scannerStart + lineHeight); canvas.drawOval(rectF, paint); scannerStart += lineMoveDistance; } else { scannerStart = frame.top; } paint.setShader(null); } } private void drawResultPoint(Canvas canvas, Rect frame) { if (resultPointColor != Color.TRANSPARENT) { Collection<ResultPoint> currentPossible = possibleResultPoints; Collection<ResultPoint> currentLast = lastPossibleResultPoints; if (currentPossible.isEmpty()) { lastPossibleResultPoints = null; } else { possibleResultPoints = new HashSet<ResultPoint>(5); lastPossibleResultPoints = currentPossible; paint.setAlpha(OPAQUE); paint.setColor(resultPointColor); for (ResultPoint point : currentPossible) { canvas.drawCircle(frame.left + point.getX(), frame.top + point.getY(), 6.0f, paint); } } if (currentLast != null) { paint.setAlpha(OPAQUE / 2); paint.setColor(resultPointColor); for (ResultPoint point : currentLast) { canvas.drawCircle(frame.left + point.getX(), frame.top + point.getY(), 3.0f, paint); } } } } //處理顏色模糊 public int shadeColor(int color) { String hax = Integer.toHexString(color); String result = '20' + hax.substring(2); return Integer.valueOf(result, 16); } public void drawViewfinder() { invalidate(); } public void addPossibleResultPoint(ResultPoint point) { possibleResultPoints.add(point); } private int dp2px(Context context, float dpValue) { float density = context.getApplicationContext().getResources().getDisplayMetrics().density; return (int) (dpValue * density + 0.5f); } private int sp2px(Context context, float spValue) { float scaleDensity = context.getApplicationContext().getResources().getDisplayMetrics().scaledDensity; return (int) (spValue * scaleDensity + 0.5f); }}

2、CaptureActivity:掃碼的Activity基類,代碼如下;

/** * Created by xuzhb on 2019/11/16 * Desc:掃碼的Activity類 * 整個Activity最重要的兩個控件是一個SurfaceView(攝像頭)和一個ViewfinderView(掃描區) * 對于繼承CaptureActivity的Activity子類來說, * 可以選擇在自己的布局中定義和CaptureActivity的布局文件id相同的控件, * 這樣即使它們在兩個布局中表現不同也能執行相同的邏輯,包括其他控件 * 或者選擇重寫getSurfaceView()和getViewfinderView()返回對應的兩個控件, * 掃碼最終是在handleDecode(Result result, Bitmap bitmap)處理掃描后的結果 */public class CaptureActivity extends AppCompatActivity implements SurfaceHolder.Callback { private static final String TAG = 'CaptureActivity'; private static final int IMAGE_PICKER = 1999; private BeepManager mBeepManager; private CaptureActivityHandler mHandler; private Vector<BarcodeFormat> mDecodeFormats; private String mCharacterSet; private InactivityTimer mInactivityTimer; private boolean hasSurface = false; private boolean isLightOn = false; //是否打開閃光燈 private boolean isPlayBeep = true; //是否開啟掃描后的滴滴聲 private boolean isVibrate = true; //是否震動 private String mPhotoPath; //選中的圖片路徑 private TitleBar mTitleBar; private SurfaceView mSurfaceView; private ViewfinderView mViewfinderView; private LinearLayout mLightLl; private ImageView mLightIv; private TextView mLightTv; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(getLayoutId()); CameraManager.init(getApplicationContext()); mBeepManager = new BeepManager(this); hasSurface = false; mInactivityTimer = new InactivityTimer(this); handleView(savedInstanceState); initView(); initListener(); } protected int getLayoutId() { return R.layout.activity_capture; } protected void handleView(@Nullable Bundle savedInstanceState) { } private void initView() { mTitleBar = findViewById(R.id.title_bar); mSurfaceView = findViewById(R.id.surfaceView); mViewfinderView = findViewById(R.id.viewfinderView); mLightLl = findViewById(R.id.light_ll); mLightIv = findViewById(R.id.light_iv); mLightTv = findViewById(R.id.light_tv); } protected void initListener() { //因為繼承CaptureActivity的Activity子類的布局不一定包含id為title_bar和light_ll的控件, //沒有的話如果子類通過super.initListener()覆寫時會因為找不到而報異常,所以這里加了一個判空; //如果子類的布局中包含id相同的控件,則不需要在子類中再重寫相同的邏輯 if (mTitleBar != null) { StatusBarUtil.INSTANCE.darkModeAndPadding(this, mTitleBar, Color.BLACK, 0, false); mTitleBar.setOnLeftClickListener(v -> { finish(); return null; }); mTitleBar.setOnRightClickListener(v -> { openAlbum(); //打開相冊選取圖片掃描 return null; }); } if (mLightLl != null) { mLightLl.setOnClickListener(v -> switchLight()); //打開或關閉閃光燈 } } //打開相冊 protected void openAlbum() { Intent intent = new Intent(Intent.ACTION_PICK, null); intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 'image/*'); startActivityForResult(intent, IMAGE_PICKER); } //開啟/關閉閃光燈 private void switchLight() { if (CameraManager.get() != null) { if (isLightOn) { mLightTv.setText('輕觸點亮'); CameraManager.get().turnLightOffFlashLight(); } else { mLightTv.setText('輕觸關閉'); CameraManager.get().turnOnFlashLight(); } isLightOn = !isLightOn; mLightIv.setSelected(isLightOn); } } @Override protected void onResume() { super.onResume(); SurfaceHolder holder = getSurfaceView().getHolder(); if (hasSurface) { initCamera(holder); } else { holder.addCallback(this); holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } mDecodeFormats = null; mCharacterSet = null; } @Override protected void onPause() { super.onPause(); if (mHandler != null) { mHandler.quitSynchronously(); mHandler = null; } CameraManager.get().closeDriver(); } @Override protected void onDestroy() { mInactivityTimer.shutdown(); mBeepManager.releaseRing(); super.onDestroy(); } @Override public void surfaceCreated(SurfaceHolder holder) { } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { if (!hasSurface) { hasSurface = true; initCamera(holder); } } @Override public void surfaceDestroyed(SurfaceHolder holder) { hasSurface = false; } private void initCamera(SurfaceHolder holder) { try { CameraManager.get().openDriver(holder); } catch (Exception e) { e.printStackTrace(); } if (mHandler == null) { mHandler = new CaptureActivityHandler(this, mDecodeFormats, mCharacterSet); } } //繼承CaptureActivity的Activity類,如果SurfaceView的id和CaptureActivity布局中SurfaceView的id不同 //需要重寫這個方法,返回自己布局中的SurfaceView public SurfaceView getSurfaceView() { return mSurfaceView; } //繼承CaptureActivity的Activity類,如果ViewfinderView的id和CaptureActivity布局中ViewfinderView的id不同 //需要重寫這個方法,返回自己布局中的ViewfinderView public ViewfinderView getViewfinderView() { return mViewfinderView; } public Handler getHandler() { return mHandler; } public void drawViewfinder() { getViewfinderView().drawViewfinder(); } //處理掃描后的結果 public void handleDecode(Result result, Bitmap bitmap) { mInactivityTimer.onActivity(); if (result != null) { String text = result.getText(); Log.i(TAG, '識別的結果:' + text); if (!TextUtils.isEmpty(text)) { //識別成功 playBeepSoundAndVibrate(); returnQRCodeResult(text); } else { showToast('很抱歉,識別二維碼失敗!'); } } else { showToast('未發現二維碼!'); } } private void playBeepSoundAndVibrate() { if (isPlayBeep) { mBeepManager.startRing(); //播放掃碼的滴滴聲 } if (isVibrate) { Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); if (vibrator != null) { vibrator.vibrate(200); //震動200毫秒 } } } //返回掃描結果 private void returnQRCodeResult(String result) { Intent intent = new Intent(); intent.putExtra(QRConstant.SCAN_QRCODE_RESULT, result); setResult(Activity.RESULT_OK, intent); finish(); } private void showToast(CharSequence text) { runOnUiThread(() -> { ToastUtil.INSTANCE.showToast(text, true, false, getApplicationContext()); }); } @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == IMAGE_PICKER && resultCode == Activity.RESULT_OK) { if (data != null) { Uri uri = data.getData(); if (uri != null) { Cursor cursor = getContentResolver().query(uri, null, null, null, null); if (cursor != null) { if (cursor.moveToFirst()) { mPhotoPath = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA)); } cursor.close(); if (!TextUtils.isEmpty(mPhotoPath)) { //可以加個提示正在掃描的加載框,如showLoadingDialog('正在掃描...') new Thread(() -> {handleDecode(QRCodeUtil.decodeImage(mPhotoPath), null);//取消加載框,dismissLoadingDialog() }).start(); } else { Log.e(TAG, '未找到圖片'); } } } } } }}

看一下使用的例子

Android集成zxing掃碼框架功能 Android集成zxing掃碼框架功能

最后,附上整個項目的github地址,注:項目使用了視圖綁定ViewBinding,所以需要使用AndroidStudio 3.6.x版本。

到此這篇關于Android集成zxing掃碼框架功能的文章就介紹到這了,更多相關android zxing掃碼內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Android
相關文章:
主站蜘蛛池模板: 单级/双级旋片式真空泵厂家,2xz旋片真空泵-浙江台州求精真空泵有限公司 | 正压密封性测试仪-静态发色仪-导丝头柔软性测试仪-济南恒品机电技术有限公司 | 专业生产动态配料系统_饲料配料系统_化肥配料系统等配料系统-郑州鑫晟重工机械有限公司 | 粉丝机械,粉丝烘干机,粉丝生产线-招远市远东粉丝机械有限公司 | 首页 - 张店继勇软件开发工作室| 施工电梯_齿条货梯_烟囱电梯_物料提升机-河南大诚机械制造有限公司 | 湖州织里童装_女童男童中大童装_款式多尺码全_织里儿童网【官网】-嘉兴嘉乐网络科技有限公司 | 电机修理_二手电机专家-河北豫通机电设备有限公司(原石家庄冀华高压电机维修中心) | 飞象网 - 通信人每天必上的网站 全球化工设备网—化工设备,化工机械,制药设备,环保设备的专业网络市场。 | 英国雷迪地下管线探测仪-雷迪RD8100管线仪-多功能数字听漏仪-北京迪瑞进创科技有限公司 | 螺旋丝杆升降机-SWL蜗轮-滚珠丝杆升降机厂家-山东明泰传动机械有限公司 | 环球周刊网| 扬尘监测_扬尘监测系统_带证扬尘监测设备 - 郑州港迪科技有限公司 | 西安文都考研官网_西安考研辅导班_考研培训机构_西安在职考研培训 | 手术室净化厂家-成都做医院净化工程的公司-四川华锐-15年特殊科室建设经验 | 根系分析仪,大米外观品质检测仪,考种仪,藻类鉴定计数仪,叶面积仪,菌落计数仪,抑菌圈测量仪,抗生素效价测定仪,植物表型仪,冠层分析仪-杭州万深检测仪器网 | 制样机-密封锤式破碎机-粉碎机-智能马弗炉-南昌科鑫制样 | 不锈钢管件(不锈钢弯头,不锈钢三通,不锈钢大小头),不锈钢法兰「厂家」-浙江志通管阀 | 塑钢件_塑钢门窗配件_塑钢配件厂家-文安县启泰金属制品有限公司 深圳南财多媒体有限公司介绍 | 电液推杆生产厂家|电动推杆|液压推杆-扬州唯升机械有限公司 | 冰晶石|碱性嫩黄闪蒸干燥机-有机垃圾烘干设备-草酸钙盘式干燥机-常州市宝康干燥 | 上海璟文空运首页_一级航空货运代理公司_机场快递当日达 | 真石漆,山东真石漆,真石漆厂家,真石漆价格-山东新佳涂料有限公司 | 气动绞车,山东气动绞车,气动绞车厂家-烟台博海石油机械有限公司 气动隔膜泵厂家-温州永嘉定远泵阀有限公司 | 橡胶膜片,夹布膜片,橡胶隔膜密封,泵阀设备密封膜片-衡水汉丰橡塑科技公司网站 | 招商帮-一站式网络营销服务|搜索营销推广|信息流推广|短视视频营销推广|互联网整合营销|网络推广代运营|招商帮企业招商好帮手 | 西门子伺服控制器维修-伺服驱动放大器-828D数控机床维修-上海涌迪 | 济南菜鸟驿站广告|青岛快递车车体|社区媒体-抖音|墙体广告-山东揽胜广告传媒有限公司 | 周口市风机厂,周鼓风机,河南省周口市风机厂 | 贝朗斯动力商城(BRCPOWER.COM) - 买叉车蓄电池上贝朗斯商城,价格更超值,品质有保障! | 上海质量认证办理中心| 深圳激光打标机_激光打标机_激光焊接机_激光切割机_同体激光打标机-深圳市创想激光科技有限公司 深圳快餐店设计-餐饮设计公司-餐饮空间品牌全案设计-深圳市勤蜂装饰工程 | 断桥铝破碎机_铝合金破碎机_废铁金属破碎机-河南鑫世昌机械制造有限公司 | 派克防爆伺服电机品牌|国产防爆伺服电机|高低温伺服电机|杭州摩森机电科技有限公司 | 工装定制/做厂家/公司_工装订做/制价格/费用-北京圣达信工装 | 蜗轮丝杆升降机-螺旋升降机-丝杠升降机厂家-润驰传动 | 时代北利离心机,实验室离心机,医用离心机,低速离心机DT5-2,美国SKC采样泵-上海京工实业有限公司 工业电炉,台车式电炉_厂家-淄博申华工业电炉有限公司 | 右手官网|右手工业设计|外观设计公司|工业设计公司|产品创新设计|医疗产品结构设计|EMC产品结构设计 | 对辊破碎机-液压双辊式,强力双齿辊,四辊破碎机价格_巩义市金联机械设备生产厂家 | 培训中心-翰香原香酥板栗饼加盟店总部-正宗板栗酥饼技术 | 合肥制氮机_合肥空压机厂家_安徽真空泵-凯圣精机 |