溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

[Unity+Android]橫版掃描二維碼

發(fā)布時(shí)間:2020-07-13 02:45:17 來源:網(wǎng)絡(luò) 閱讀:1676 作者:蓬萊仙羽 欄目:移動(dòng)開發(fā)

終于解決了一個(gè)憂傷好久的問題,嚴(yán)重拖了項(xiàng)目進(jìn)度,深感慚愧!一直被一系列的問題所困擾,然后又只能自己一個(gè)人摸索,也是一段辛酸憂傷史,現(xiàn)在小結(jié)一下上個(gè)月在做二維碼的過程中所碰到的問題以及解決辦法,現(xiàn)在慶幸終于解決好了,終于能將這個(gè)功能告一段落,一下小結(jié)也是分享一下Unity的某些“坑”,讓同行少走彎路,起碼在二維碼這方面應(yīng)該會有所啟迪,欣慰的是接下來幾天終于可以做自己應(yīng)該做的事情了!

效果圖:

 [Unity+Android]橫版掃描二維碼

 [Unity+Android]橫版掃描二維碼

先小結(jié)一下碰到的問題:

1.Unity工程屏幕方向與Android工程屏幕方向要一致的問題

本來我測試Android掃碼的功能,已經(jīng)測是通過了,可以參考之前寫的博文:http://blog.csdn.net/dingxiaowei2013/article/details/24677795,后來將這這個(gè)插件添加到現(xiàn)有的項(xiàng)目中,但導(dǎo)出項(xiàng)目apk后,打開應(yīng)用怎么就是閃退,表示很憂傷,后來一步一步的精簡對比測試,表示自己五一那天一直摸索到凌晨三點(diǎn)才發(fā)現(xiàn)這一問題根源,有了這個(gè)基礎(chǔ)才有接下來思路的轉(zhuǎn)變。我的Android工程設(shè)置的屏幕旋轉(zhuǎn)方向是portrait,但由于項(xiàng)目原因,Unity的導(dǎo)出方向必須是landscapeleft,這兩者方向不一致會導(dǎo)致應(yīng)用異常奔潰閃退!當(dāng)然我的解決思路可能是比較笨的,我將Android工程做成的插件的屏幕方向也做成了橫屏的,為了和Unity的方向一致,我想應(yīng)該就不會出現(xiàn)那種問題。我原本的思路是將Unity導(dǎo)出屏幕設(shè)置成auto,然后代碼控制屏幕的方向,但貌似還是不成功,沒轍只能還是換種思路!網(wǎng)上有不少Android的掃碼工程,最多的就是基于zxing,但是都是有很多冗余,不適合初學(xué)者,尤其是像我這種Android初學(xué)者,我倒是看到一個(gè)比較適合入門的精簡的掃碼工程,可惜是縱屏的,上一篇文章就是介紹的這個(gè),但并不適合我的項(xiàng)目需求,所以我就想辦法將這個(gè)工程改成橫屏工程,本以為只要改改xml配置文件就OK的,結(jié)果并不是想象的那么簡單,僅僅那么該會出現(xiàn)掃的過程中圖片壓縮以及移動(dòng)別扭等現(xiàn)象,還是需要修改里面的工程的!這里可以參考:http://dingxiaowei2013.blog.163.com/blog/static/21965310720144595534507/,這篇是將橫屏改縱屏的解決方案,然后將其逆序操作,但我還是出現(xiàn)了一些問題,比如掃到一半的時(shí)候應(yīng)用異常崩潰,又表示很憂傷,為啥都不是一帆風(fēng)順呢!然后反復(fù)重做,終于成功了!精簡版的工程源碼我會貼出來共享!為了實(shí)現(xiàn)這個(gè)功能,可謂是一次有一次的導(dǎo)出,一次有一次的測試,千言萬語無法言表其中的憂傷,總而言之,堅(jiān)韌,是程序猿必須具備的品質(zhì)!

2.Unity與Android場景跳轉(zhuǎn)的問題

