这两天玩Android玩的废寝忘食,Blog都好几天没加东西了,惭愧!记录一下这两天最崩溃的一个问题。
好早就装了开发环境,真正着手还是这两天,非常的生疏,虽然有SDK文档,那么多蚊子一般的字,实在没心思慢慢研究。这不想调用摄像头,原以为很容易就能搞定的,累计花了大概有一天的时间才只能保证不出错……至于效果嘛,难说啊!
先看API-examples里有调用 摄像头的例子,在模拟器上虽然看不出什么效果,毕竟还是能执行的,就是一个方块在黑白相间的背景上移动呗。
就这么一个Google提供的范例,传到我的HTC G2上也能一执行就报错,我对Google的尊敬之情顿时减少了0.0001%啊……(当然有可能是G2不够标准,但毕竟其他的软件都是能用的,看来是有不少健壮代码了啊)。联机调试看了一下,出错的这一行(android-7里的):
1
|
parameters
.
setPreviewSize
(
w
,
h
)
;
|
查一下,摄像头不是所有随便的(w, h)都能够认识的,所以呢,我们有了下面这样的增强版:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
List
<
Size
>
mSupportedPreviewSizes
;
mSupportedPreviewSizes
=
mCamera
.
getParameters
(
)
.
getSupportedPreviewSizes
(
)
;
mPreviewSize
=
getOptimalPreviewSize
(
mSupportedPreviewSizes
,
width
,
height
)
;
private
Size
getOptimalPreviewSize
(
List
<
Size
>
sizes
,
int
w
,
int
h
)
{
final
double
ASPECT_TOLERANCE
=
0.1
;
double
targetRatio
=
(
double
)
w
/
h
;
if
(
sizes
==
null
)
return
null
;
Size
optimalSize
=
null
;
double
minDiff
=
Double
.
MAX_VALUE
;
int
targetHeight
=
h
;
// Try to find an size match aspect ratio and size
for
(
Size
size
:
sizes
)
{
double
ratio
=
(
double
)
size
.
width
/
size
.
height
;
if
(
Math
.
abs
(
ratio
-
targetRatio
)
>
ASPECT_TOLERANCE
)
continue
;
if
(
Math
.
abs
(
size
.
height
-
targetHeight
)
<
minDiff
)
{
optimalSize
=
size
;
minDiff
=
Math
.
abs
(
size
.
height
-
targetHeight
)
;
}
}
// Cannot find the one match the aspect ratio, ignore the requirement
if
(
optimalSize
==
null
)
{
minDiff
=
Double
.
MAX_VALUE
;
for
(
Size
size
:
sizes
)
{
if
(
Math
.
abs
(
size
.
height
-
targetHeight
)
<
minDiff
)
{
optimalSize
=
size
;
minDiff
=
Math
.
abs
(
size
.
height
-
targetHeight
)
;
}
}
}
return
optimalSize
;
}
|
后来的Sample里有了这段代码,看起来强大了不少。然而非常不幸的,首先getSupportedPreviewSizes()这个函数在2.1之后才有,我一开始是打算用1.6开发的……好吧我改,这个先不说,自己的手机已经刷到2.1了,这个函数的返回值居然是null?!如果确实想老版本上也用的话,怎么办??
有鉴于有软件可以达成,所以肯定是有方法的!得这么写:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
public
class
SupportedSizesReflect
{
private
static
Method
Parameters_getSupportedPreviewSizes
=
null
;
private
static
Method
Parameters_getSupportedPictureSizes
=
null
;
static
{
initCompatibility
(
)
;
}
;
private
static
void
initCompatibility
(
)
{
try
{
Parameters_getSupportedPreviewSizes
=
Camera
.
Parameters
.
class
.
getMethod
(
"getSupportedPreviewSizes"
,
new
Class
[
]
{
}
)
;
Parameters_getSupportedPictureSizes
=
Camera
.
Parameters
.
class
.
getMethod
(
"getSupportedPictureSizes"
,
new
Class
[
]
{
}
)
;
}
catch
(
NoSuchMethodException
nsme
)
{
nsme
.
printStackTrace
(
)
;
Parameters_getSupportedPreviewSizes
=
Parameters_getSupportedPictureSizes
=
null
;
}
}
/**
* Android 2.1之后有效
* @param p
* @return Android1.x返回null
*/
public
static
List
<
Size
>
getSupportedPreviewSizes
(
Camera
.
Parameters
p
)
{
return
getSupportedSizes
(
p
,
Parameters_getSupportedPreviewSizes
)
;
}
public
static
List
<
Size
>
getSupportedPictureSizes
(
Camera
.
Parameters
p
)
{
return
getSupportedSizes
(
p
,
Parameters_getSupportedPictureSizes
)
;
}
@
SuppressWarnings
(
"unchecked"
)
private
static
List
<
Size
>
getSupportedSizes
(
Camera
.
Parameters
p
,
Method
method
)
{
try
{
if
(
method
!=
null
)
{
return
(
List
<
Size
>
)
method
.
invoke
(
p
)
;
}
else
{
return
null
;
}
}
catch
(
InvocationTargetException
ite
)
{
Throwable
cause
=
ite
.
getCause
(
)
;
if
(
cause
instanceof
RuntimeException
)
{
throw
(
RuntimeException
)
cause
;
}
else
if
(
cause
instanceof
Error
)
{
throw
(
Error
)
cause
;
}
else
{
throw
new
RuntimeException
(
ite
)
;
}
}
catch
(
IllegalAccessException
ie
)
{
return
null
;
}
}
}
|
啊啊~,リフレクションなんか、大嫌い……然后还要用类似这样的方法调用~
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
@
Override
public
void
surfaceChanged
(
SurfaceHolder
holder
,
int
format
,
int
width
,
int
height
)
{
Camera
.
Parameters
params
=
camera
.
getParameters
(
)
;
List
<
Size
>
supportedPictureSizes
=
SupportedSizesReflect
.
getSupportedPictureSizes
(
params
)
;
List
<
Size
>
supportedPreviewSizes
=
SupportedSizesReflect
.
getSupportedPreviewSizes
(
params
)
;
if
(
supportedPictureSizes
!=
null
&&
supportedPreviewSizes
!=
null
&&
supportedPictureSizes
.
size
(
)
>
0
&&
supportedPreviewSizes
.
size
(
)
>
0
)
{
//2.x
pictureSize
=
supportedPictureSizes
.
get
(
0
)
;
int
maxSize
=
1280
;
if
(
maxSize
>
0
)
{
for
(
Size
size
:
supportedPictureSizes
)
{
if
(
maxSize
>=
Math
.
max
(
size
.
width
,
size
.
height
)
)
{
pictureSize
=
size
;
break
;
}
}
}
WindowManager
windowManager
=
(
WindowManager
)
context
.
getSystemService
(
Context
.
WINDOW_SERVICE
)
;
Display
display
=
windowManager
.
getDefaultDisplay
(
)
;
DisplayMetrics
displayMetrics
=
new
DisplayMetrics
(
)
;
display
.
getMetrics
(
displayMetrics
)
;
previewSize
=
getOptimalPreviewSize
(
supportedPreviewSizes
,
display
.
getWidth
(
)
,
display
.
getHeight
(
)
)
;
params
.
setPictureSize
(
pictureSize
.
width
,
pictureSize
.
height
)
;
params
.
setPreviewSize
(
previewSize
.
width
,
previewSize
.
height
)
;
}
this
.
camera
.
setParameters
(
params
)
;
try
{
this
.
camera
.
setPreviewDisplay
(
holder
)
;
}
catch
(
IOException
e
)
{
e
.
printStackTrace
(
)
;
}
this
.
camera
.
startPreview
(
)
;
}
|
死机无数次之后总结出来的啊,发现程序写的一个不好强制结束了,摄像头都无法再次启用了,kill都不行,只能重新启动手机才好。重启一次还那么慢,谁知道有比较适合G2的row?
哦还有一个,预览画面90°的,2.X后可以用parameters.set(“rotation”, “90”),之前的话得写成parameters.set(“orientation”, “portrait”)。但是据说不是所有的机器都可以的……