Android 截屏方式

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 截屏方式相关的知识,希望对你有一定的参考价值。

参考技术A 两种方案:

android 在5.0 之后支持了实时录屏的功能。通过实时录屏我们可以拿到截屏的图像。同时可以通过在Service中处理实现后台的录屏。具体的类讲解大家自行网上查阅。
大体步骤:

1.初始化一个MediaProjectionManager

2.创建intent,并启动Intent。注意这里是startActivityForResult

3.在onActivityResult中拿到Mediaprojection

4.设置VirtualDisplay 将图像和展示的View关联起来。一般来说我们会将图像展示到SurfaceView,这里为了为了便于拿到截图,我们使用ImageReader,他内置有SurfaceView。

5.通过ImageReader拿到截图

6.注意截屏之后要及时关闭VirtualDisplay ,因为VirtualDisplay 是十分消耗内存和电量的。

截取长屏其实原理就是截取整个ScrollView或者ListView的视图,因此实现原理跟上面中提到的截取某个控件的View基本一致。

可参考2中Android 在5.0的做法,进行实时录制。

原文地址

Android以编程方式截屏

【中文标题】Android以编程方式截屏【英文标题】:Android take screen shot programmatically 【发布时间】:2011-12-07 10:31:27 【问题描述】:

首先我正在编写一个根应用程序,因此根权限没有问题。我已经搜索和搜索,发现很多对我来说从来没有用过的代码是我迄今为止拼凑起来的,并且有点工作。当我说 sorta 时,我的意思是它在我的 /sdcard/test.png 上制作了一张图片,但是该文件为 0 字节,显然无法查看。

public class ScreenShot extends Activity

View content;

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.blank);
    content = findViewById(R.id.blankview);
    getScreen();


private void getScreen()
    Bitmap bitmap = content.getDrawingCache();
    File file = new File("/sdcard/test.png");
    try 
    
        file.createNewFile();
        FileOutputStream ostream = new FileOutputStream(file);
        bitmap.compress(CompressFormat.PNG, 100, ostream);
        ostream.close();
     
    catch (Exception e) 
    
        e.printStackTrace();
    


任何关于我如何通过代码在 android 中截屏的帮助将不胜感激,谢谢!

===编辑===

以下是我正在使用的所有内容图像是在我的 sdcard 上制作的,不再是 0bytes,但整个东西都是黑色的,上面什么都没有。我已经将活动绑定到我的搜索按钮,所以当我在手机上的某个位置时,我长按搜索,它应该拍摄屏幕截图,但我只是得到一个黑色图像?一切都设置为透明,所以我认为它应该抓住屏幕上的任何东西,但我只是不断变黑

清单

<activity android:name=".extras.ScreenShot"
    android:theme="@android:style/Theme.Translucent.NoTitleBar"
    android:noHistory="true" >
    <intent-filter>
        <action android:name="android.intent.action.SEARCH_LONG_PRESS" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
    </activity>

XML

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_
  android:layout_
  android:background="#00000000"
  android:id="@+id/screenRoot">    
</LinearLayout>

截图类

public class ScreenShot extends Activity

View content;

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.screenshot);
    content = findViewById(R.id.screenRoot);
    ViewTreeObserver vto = content.getViewTreeObserver();
    vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() 
      @Override
      public void onGlobalLayout() 
        content.getViewTreeObserver().removeGlobalOnLayoutListener(this);
        getScreen();
      
    );


private void getScreen()
    View view = content;
    View v = view.getRootView();
    v.setDrawingCacheEnabled(true);
    Bitmap b = v.getDrawingCache();             
    String extr = Environment.getExternalStorageDirectory().toString();
    File myPath = new File(extr, "test.jpg");
    FileOutputStream fos = null;
    try 
        fos = new FileOutputStream(myPath);
        b.compress(Bitmap.CompressFormat.JPEG, 100, fos);
        fos.flush();
        fos.close();
        MediaStore.Images.Media.insertImage(getContentResolver(), b, "Screen", "screen");
    catch (FileNotFoundException e) 
        // TODO Auto-generated catch block
        e.printStackTrace();
     catch (Exception e) 
        // TODO Auto-generated catch block
        e.printStackTrace();
    
    finish();


【问题讨论】:

【参考方案1】:

给你...我用这个:

View v = view.getRootView();
v.setDrawingCacheEnabled(true);
Bitmap b = v.getDrawingCache();
String extr = Environment.getExternalStorageDirectory().toString();
File myPath = new File(extr, getString(R.string.free_tiket)+".jpg");
FileOutputStream fos = null;
try 
    fos = new FileOutputStream(myPath);
    b.compress(Bitmap.CompressFormat.JPEG, 100, fos);
    fos.flush();
    fos.close();
    MediaStore.Images.Media.insertImage( getContentResolver(), b, 
                                         "Screen", "screen");
 catch (FileNotFoundException e) 
    // TODO Auto-generated catch block
    e.printStackTrace();
 catch (Exception e) 
    // TODO Auto-generated catch block
    e.printStackTrace();

v iz 根布局...只是指出 ;)))

