hsongxian / Wallpaper

透明屏幕
372 stars 103 forks source link

java.lang.RuntimeException: Fail to connect to camera service #4

Open zsj6102 opened 7 years ago

zsj6102 commented 7 years ago

android API 19

PeanutZhang commented 7 years ago

MEIZU API23 也是这个错误 , 定位在camera = Camera.open();这一行

hsongxian commented 7 years ago

加上 :

试试,因为我没那么多手机测试 原文: https://developer.android.com/reference/android/hardware/Camera.html

hsongxian commented 7 years ago
<uses-feature android:name="android.hardware.camera.autofocus" />
hsongxian commented 7 years ago

发不了标签, 标签加上 / :

hsongxian commented 7 years ago

uses-feature android:name="android.hardware.camera" uses-feature android:name="android.hardware.camera.autofocus"

vonions commented 7 years ago

NX513J 加了标签还是报错

LoveqLRC commented 7 years ago

加了标签还是报错...华为

kHRYSTAL commented 7 years ago

这样可以解决这个异常

private void startPreview() {
            if (camera != null) {
                camera.release();
            }
            camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
            camera.setDisplayOrientation(90);

            try {
                camera.setPreviewDisplay(getSurfaceHolder());
            } catch (IOException e) {
                e.printStackTrace();
            }
            camera.startPreview();
        }
LoveqLRC commented 7 years ago

well done @kHRYSTAL

LoveqLRC commented 7 years ago

有没有什么办法控制清晰度?

kHRYSTAL commented 7 years ago

@LoveqLRC 清晰度还有预览变形是因为预览分辨率和没有对焦导致的 我简单改了下代码 如果要做到机型适配这个方案不可行 需要写Sensor控制对焦

private void startPreview() {
            if (camera != null) {
                camera.release();
                camera = null;
            }
            camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
            camera.setDisplayOrientation(90);

            // 设置预览分辨率
            Camera.Parameters parameters = camera.getParameters();
            Camera.Size size = CameraUtil.getFullScreenSize(parameters.getSupportedPreviewSizes());
            parameters.setPreviewSize(size.width, size.height);
            // 设置自动对焦
            parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
            camera.setParameters(parameters);

            try {
                camera.setPreviewDisplay(getSurfaceHolder());
            } catch (IOException e) {
                e.printStackTrace();
            }
            camera.startPreview();
            camera.cancelAutoFocus();
        }

CameraUtil:

public class CameraUtil {

    private static final String TAG = CameraUtil.class.getSimpleName();

