标签: surfaceview

使用SurfaceView编程和用于游戏开发的线程策略

我正在使用SurfaceView和渲染线程来开发基于LunarLander等结构的游戏.

但是,我遇到了很多问题,我想在这里指出一切.我希望任何想要开发游戏的人都不需要再与他们斗争了.任何对结构有更好了解的人都可以分享他们的经验,因为我还是新手,并渴望学习:)

[1] thread.start()不应多次调用该函数.

在创建表面时创建线程时提到的许多文章,以便在使用该方法暂停活动后再次渲染:

public void surfaceCreated(SurfaceHolder holder) {
    // start the thread here so that we don't busy-wait in run()
    // waiting for the surface to be created
    if (thread.getState() == Thread.State.TERMINATED)
    {
        thread = new LunarThread(getHolder(), getContext(), getHandler());
    }
    thread.setRunning(true);
    thread.start();
}
Run Code Online (Sandbox Code Playgroud)

您可以看到,如果线程未终止且函数被调用,则活动崩溃.

[2]如果您按下"电源"或"红色电话"按钮,或者电话闲置几分钟,则活动将处于onPause()状态,但线程仍在运行.这是一个非常糟糕的做法,所以我需要找到让线程停止的方法,然后重新开始onResume().

[3]如果屏幕锁定是纵向/横向,并且您的游戏粘贴到另一个方向,则屏幕锁定会强制您"定向"一次.这意味着再次开始活动.我仍然无法找到解决方案.(正如我在Android屏幕方向错误中提到的那样)

以下是我修复这些问题的代码:

UIThread

public class UIThread extends Activity
{
    private gameView gameview;
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        gameview = (gameView) findViewById(R.id.gameview);
    }
    protected …
Run Code Online (Sandbox Code Playgroud)

multithreading android surfaceview android-activity

15
推荐指数
1
解决办法
2万
查看次数

如何暂停和恢复surfaceView线程

我有一个surfaceView设置并运行,但当我恢复它时,我得到一个错误,该线程已经启动.当应用程序进入后台然后返回前台时,处理的正确方法是什么?我已经修好了并且设法让应用程序无法崩溃而返回......但是SurfaceView不再绘制任何东西了.我的代码:

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
           Log.e("sys","surfaceCreated was called.");
           if(systemState==BACKGROUND){
                  thread.setRunning(true);

           }
           else {
        thread.setRunning(true);
               thread.start();
               Log.e("sys","started thread");
               systemState=READY;
           }



    }
    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
           Log.e("sys","surfaceDestroyed was called.");
           thread.setRunning(false);
           systemState=BACKGROUND;
    }
Run Code Online (Sandbox Code Playgroud)

multithreading android surfaceview

14
推荐指数
2
解决办法
4万
查看次数

lockCanvas()真的很慢

在较慢的设备上测试我的游戏(Orange旧金山又名中兴Blade),我的帧速率令人震惊.

我将一些调试代码放入绘制循环中,发现以下行占用了100ms:

c = mSurfaceHolder.lockCanvas();
Run Code Online (Sandbox Code Playgroud)

其他人看到过这种行为吗?我通过扩展查看和执行的onDraw()暂时取代了surfaceview,我获得了很多更好的帧率.

虽然一般来说,SurfaceView在我的HTC Desire上要快得多.我怀疑这可能是Android 2.1问题.如果可能的话,我正在考虑生根并将其升级到2.2,但我确实想要在2.1上运行设备,这样从长远来看可能会适得其反.

**更新**

我一直在研究这个问题,并且发现了一些令人费解的方面.

我根据手机安装了2.2并且问题仍然存在.当应用程序首次启动时,lockCanvas按预期工作(0-1毫秒).然后在初始化期间的某个时刻,lockCanvas突然开始大约需要100ms.

值得指出的是,我正在异步任务中加载我的资产,以便我可以显示加载屏幕.

尽管我尽力确定程序在发生缓慢时实际正在做什么,但我无法做到这一点.事实上,当我在调试模式下单步运行时,它运行得很快!

现在我发现如果我在SurfaceView的构造函数中添加延迟(大约10秒),则不会发生缓慢而且一切正常.

但是,如果您按Home键然后切换回来,则缓慢返回.

对于这个愚蠢的不合逻辑的问题,我几乎已经到了最后!我有心思把它归结为特定于设备的问题.

我觉得它可能与内存使用有关.也许有些东西被换掉了,它会影响视频内存?

我至少对理论很感兴趣.

performance android frame-rate surfaceview