【讨论】:

什么是视图??我正在使用您的代码,但出现无法解析视图的错误。那么什么是视图? View 是 LinearLayout...您必须将 id 添加到您的线性或相对布局(您使用的)中,并在 onCreate 中这样定义它: View view= findViewById(R.id.linearLayoutRoot);然后你使用我的其余代码...... 好的,谢谢。我得到了它。而且效果很好。但如果可以的话,我需要你的帮助。 实际上我正在拍摄屏幕上显示的相机预览的屏幕截图。该视图上还有一些可用的按钮。现在,当我拍摄屏幕截图时,该布局被捕获,但我无法拍摄该相机显示的快照。为什么会这样??? 你有什么想法来实现它吗?【参考方案2】:

对于这个问题的下一位读者-

将视图绘制到画布上的非常简单的方法-

将您的主要布局引用传递给此方法-

 Bitmap file = save(layout);

 Bitmap save(View v)
   
    Bitmap b = Bitmap.createBitmap(v.getWidth(), v.getHeight(), Bitmap.Config.ARGB_8888);
    Canvas c = new Canvas(b);
    v.draw(c);
    return b;
   

【讨论】:

非常好,这是更新,但其他方式现金形象很糟糕【参考方案3】:

我认为您必须等到完全绘制布局..使用 ViewTreeObserver 在完全绘制布局时获取回调..

在您的 onCreate 添加此代码..仅从 onGlobalLayout() 内部调用 getScreen..

ViewTreeObserver vto = content.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() 
  @Override
  public void onGlobalLayout() 
    content.getViewTreeObserver().removeGlobalOnLayoutListener(this);
    getScreen();
  
);

我曾经问过一个有点类似的question..请参阅我的问题,它解释了在 android 中截屏的方式..希望这会有所帮助

【讨论】:

k 感谢您的回答,明天看看您的问题,现在太累了。我确实还有另一个问题,但是当我这样做时为什么不调用 root ?并且此代码是否只是对布局进行屏幕截图只是因为我想基本上对屏幕上的内容进行屏幕截图我长按时将其绑定到搜索键 好的。它工作正常。但是,如果我使用该代码截取相机视图的屏幕截图,那么它将无法正常工作。【参考方案4】:
public class MainActivity extends Activity

Button btn;

@Override
protected void onCreate(Bundle savedInstanceState)

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    btn = (Button) findViewById(R.id.btn);
    btn.setOnClickListener(new OnClickListener()
    

        @Override
        public void onClick(View v)
        
            // TODO Auto-generated method stub
            Bitmap bitmap = takeScreenshot();
            saveBitmap(bitmap);

        
    );


public Bitmap takeScreenshot()

    View rootView = findViewById(android.R.id.content).getRootView();
    rootView.setDrawingCacheEnabled(true);
    return rootView.getDrawingCache();


public void saveBitmap(Bitmap bitmap)

    File imagePath = new File(Environment.getExternalStorageDirectory() + "/screenshot.png");
    FileOutputStream fos;
    try
    
        fos = new FileOutputStream(imagePath);
        bitmap.compress(CompressFormat.JPEG, 100, fos);
        fos.flush();
        fos.close();
    
    catch (FileNotFoundException e)
    
        Log.e("GREC", e.getMessage(), e);
    
    catch (IOException e)
    
        Log.e("GREC", e.getMessage(), e);
    


别忘了给外部存储写权限!

【讨论】:

【参考方案5】:

你这样截屏…………

View view =  findViewById(R.id.rellayout);
        view.getRootView();
        String state = Environment.getExternalStorageState();
        if (Environment.MEDIA_MOUNTED.equals(state)) 
        
            File picDir  = new File(Environment.getExternalStorageDirectory()+ "/name");
            if (!picDir.exists())
            
                picDir.mkdir();
            
            view.setDrawingCacheEnabled(true);
            view.buildDrawingCache(true);
            Bitmap bitmap = view.getDrawingCache();
//          Date date = new Date();
            String fileName = "mylove" + ".jpg";
            File picFile = new File(picDir + "/" + fileName);
            try 
            
                picFile.createNewFile();
                FileOutputStream picOut = new FileOutputStream(picFile);
                bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), (int)(bitmap.getHeight()/1.2));//Optional
                boolean saved = bitmap.compress(CompressFormat.JPEG, 100, picOut);
                if (saved) 
                
                    Toast.makeText(getApplicationContext(), "Image saved to your device Pictures "+ "directory!", Toast.LENGTH_SHORT).show();
                 else 
                
                    //Error
                
                picOut.close();
             
            catch (Exception e) 
            
                e.printStackTrace();
            
            view.destroyDrawingCache();
         else 


        

【讨论】:

以上是关于Android 截屏方式的主要内容,如果未能解决你的问题,请参考以下文章

如何以编程方式在 Android 上截屏?

当相机在Android中的表面视图上以编程方式截屏

Android以编程方式截屏

Android监听截屏

Android 截屏的三种方法

求教怎么在android下实现截取任一屏幕,也就是拷屏!!!