Unity和Android交互不僅僅是調(diào)用函數(shù),交互數(shù)據(jù),很大的一個(gè)還是需要交互視圖和場景,將其很好的進(jìn)行切換。當(dāng)然場景的跳轉(zhuǎn)或者是切換還是通過調(diào)用接口函數(shù)來實(shí)現(xiàn),但這里通過了一個(gè)很重要的Activity來實(shí)現(xiàn)了這一效果,就是UnityPlayerActivity,Android的接口視圖就是繼承了這個(gè)UnityPlayerActivity,這個(gè)是為Unity和Android搭建了一個(gè)橋梁,當(dāng)然這個(gè)類必須導(dǎo)入U(xiǎn)nity的接口包,在Unity的安裝目錄下,詳細(xì)可以參考上一篇文章,繼承了UnityPlayerActivity的視圖是作為Unity和Android的一個(gè)通用視圖,它是Android插件的一個(gè)入口,無論是在Unity切換到Android界面還是Android切換到Unity界面,必須都要通過這個(gè)Activity來操作,記得是必須,這里我也是吃過苦頭,我想在其他的Activity中來調(diào)用Unity的接口函數(shù)來實(shí)現(xiàn)Unity界面的跳轉(zhuǎn),但都嘗試失??!后來再重頭再來,這些都是經(jīng)過了一遍又一遍的實(shí)驗(yàn)才得出的結(jié)論!

3.LG的手機(jī)作為Unity的測試機(jī)貌似有一些問題(純屬個(gè)人感覺)

我測試最簡單的OnGUI的方法,GUI里面包含中文,LG的顯示不出來,由于公司所有的Android機(jī)和個(gè)人手機(jī)基本都是LG的,測試下來中文不顯示,估計(jì)還得做字體,難道是因?yàn)樗琼n國貨?!純屬我個(gè)人瞎猜,解決辦法就是你可以在工程里面做一套字體,然后做GUISkin供GUI用,我用其他的手機(jī),比如我的破舊的中興還有其他的非LG手機(jī)就能顯示,這個(gè)橫版的二維碼掃碼插件工程用LG測試還是有點(diǎn)問題,會出現(xiàn)掃的時(shí)候卡屏的現(xiàn)像,不知道是不是因?yàn)閮?nèi)存飆升,這個(gè)可以用Eclipse測試一下看看是不是因?yàn)檫@個(gè)原因!

附帶修改的Android精簡版的掃碼工程代碼(只貼修改過的腳本):

AndroidManifest.xml

[java]view plaincopyprint?
  1. <?xml version="1.0" encoding="utf-8"?>  

  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"

  3. package="com.example.qr_codescan"

  4.    android:versionCode="1"

  5.    android:versionName="1.0" >  

  6.    <uses-sdk  

  7.        android:minSdkVersion="8"

  8.        android:targetSdkVersion="16" />  

  9.    <application  

  10.        android:allowBackup="true"

  11.        android:icon="@drawable/ic_launcher"

  12.        android:label="@string/app_name"

  13.        android:theme="@android:style/Theme.NoTitleBar" >  

  14.           <activity  

  15.            android:name="com.example.qr_codescan.MainActivity"

  16.            android:screenOrientation="landscape"

  17.            android:label="@string/app_name" >  

  18.            <intent-filter>  

  19.                <action android:name="android.intent.action.MAIN" />  

  20.                <category android:name="android.intent.category.LAUNCHER" />  

  21.            </intent-filter>  

  22.        </activity>  

  23.        <activity  

  24.            android:name=".MipcaActivityCapture"

  25.            android:configChanges="orientation|keyboardHidden"

  26.            android:screenOrientation="landscape"

  27.            android:windowSoftInputMode="stateAlwaysHidden" >  

  28.        </activity>  

  29.    </application>  

  30.    <uses-permission android:name="android.permission.VIBRATE" />  

  31.    <uses-permission android:name="android.permission.CAMERA" />  

  32.    <uses-feature android:name="android.hardware.camera" />  

  33.    <uses-feature android:name="android.hardware.camera.autofocus" />  

  34. </manifest>  