    public static void setFullScreenSize(Activity context) {
        DisplayMetrics dm = new DisplayMetrics();
        //获取屏幕信息
        context.getWindowManager().getDefaultDisplay().getMetrics(dm);
        int screenWidth = dm.widthPixels;
        int screenHeight = dm.heightPixels;
        setKeyValue("width", screenWidth);
        setKeyValue("height", screenHeight);

        int statusBarHeight = -1;
        int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            //根据资源ID获取响应的尺寸值
            statusBarHeight = context.getResources().getDimensionPixelSize(resourceId);
        }
        setKeyValue("status", statusBarHeight);
    }

    public static Camera.Size getFullScreenSize(List<Camera.Size> preSizeList) {
        int width = getByKey("width", 1080);
        int height = getByKey("height", 1920);
        return getCloselyPreSize(true, width, height, preSizeList);
    }

    /**
     * set key and valueint
     */
    public static  <T> void setKeyValue(String key, T i) {
        SharedPreferences.Editor editor = Application.APP_PREFERENCE.edit();
        if (i instanceof Integer) {
            editor.putInt(key, (Integer) i);
        } else if (i instanceof String) {
            editor.putString(key, (String) i);
        } else if (i instanceof Long) {
            editor.putLong(key, (Long) i);
        } else if (i instanceof Boolean) {
            editor.putBoolean(key, (Boolean) i);
        }
        editor.commit();
    }

    /**
     * 获取value
     *
     * @param key
     * @param defaultValue 当不存在时返回默认值
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T getByKey(String key, T defaultValue) {
        Map<String, ?> maps = Application.APP_PREFERENCE.getAll();
        if (!maps.containsKey(key))
            return defaultValue;

        Object value = maps.get(key);
        return (T) value;
    }

    /**
     * 获取近似的摄像头预览尺寸
     * @return
     */
    public static Camera.Size getCloselyPreSize(boolean isPortrait, int surfaceWidth, int surfaceHeight,
                                            List<Camera.Size> preSizeList) {
        int ReqTmpWidth;
        int ReqTmpHeight;
        // 当屏幕为垂直的时候需要把宽高值进行调换,保证宽大于高
        if (isPortrait) {
            ReqTmpWidth = surfaceHeight;
            ReqTmpHeight = surfaceWidth;
        } else {
            ReqTmpWidth = surfaceWidth;
            ReqTmpHeight = surfaceHeight;
        }
        //先查找preview中是否存在与surfaceview相同宽高的尺寸
        for(Camera.Size size : preSizeList){
            if((size.width == ReqTmpWidth) && (size.height == ReqTmpHeight)){
                return size;
            }
        }

        // 得到与传入的宽高比最接近的size
        float reqRatio = ((float) ReqTmpWidth) / ReqTmpHeight;
        float curRatio, deltaRatio;
        float deltaRatioMin = Float.MAX_VALUE;
        Camera.Size retSize = null;
        for (Camera.Size size : preSizeList) {
            curRatio = ((float) size.width) / size.height;
            deltaRatio = Math.abs(reqRatio - curRatio);
            if (deltaRatio < deltaRatioMin) {
                deltaRatioMin = deltaRatio;
                retSize = size;
            }
        }
        return retSize;
    }
}

这只是适配个人测试手机(1+ A1001 5.1)的改动, 魅族mx6(6.0)测试不支持

LoveqLRC commented 7 years ago

老铁,Application.APP_PREFERENCE 这个是自己定义的工具类吧 @kHRYSTAL 可以的话,顺便贴一下

hsongxian commented 7 years ago

@LoveqLRC Application.APP_PREFERENCE 应该是 android.content.SharedPreferences

kHRYSTAL commented 7 years ago
public class Application extends android.app.Application {

    public static SharedPreferences APP_PREFERENCE;
    public static Context CONTEXT;

    @Override
    public void onCreate() {
        super.onCreate();
        CONTEXT = this;
        APP_PREFERENCE = this.getApplicationContext()
                .getSharedPreferences("wallpaper", Context.MODE_PRIVATE);
    }
}
LoveqLRC commented 7 years ago

一些机型,设置壁纸后,打开不了系统相机应用了 @songixan

LoveqLRC commented 7 years ago

设置壁纸后,一些机型,打开不了系统相机应用了 @kHRYSTAL

kHRYSTAL commented 7 years ago

@LoveqLRC 这应该是因为onVisiableChanged 回调是在相机打开后启动的 应该是某些rom没有处理multi camera open 导致的, 而之后再调用camera.release() 实际上已经没用了, 刚查了一下 没有找到好的解决办法 我想可以开一个线程快速轮询 检查当前系统最上方packagename是否与系统相机的packagename相同 如果相同 则释放camera :-(

xiangdengbin commented 6 years ago

I had the same problem.Can somebody help me? `public static Camera open() {

    int numCameras = Camera.getNumberOfCameras();
    if (numCameras == 0) {
        Log.w("TAG", "No cameras!");
        return null;
    }

    int index = 0;
    while (index < numCameras) {
        Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
        Camera.getCameraInfo(index, cameraInfo);
        // CAMERA_FACING_BACK:手机背面的摄像头
        if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
            break;
        }
        index++;
    }

    Camera camera;
    if (index < numCameras) {
        Log.i("TAG", "Opening camera #" + index);
        camera = Camera.open(index); **_// here is the wrong code._**
    } else {
        Log.i("TAG", "No camera facing back; returning camera #0");
        camera = Camera.open(0);
    }

    return camera;
}`