I’ve got live camera input working both on the desktop (MacBook Pro) and iOS (iPhone4), but I can’t get anything out of either of my Android phones (LG Optimus and Samsung Galaxy Nexus).
Here’s my script (attach it to a plane with a RenderTexture)
#pragma strict
private var devices : WebCamDevice[];
public var deviceName : String;
private var wct : WebCamTexture;
private var resultString : String;
function Start() {
yield Application.RequestUserAuthorization (UserAuthorization.WebCam | UserAuthorization.Microphone);
if (Application.HasUserAuthorization(UserAuthorization.WebCam | UserAuthorization.Microphone)) {
devices = WebCamTexture.devices;
deviceName = devices[0].name;
wct = new WebCamTexture(deviceName, 640, 480, 30);
renderer.material.mainTexture = wct;
wct.Play();
resultString = "no problems";
} else {
resultString = "no permission!";
}
}
function OnGUI() {
for (var i = 0; i < devices.length; i++) {
GUI.Box(Rect(100, 100+(i*25), 300, 25),devices[i].name);
}
GUI.Box(Rect(100, 100+(i*25), 400, 25),resultString);
}
Unfortunately, I don’t know how to query the phone to figure out what the default values are - specs on the phone are 1080p on the main camera, 720p on the front-facing one - I’ve tried those and every other standard resolution I can think of, but none of them make any difference
In any case, according to the script reference, all I’m specifying are the requested width, height, fps:
“The real width [height, frame rate] may be different, and will match the closest width [height, frame rate] supported by the device.”
So shouldn’t it work whatever resolution I’m requesting?
Meanwhile, does anyone have any suggestions regarding the AndroidManifest file? Does anything look wrong? I’d really love to get this working.
I don’t have anything productive to offer, other than a “me too” - on an Asus Eee Transformer TF-101 (last year’s version), it reports two cameras and everything looks fine except the picture is just black, whichever camera I use. I tried the same authorization request code that you’re using, and confirmed via OnGUI that HasUserAuthorization is returning true.
I have no idea where to find the manifest file, let alone what it ought to look like! As far as I can tell, Unity generates an APK and copies it straight to the device, and everything works except the camera.
I found a lot of old threads, and UnityAnswers questions, on this topic but I think MADmarine’s post is the first time I’ve seen anybody saying it actually works for them!
George - The Android Manifest file is created when you build your application for Android - there’s a Temp folder in the project folder, inside that a StagingArea folder gets created when you build, and inside that is the AndroidManifest.xml file. The manifest gets created on the fly every time you build your app, but as I understand it, you can move it to Assets/Plugins/Android/, make any changes you want to it, and then that’s the manifest that will be loaded next time you build. Someone with more knowledge than me should confirm that I’ve got all the facts right on this.
And (speaking of people with more knowledge than me) I would really appreciate it if someone - anyone - who understands these things could take a look at the Android Manifest file that I posted above and make some suggestions about what alterations or updates might have an effect.
MADmarine - phones are up to date, don’t think that’s the problem
tonydongyiqi? wccrawford? Anyone? Care to help us out here?
Someone just PM’ed me with a few more questions about how I got the camera to work on my tablet, I thought I’d just share some of my answers just in case it helps anyone else:
I think it may be written somewhere that Android 4.0.3 is needed for the camera, but it is definitely not required for it to run on the tablet/phone. I do think you have to have the 4.0.3 SDK installed on your development system however. I’m not sure what the key bit of info is to getting the camera to work, so I’ll just list as many things as I can about what I’m doing and hopefully you’ll manage to get it working.
I made sure that I downloaded the latest SDK for Android along with some others and pointed Unity at that. So have on my system the SDKs for 4.0.3, 2.3.3, and 2.1 installed. And that’s WITH the Google APIs for each.
In my Unity settings I put the minimum API Level as 2.3.3 Gingerbread (API level 10).
The other settings are mostly at default (ARMv7 only, OpenGL ES 2.0, with auto install and internet access, write access to external storage).
I don’t know if this also makes a massive difference, but I don’t start up my camera straight away. I find that if I try to do too much with the camera in a single frame my tablet crashes too. So perhaps try having a button in your app that will start up the camera (just for testing this out anyway), don’t try to start up at the same time as the app.
I’ve got all the Android SDKs installed, and the Google APIs as well.
As far as “pointing Unity towards the SDK” - you just mean the setting in Preferences/External Tools/Android SDK Location, right? I have that set to /Developer/android-sdk-macosx
I tried changing the minimum API level at 2.3.3 (and tried 4.0 also, since that’s what’s running on the phone).
I tried using a button to start the camera up, instead of starting it up with the app.
Still getting nothing but a big black rectangle.
Anyway, MADmarine, I really appreciate all your help on this, whether we’ve solved it or not.
Obviously I’m not the only one having this problem, but in the absence of anyone else chiming in with any ideas or suggestions (by now I would have expected somebody from Unity to offer some kind of support) I guess I will have to conclude that this is a bug, and that I should just file a bug report and give up until it gets fixed.
#pragma strict
private var m_CameraTexture : WebCamTexture;
function Start () {
}
function Update () {
if (m_CameraTexture != null m_CameraTexture.didUpdateThisFrame) {
transform.renderer.material.mainTexture = m_CameraTexture;
}
}
function OnGUI() {
if (GUI.Button(Rect(50,10,200,50),"Start WebCam")) {
m_CameraTexture = new WebCamTexture(WebCamTexture.devices[0].name);
if (m_CameraTexture != null) {
m_CameraTexture.Play();
}
}
}
Yep, sorry I wasn’t too clear about that SDK part.
It definitely shouldn’t be this hard to get the camera working so there’s a bug or two somewhere I agree. I guess another thing different from my setup is that I’m using C#, but this is just clutching at straws now.
Hi MADmarine, thanks for giving more details. I wondered whether you could upload a working .apk file so we can test it on our devices? It would determine once and for all whether it’s a device problem or a build problem.
This script works on my macbook pro, and on a toshiba thrive. No luck on droid-x. On the thrive, both cameras are detected.
using System;
using UnityEngine;
using System.Collections.Generic;
public class CameraTest : MonoBehaviour
{
/// <summary>
/// Meta reference to the camera
/// </summary>
public Material CameraMaterial = null;
/// <summary>
/// The number of frames per second
/// </summary>
private int m_framesPerSecond = 0;
/// <summary>
/// The current frame count
/// </summary>
private int m_frameCount = 0;
/// <summary>
/// The frames timer
/// </summary>
private DateTime m_timerFrames = DateTime.MinValue;
/// <summary>
/// The selected device index
/// </summary>
private int m_indexDevice = -1;
/// <summary>
/// The web cam texture
/// </summary>
private WebCamTexture m_texture = null;
// Use this for initialization
void Start()
{
if (null == CameraMaterial)
{
throw new ApplicationException("Missing camera material reference");
}
Application.RequestUserAuthorization(UserAuthorization.WebCam);
}
void OnGUI()
{
if (m_timerFrames < DateTime.Now)
{
m_framesPerSecond = m_frameCount;
m_frameCount = 0;
m_timerFrames = DateTime.Now + TimeSpan.FromSeconds(1);
}
++m_frameCount;
GUILayout.Label(string.Format("Frames per second: {0}", m_framesPerSecond));
if (m_indexDevice >= 0
WebCamTexture.devices.Length > 0)
{
GUILayout.Label(string.Format("Selected Device: {0}", WebCamTexture.devices[m_indexDevice].name));
}
if (Application.HasUserAuthorization(UserAuthorization.WebCam))
{
GUILayout.Label("Has WebCam Authorization");
if (null == WebCamTexture.devices)
{
GUILayout.Label("Null web cam devices");
}
else
{
GUILayout.Label(string.Format("{0} web cam devices", WebCamTexture.devices.Length));
for (int index = 0; index < WebCamTexture.devices.Length; ++index)
{
var device = WebCamTexture.devices[index];
if (string.IsNullOrEmpty(device.name))
{
GUILayout.Label("unnamed web cam device");
continue;
}
if (GUILayout.Button(string.Format("web cam device {0}{1}{2}",
m_indexDevice == index
? "["
: string.Empty,
device.name,
m_indexDevice == index ? "]" : string.Empty),
GUILayout.MinWidth(200),
GUILayout.MinHeight(50)))
{
m_indexDevice = index;
// stop playing
if (null != m_texture)
{
if (m_texture.isPlaying)
{
m_texture.Stop();
}
}
// destroy the old texture
if (null != m_texture)
{
UnityEngine.Object.DestroyImmediate(m_texture, true);
}
// use the device name
m_texture = new WebCamTexture(device.name);
// start playing
m_texture.Play();
// assign the texture
CameraMaterial.mainTexture = m_texture;
}
}
}
}
else
{
GUILayout.Label("Pending WebCam Authorization...");
}
}
// Update is called once per frame
private void Update()
{
if (null != m_texture
m_texture.didUpdateThisFrame)
{
CameraMaterial.mainTexture = m_texture;
}
}
}
I get the same issues as tgraupmann, and can’t seem to find a solution either, other than looking elsewhere. Prime31s plugin works, but it launches an entirely seperate activity which isn’t what we want.
checking out the logcat, get interesting dump of camera stats, but nothing that hints at what maybe amiss, except the mysterious param 50, 51, and 53.