MainActivity.java

[java]view plaincopyprint?
  1. package com.example.qr_codescan;  

  2. import android.app.Activity;  

  3. import android.content.Intent;  

  4. import android.graphics.Bitmap;  

  5. import android.os.Bundle;  

  6. import android.view.View;  

  7. import android.view.View.OnClickListener;  

  8. import android.widget.Button;  

  9. import android.widget.ImageView;  

  10. import android.widget.TextView;  

  11. import com.unity3d.player.UnityPlayer;  

  12. import com.unity3d.player.UnityPlayerActivity;  

  13. publicclass MainActivity extends UnityPlayerActivity {  

  14. privatefinalstaticint SCANNIN_GREQUEST_CODE = 1;  

  15. /**

  16.     * 顯示掃描結(jié)果

  17.     */

  18. //  private TextView mTextView ;

  19. /**

  20.     * 顯示掃描拍的圖片

  21.     */

  22. //  private ImageView mImageView;

  23. @Override

  24. protectedvoid onCreate(Bundle savedInstanceState) {  

  25. super.onCreate(savedInstanceState);  

  26. //      setContentView(R.layout.activity_main);

  27. //      

  28. //      mTextView = (TextView) findViewById(R.id.result);

  29. //      mImageView = (ImageView) findViewById(R.id.qrcode_bitmap);

  30. //      

  31. //      //點(diǎn)擊按鈕跳轉(zhuǎn)到二維碼掃描界面,這里用的是startActivityForResult跳轉(zhuǎn)

  32. //      //掃描完了之后調(diào)到該界面

  33. //      Button mButton = (Button) findViewById(R.id.button1);

  34. //      mButton.setOnClickListener(new OnClickListener() {

  35. //          

  36. //          @Override

  37. //          public void onClick(View v) {

  38. //              Intent intent = new Intent();

  39. //              intent.setClass(MainActivity.this, MipcaActivityCapture.class);

  40. //              intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

  41. //              startActivityForResult(intent, SCANNIN_GREQUEST_CODE);

  42. //          }

  43. //      });

  44.    }  

  45. publicvoid Show()  

  46.    {  

  47.        Intent intent = new Intent();  

  48.        intent.setClass(MainActivity.this, MipcaActivityCapture.class);  

  49.        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);  

  50.        startActivityForResult(intent, SCANNIN_GREQUEST_CODE);  

  51.    }  

  52. @Override

  53. protectedvoid onActivityResult(int requestCode, int resultCode, Intent data) {  

  54. super.onActivityResult(requestCode, resultCode, data);  

  55. switch (requestCode) {  

  56. case SCANNIN_GREQUEST_CODE:  

  57. if(resultCode == RESULT_OK){  

  58.                Bundle bundle = data.getExtras();  

  59. //顯示掃描到的內(nèi)容

  60. //              mTextView.setText(bundle.getString("result"));

  61. //顯示

  62. //              mImageView.setImageBitmap((Bitmap) data.getParcelableExtra("bitmap"));

  63.                UnityPlayer.UnitySendMessage("GameObject","GetString",bundle.getString("result"));  

  64.            }  

  65. break;  

  66.        }  

  67.    }    

  68. }  


MipcaActivityCapture.java

修改中文編碼
characterSet = "GBK";

CameraConfigurationManager.java