14
推荐指数
1
解决办法
4209
查看次数

如何有效地调整位图的大小,并在android中失去质量

我有一个Bitmap大小,320x480我需要在不同的设备屏幕上拉伸它,我尝试使用这个:

Rect dstRect = new Rect();
canvas.getClipBounds(dstRect);
canvas.drawBitmap(frameBuffer, null, dstRect, null);
Run Code Online (Sandbox Code Playgroud)

它工作,图像像我想要的那样填满整个屏幕,但图像像素化,看起来很糟糕.然后我尝试了:

float scaleWidth = (float) newWidth / width;
float scaleHeight = (float) newHeight / height;
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
Bitmap resizedBitmap = Bitmap.createBitmap(frameBuffer, 0, 0,
                width, height, matrix, true);
canvas.drawBitmap(resizedBitmap, 0, 0, null);
Run Code Online (Sandbox Code Playgroud)

这次它看起来很完美,漂亮和流畅,但是这段代码必须在我的主游戏循环中,并且Bitmap每次迭代创建它都会使它非常慢.如何调整图像大小以使其不会像素化并快速完成?

找到解决方案:

Paint paint = new Paint();
paint.setFilterBitmap();
canvas.drawBitmap(bitmap, matrix, paint);
Run Code Online (Sandbox Code Playgroud)

android resize canvas bitmap surfaceview

14
推荐指数
1
解决办法
3万
查看次数

如何在Android中的不同视图中并排在一个布局中同时播放多个视频文件

在Android中,我创建了一个并排有三个表面视图的布局,我想同时播放一个带有不同媒体播放器的视频文件.但是我面临的一个问题是,三个人都不能同时播放该视频.其中一两个人停下了显示器.如果我直接使用视频视图而不是Media Player类,但问题仍然存在.请任何人都可以提供帮助.问题是什么?它给错误表面创建失败原生错误.我尝试了不同的组合,例如3个不同视图中的一个文件,三个不同视图中的三个文件,但问题尚未解决.其他网站上的一些回复称它取决于内核版本.如果它取决于内核版本,请你在android网站上给我任何android文档链接,它取决于内核版本.或者可以玩,请给我代码的步骤.这是错误日志 -

04-10 19:23:37.995: E/ANDROID_DRM_TEST(2573): Client::notify In
04-10 19:23:37.995: V/AudioPolicyManager(2573): startOutput() output 1, stream 3,  session 131
04-10 19:23:37.995: V/AudioPolicyManager(2573): getDeviceForStrategy() from cache strategy 0, device 2
04-10 19:23:37.995: V/AudioPolicyManager(2573): getNewDevice() selected device 2
04-10 19:23:37.995: V/AudioPolicyManager(2573): setOutputDevice() output 1 device 2 delayMs 0
04-10 19:23:37.995: V/AudioPolicyManager(2573): setOutputDevice() setting same device 2 or null device for output 1
04-10 19:23:37.995: I/AudioFlinger(2573): start output streamType (0, 3) for 1
04-10 19:23:37.995: D/AudioHardwareYamaha(2573): AudioStreamOut::setParameters(keyValuePairs="start_output_streamtype=3")
04-10 19:23:38.010: W/SEC_Overlay(2689): overlay_setPosition(0) 0,0,200,397 => 0,0,200,397 …
Run Code Online (Sandbox Code Playgroud)

android surfaceview android-ndk android-mediaplayer android-videoview

14
推荐指数
3
解决办法
3万
查看次数

以编程方式截取屏幕截图并不捕获surfaceVIew的内容

我有一个应用程序,我希望能够捕获屏幕截图.布局的背景是surfaceView,它显示后置摄像头的视频.以下代码可以截取屏幕截图,但surfaceView的内容保存为黑色.这是代码:

btn.setOnClickListener(new OnClickListener()
{

public void onClick(View v)
{
    Random num = new Random();
    int nu=num.nextInt(1000);
    Bitmap bmp;
    CamView.setDrawingCacheEnabled(true); 
    CamView.buildDrawingCache(true);
    Bitmap bmp2 = Bitmap.createBitmap(CamView.getDrawingCache()); //Screenshot of the layout
    CamView.setDrawingCacheEnabled(false);

    SurView.setDrawingCacheEnabled(true); 
    SurView.buildDrawingCache(true);
    Bitmap bmp1 = Bitmap.createBitmap(SurView.getDrawingCache()); //Screenshot of the surfaceView
    SurView.setDrawingCacheEnabled(false);

    Bitmap bmOverlay = Bitmap.createBitmap(bmp1.getWidth(), bmp1.getHeight(),bmp1.getConfig());
    Canvas canvas = new Canvas(bmOverlay); //Overlaying the 2 bitmaps
    canvas.drawBitmap(bmp1, 0,0, null);
    canvas.drawBitmap(bmp2, 0,0, null);
    bmp=bmOverlay;

    //saving the file
    ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
    bmp.compress(CompressFormat.JPEG, 100, bos); 
    byte[] bitmapdata = bos.toByteArray();
    ByteArrayInputStream fis = new …
Run Code Online (Sandbox Code Playgroud)

storage camera android screenshot surfaceview

14
推荐指数
1
解决办法
1万
查看次数

视图裁剪超过10.000像素宽度

更新:在带有Android Oreo(8.X)的模拟器上工作。我有可能直接对android源进行更改,因此,如果有人知道我必须更改或更新以使其正常工作的android源中的内容,这也将有所帮助(因此,我实际上并不需要Android 7解决方法(尽管无法进行Android 8更新)。

我在FrameLayout中有一个SurfaceView。SurfaceView通常会显示视频,例如,我实际上是在绘制图像。问题是,如果我将FrameLayout(或SurfaceView)的尺寸设置为宽度大于10.000像素,则会在左侧裁剪。

在Android 7.1.1上进行了测试(在设备和仿真器上:Android TV(1080p)API 25

public class TestActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //add surfaceview
        TestSurfaceView testSurfaceView = new TestSurfaceView(this);
        setContentView(testSurfaceView);

        //resize
        FrameLayout.LayoutParams bgParams = (FrameLayout.LayoutParams) testSurfaceView.getLayoutParams();

        //testcase full hd - working
        bgParams.width = 1920;

        //testcase 2 - working - each segment is 330px as 9900 / 1920 * 64 (default segment width) == 330
        //bgParams.width = 9900;

        //testcase 3 - working
        //bgParams.width = 10000;

        //testcase 4 - not working - …
Run Code Online (Sandbox Code Playgroud)

android surfaceview android-source android-x86 android-7.0-nougat

14
推荐指数
0
解决办法
366
查看次数

旋转Android视频

我的应用程序仅提供纵向模式.在肖像活动中,我有一个全屏VideoView.我想要做的是在横向模式下将VideoView(实际视频,视频缓冲)旋转90度.不允许将活动设置为Lanscape模式.扩展VideoView和画布旋转将不起作用,因为它是SurfaceView而不是实际视图.有没有办法用videoView实现这一目标?

android surfaceview android-videoview

13
推荐指数
2
解决办法
2万
查看次数

仅适用于Android 4.0及以上的色带

在运行Android 4.0或4.0.3的模拟器上,我看到了可怕的色带,我似乎无法摆脱它.在我测试的每个其他Android版本上,渐变看起来很流畅.

我有一个配置为RGBX_8888的SurfaceView,并且渲染画布中不存在条带.如果我通过在渲染结束时叠加噪声模式来手动抖动图像,我可以使渐变再次平滑,但显然代价是我宁愿避免的性能.

因此绑带将在稍后介绍.我只能假设,在4.0+上,我的SurfaceView在被绘制和显示之间的某个点处被量化为较低的位深度,我可以从屏幕截图中看到渐变是一次步进8个值每个通道,建议量化到555(而不是565).

我将以下内容添加到我的Activity onCreate函数中,但它没有任何区别.

getWindow().setFormat(PixelFormat.RGBA_8888);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DITHER);
Run Code Online (Sandbox Code Playgroud)

我也尝试将上面的内容放在onAttachedToWindow()上,但仍然没有变化.

(我相信RGBA_8888无论如何都是2.2及以上版本的默认窗口格式,因此明确设置该格式对4.0+没有影响也就不足为奇了.)

这就留下了一个问题,如果源是8888,目的地是8888,那么引入量化/条带的原因是什么,它为什么只出现在4.0+?

非常令人费解.我想知道是否有人可以放弃一些光线?

android gradient dithering quantization surfaceview

13
推荐指数
1
解决办法
2795
查看次数

Android中SurfaceView和GLSurfaceView的区别

谁能告诉我SurfaceView和GLSurfaceView之间的基本区别是什么?我什么时候应该使用SurfaceView,何时应该使用GLSurfaceView?

我在Stack Overflow上阅读了一些已经回答的问题,但它们并不能满足我的疑问.

任何帮助,将不胜感激.

android opengl-es surfaceview

13
推荐指数
3
解决办法
2万
查看次数