[java]view plaincopyprint?
  1. /*

  2. * Copyright (C) 2010 ZXing authors

  3. *

  4. * Licensed under the Apache License, Version 2.0 (the "License");

  5. * you may not use this file except in compliance with the License.

  6. * You may obtain a copy of the License at

  7. *

  8. *      http://www.apache.org/licenses/LICENSE-2.0

  9. *

  10. * Unless required by applicable law or agreed to in writing, software

  11. * distributed under the License is distributed on an "AS IS" BASIS,

  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

  13. * See the License for the specific language governing permissions and

  14. * limitations under the License.

  15. */

  16. package com.mining.app.zxing.camera;  

  17. import android.content.Context;  

  18. import android.graphics.Point;  

  19. import android.hardware.Camera;  

  20. import android.os.Build;  

  21. import android.util.Log;  

  22. import android.view.Display;  

  23. import android.view.WindowManager;  

  24. import java.lang.reflect.Method;  

  25. import java.util.regex.Pattern;  

  26. finalclass CameraConfigurationManager {  

  27. privatestaticfinal String TAG = CameraConfigurationManager.class.getSimpleName();  

  28. privatestaticfinalint TEN_DESIRED_ZOOM = 27;  

  29. privatestaticfinalint DESIRED_SHARPNESS = 30;  

  30. privatestaticfinal Pattern COMMA_PATTERN = Pattern.compile(",");  

  31. privatefinal Context context;  

  32. private Point screenResolution;  

  33. private Point cameraResolution;  

  34. privateint previewFormat;  

  35. private String previewFormatString;  

  36.  CameraConfigurationManager(Context context) {  

  37. this.context = context;  

  38.  }  

  39. /**

  40.   * Reads, one time, values from the camera that are needed by the app.

  41.   */

  42. void initFromCameraParameters(Camera camera) {  

  43.    Camera.Parameters parameters = camera.getParameters();  

  44.    previewFormat = parameters.getPreviewFormat();  

  45.    previewFormatString = parameters.get("preview-format");  

  46.    Log.d(TAG, "Default preview format: " + previewFormat + '/' + previewFormatString);  

  47.    WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);  

  48.    Display display = manager.getDefaultDisplay();  

  49.    screenResolution = new Point(display.getWidth(), display.getHeight());  

  50.    Log.d(TAG, "Screen resolution: " + screenResolution);  

  51.    cameraResolution = getCameraResolution(parameters, screenResolution);  

  52.    Log.d(TAG, "Camera resolution: " + screenResolution);  

  53.  }  

  54. /**

  55.   * Sets the camera up to take preview p_w_picpaths which are used for both preview and decoding.

  56.   * We detect the preview format here so that buildLuminanceSource() can build an appropriate

  57.   * LuminanceSource subclass. In the future we may want to force YUV420SP as it's the smallest,

  58.   * and the planar Y can be used for barcode scanning without a copy in some cases.

  59.   */

  60. void setDesiredCameraParameters(Camera camera) {  

  61.    Camera.Parameters parameters = camera.getParameters();  

  62.    Log.d(TAG, "Setting preview size: " + cameraResolution);  

  63.    parameters.setPreviewSize(cameraResolution.x, cameraResolution.y);  

  64.    setFlash(parameters);  

  65.    setZoom(parameters);  

  66. //setSharpness(parameters);

  67. //modify here

  68. //    camera.setDisplayOrientation(90);

  69. //兼容2.1

  70. //setDisplayOrientation(camera, 90);

  71.    camera.setParameters(parameters);  

  72.  }  

  73.  Point getCameraResolution() {  

  74. return cameraResolution;  

  75.  }  

  76.  Point getScreenResolution() {  

  77. return screenResolution;  

  78.  }  

  79. int getPreviewFormat() {  

  80. return previewFormat;  

  81.  }  

  82.  String getPreviewFormatString() {  

  83. return previewFormatString;  

  84.  }  

  85. privatestatic Point getCameraResolution(Camera.Parameters parameters, Point screenResolution) {  

  86.    String previewSizeValueString = parameters.get("preview-size-values");  

  87. // saw this on Xperia

  88. if (previewSizeValueString == null) {  

  89.      previewSizeValueString = parameters.get("preview-size-value");  

  90.    }  

  91.    Point cameraResolution = null;  

  92. if (previewSizeValueString != null) {  

  93.      Log.d(TAG, "preview-size-values parameter: " + previewSizeValueString);  

  94.      cameraResolution = findBestPreviewSizeValue(previewSizeValueString, screenResolution);  

  95.    }  

  96. if (cameraResolution == null) {  

  97. // Ensure that the camera resolution is a multiple of 8, as the screen may not be.

  98.      cameraResolution = new Point(  

  99.          (screenResolution.x >> 3) << 3,  

  100.          (screenResolution.y >> 3) << 3);  

  101.    }  

  102. return cameraResolution;  

  103.  }  

  104. privatestatic Point findBestPreviewSizeValue(CharSequence previewSizeValueString, Point screenResolution) {  

  105. int bestX = 0;  

  106. int bestY = 0;  

  107. int diff = Integer.MAX_VALUE;  

  108. for (String previewSize : COMMA_PATTERN.split(previewSizeValueString)) {  

  109.      previewSize = previewSize.trim();  

  110. int dimPosition = previewSize.indexOf('x');  

  111. if (dimPosition < 0) {  

  112.        Log.w(TAG, "Bad preview-size: " + previewSize);  

  113. continue;  

  114.      }  

  115. int newX;  

  116. int newY;  

  117. try {  

  118.        newX = Integer.parseInt(previewSize.substring(0, dimPosition));  

  119.        newY = Integer.parseInt(previewSize.substring(dimPosition + 1));  

  120.      } catch (NumberFormatException nfe) {  

  121.        Log.w(TAG, "Bad preview-size: " + previewSize);  

  122. continue;  

  123.      }  

  124. int newDiff = Math.abs(newX - screenResolution.x) + Math.abs(newY - screenResolution.y);  

  125. if (newDiff == 0) {  

  126.        bestX = newX;  

  127.        bestY = newY;  

  128. break;  

  129.      } elseif (newDiff < diff) {  

  130.        bestX = newX;  

  131.        bestY = newY;  

  132.        diff = newDiff;  

  133.      }  

  134.    }  

  135. if (bestX > 0 && bestY > 0) {  

  136. returnnew Point(bestX, bestY);  

  137.    }  

  138. returnnull;  

  139.  }  

  140. privatestaticint findBestMotZoomValue(CharSequence stringValues, int tenDesiredZoom) {  

  141. int tenBestValue = 0;  

  142. for (String stringValue : COMMA_PATTERN.split(stringValues)) {  

  143.      stringValue = stringValue.trim();  

  144. double value;  

  145. try {  

  146.        value = Double.parseDouble(stringValue);  

  147.      } catch (NumberFormatException nfe) {  

  148. return tenDesiredZoom;  

  149.      }  

  150. int tenValue = (int) (10.0 * value);  

  151. if (Math.abs(tenDesiredZoom - value) < Math.abs(tenDesiredZoom - tenBestValue)) {  

  152.        tenBestValue = tenValue;  

  153.      }  

  154.    }  

  155. return tenBestValue;  

  156.  }  

  157. privatevoid setFlash(Camera.Parameters parameters) {  

  158. // FIXME: This is a hack to turn the flash off on the Samsung Galaxy.

  159. // And this is a hack-hack to work around a different value on the Behold II

  160. // Restrict Behold II check to Cupcake, per Samsung's advice

  161. //if (Build.MODEL.contains("Behold II") &&

  162. //    CameraManager.SDK_INT == Build.VERSION_CODES.CUPCAKE) {

  163. if (Build.MODEL.contains("Behold II") && CameraManager.SDK_INT == 3) { // 3 = Cupcake

  164.      parameters.set("flash-value", 1);  

  165.    } else {  

  166.      parameters.set("flash-value", 2);  

  167.    }  

  168. // This is the standard setting to turn the flash off that all devices should honor.

  169.    parameters.set("flash-mode", "off");  

  170.  }  

  171. privatevoid setZoom(Camera.Parameters parameters) {  

  172.    String zoomSupportedString = parameters.get("zoom-supported");  

  173. if (zoomSupportedString != null && !Boolean.parseBoolean(zoomSupportedString)) {  

  174. return;  

  175.    }  

  176. int tenDesiredZoom = TEN_DESIRED_ZOOM;  

  177.    String maxZoomString = parameters.get("max-zoom");  

  178. if (maxZoomString != null) {  

  179. try {  

  180. int tenMaxZoom = (int) (10.0 * Double.parseDouble(maxZoomString));  

  181. if (tenDesiredZoom > tenMaxZoom) {  

  182.          tenDesiredZoom = tenMaxZoom;  

  183.        }  

  184.      } catch (NumberFormatException nfe) {  

  185.        Log.w(TAG, "Bad max-zoom: " + maxZoomString);  

  186.      }  

  187.    }  

  188.    String takingPictureZoomMaxString = parameters.get("taking-picture-zoom-max");  

  189. if (takingPictureZoomMaxString != null) {  

  190. try {  

  191. int tenMaxZoom = Integer.parseInt(takingPictureZoomMaxString);  

  192. if (tenDesiredZoom > tenMaxZoom) {  

  193.          tenDesiredZoom = tenMaxZoom;  

  194.        }  

  195.      } catch (NumberFormatException nfe) {  

  196.        Log.w(TAG, "Bad taking-picture-zoom-max: " + takingPictureZoomMaxString);  

  197.      }  

  198.    }  

  199.    String motZoomValuesString = parameters.get("mot-zoom-values");  

  200. if (motZoomValuesString != null) {  

  201.      tenDesiredZoom = findBestMotZoomValue(motZoomValuesString, tenDesiredZoom);  

  202.    }  

  203.    String motZoomStepString = parameters.get("mot-zoom-step");  

  204. if (motZoomStepString != null) {  

  205. try {  

  206. double motZoomStep = Double.parseDouble(motZoomStepString.trim());  

  207. int tenZoomStep = (int) (10.0 * motZoomStep);  

  208. if (tenZoomStep > 1) {  

  209.          tenDesiredZoom -= tenDesiredZoom % tenZoomStep;  

  210.        }  

  211.      } catch (NumberFormatException nfe) {  

  212. // continue

  213.      }  

  214.    }  

  215. // Set zoom. This helps encourage the user to pull back.

  216. // Some devices like the Behold have a zoom parameter

  217. if (maxZoomString != null || motZoomValuesString != null) {  

  218.      parameters.set("zoom", String.valueOf(tenDesiredZoom / 10.0));  

  219.    }  

  220. // Most devices, like the Hero, appear to expose this zoom parameter.

  221. // It takes on values like "27" which appears to mean 2.7x zoom

  222. if (takingPictureZoomMaxString != null) {  

  223.      parameters.set("taking-picture-zoom", tenDesiredZoom);  

  224.    }  

  225.  }  

  226. publicstaticint getDesiredSharpness() {  

  227. return DESIRED_SHARPNESS;  

  228.    }  

  229. /**

  230.     * compatible  1.6

  231.     * @param camera

  232.     * @param angle

  233.     */

  234. protectedvoid setDisplayOrientation(Camera camera, int angle){    

  235.        Method downPolymorphic;    

  236. try

  237.        {    

  238.            downPolymorphic = camera.getClass().getMethod("setDisplayOrientation", new Class[] { int.class });    

  239. if (downPolymorphic != null)    

  240.                downPolymorphic.invoke(camera, new Object[] { angle });    

  241.        }    

  242. catch (Exception e1)    

  243.        {    

  244.        }    

  245.   }    

  246. }  


能解決這一系列的問題還要感覺龍哥的指導(dǎo),在此感謝!
這時(shí)比較晚了就不貼原工程了,明天貼出來!
如果有誰知道以上問題有更好的解決方案,還望指教,相互學(xué)習(xí),Aladdin在此感謝,哈哈!
我的微博:http://weibo.com/dingxiaowei2013


向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI