android-實現手機截圖效果,儲存截圖圖片
一、準備一張圖片
拷貝screenshot_panel.9.png放在目錄drawable-xhdpi下
二、activity_main.xml
程式碼如下:
三、新建xml檔案<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello_world" /> <Button android:id="@+id/main_btn" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Shot" android:layout_alignParentBottom="true"/> </RelativeLayout>
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:id="@+id/global_screenshot_background" android:layout_width="match_parent" android:layout_height="match_parent" android:src="@android:color/black" android:visibility="gone" /> <ImageView android:id="@+id/global_screenshot" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:background="@drawable/screenshot_panel" android:visibility="gone" android:adjustViewBounds="true" /> <ImageView android:id="@+id/global_screenshot_flash" android:layout_width="match_parent" android:layout_height="match_parent" android:src="@android:color/white" android:visibility="gone" /> </FrameLayout>
四、在dimens.xml新增一項
<dimen name="global_screenshot_bg_padding">20dp</dimen>
五、後臺程式碼
1)SurfaceControl.java
import android.graphics.Bitmap; import android.view.View; public class SurfaceControl { public static Bitmap screenshot(View view) { view.setDrawingCacheEnabled(true); view.buildDrawingCache(); Bitmap bmp = view.getDrawingCache(); return bmp; } }
2)GlobalScreenShot.java程式碼如下,其中SavePicture方法有儲存截圖的路徑
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.PointF;
import android.media.MediaActionSound;
import android.net.Uri;
import android.os.Environment;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.animation.Interpolator;
import android.widget.ImageView;
import android.widget.Toast;
/**
* POD used in the AsyncTask which saves an image in the background.
*/
class SaveImageInBackgroundData {
Context context;
Bitmap image;
Uri imageUri;
Runnable finisher;
int iconSize;
int result;
void clearImage() {
image = null;
imageUri = null;
iconSize = 0;
}
void clearContext() {
context = null;
}
}
/**
* TODO:
* - Performance when over gl surfaces? Ie. Gallery
* - what do we say in the Toast? Which icon do we get if the user uses another
* type of gallery?
*/
class GlobalScreenshot {
private static final String TAG = "GlobalScreenshot";
private static final int SCREENSHOT_FLASH_TO_PEAK_DURATION = 130;
private static final int SCREENSHOT_DROP_IN_DURATION = 430;
private static final int SCREENSHOT_DROP_OUT_DELAY = 500;
private static final int SCREENSHOT_DROP_OUT_DURATION = 430;
private static final int SCREENSHOT_DROP_OUT_SCALE_DURATION = 370;
private static final int SCREENSHOT_FAST_DROP_OUT_DURATION = 320;
private static final float BACKGROUND_ALPHA = 0.5f;
private static final float SCREENSHOT_SCALE = 1f;
private static final float SCREENSHOT_DROP_IN_MIN_SCALE = SCREENSHOT_SCALE * 0.725f;
private static final float SCREENSHOT_DROP_OUT_MIN_SCALE = SCREENSHOT_SCALE * 0.45f;
private static final float SCREENSHOT_FAST_DROP_OUT_MIN_SCALE = SCREENSHOT_SCALE * 0.6f;
private static final float SCREENSHOT_DROP_OUT_MIN_SCALE_OFFSET = 0f;
private Context mContext;
private WindowManager mWindowManager;
private WindowManager.LayoutParams mWindowLayoutParams;
private Display mDisplay;
private DisplayMetrics mDisplayMetrics;
private Bitmap mScreenBitmap;
private View mScreenshotLayout;
private ImageView mBackgroundView;
private ImageView mScreenshotView;
private ImageView mScreenshotFlash;
private AnimatorSet mScreenshotAnimation;
private float mBgPadding;
private float mBgPaddingScale;
private MediaActionSound mCameraSound;
/**
* @param context everything needs a context :(
*/
public GlobalScreenshot(Context context) {
Resources r = context.getResources();
mContext = context;
LayoutInflater layoutInflater = (LayoutInflater)
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// Inflate the screenshot layout
mScreenshotLayout = layoutInflater.inflate(R.layout.global_screenshot, null);
mBackgroundView = (ImageView) mScreenshotLayout.findViewById(R.id.global_screenshot_background);
mScreenshotView = (ImageView) mScreenshotLayout.findViewById(R.id.global_screenshot);
mScreenshotFlash = (ImageView) mScreenshotLayout.findViewById(R.id.global_screenshot_flash);
mScreenshotLayout.setFocusable(true);
mScreenshotLayout.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// Intercept and ignore all touch events
return true;
}
});
// Setup the window that we are going to use
mWindowLayoutParams = new WindowManager.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, 0, 0,
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
WindowManager.LayoutParams.FLAG_FULLSCREEN
| WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED,
PixelFormat.TRANSLUCENT);
mWindowLayoutParams.setTitle("ScreenshotAnimation");
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
mDisplay = mWindowManager.getDefaultDisplay();
mDisplayMetrics = new DisplayMetrics();
mDisplay.getRealMetrics(mDisplayMetrics);
// Scale has to account for both sides of the bg
mBgPadding = (float) r.getDimensionPixelSize(R.dimen.global_screenshot_bg_padding);
mBgPaddingScale = mBgPadding / mDisplayMetrics.widthPixels;
// Setup the Camera shutter sound
mCameraSound = new MediaActionSound();
mCameraSound.load(MediaActionSound.SHUTTER_CLICK);
}
/**
* Takes a screenshot of the current display and shows an animation.
*/
void takeScreenshot(View view, Runnable finisher, boolean statusBarVisible, boolean navBarVisible) {
// Take the screenshot
Log.d("debug","takeScreenshot start");
mScreenBitmap = SurfaceControl.screenshot(view);
Log.d("debug","takeScreenshot 1");
if (mScreenBitmap == null) {
notifyScreenshotError(mContext);
finisher.run();
return;
}
// Optimizations
mScreenBitmap.setHasAlpha(false);
mScreenBitmap.prepareToDraw();
Log.d("debug","takeScreenshot 2");
Log.d("debug","takeScreenshot 3");
// Start the post-screenshot animation
startAnimation(finisher, mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels,
statusBarVisible, navBarVisible);
Log.d("debug","takeScreenshot end");
}
private void SavePicture(){
Log.d("debug","SavePicture 1");
mScreenshotView.setDrawingCacheEnabled(true);
Log.d("debug","SavePicture 2");
Bitmap obmp = Bitmap.createBitmap(mScreenshotView.getDrawingCache());
Log.d("debug","SavePicture 3");
if (obmp != null) {
// 圖片儲存路徑
String SavePath = getSDCardPath() + "/test/ScreenImages";
// 儲存Bitmap
Log.d("debug","SavePath = "+SavePath);
try {
File path = new File(SavePath);
// 檔案
String filepath = SavePath + "/Screen_1.png";
Log.d("debug","filepath = "+filepath);
File file = new File(filepath);
if (!path.exists()) {
Log.d("debug","path is not exists");
path.mkdirs();
}
if (!file.exists()) {
Log.d("debug","file create new ");
file.createNewFile();
}
FileOutputStream fos = null;
fos = new FileOutputStream(file);
if (null != fos) {
obmp.compress(Bitmap.CompressFormat.PNG, 90, fos);
fos.flush();
fos.close();
Log.d("debug","save ok");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 獲取SDCard的目錄路徑功能
*
* @return
*/
private String getSDCardPath() {
File sdcardDir = null;
// 判斷SDCard是否存在
boolean sdcardExist = Environment.getExternalStorageState().equals(
android.os.Environment.MEDIA_MOUNTED);
if (sdcardExist) {
sdcardDir = Environment.getExternalStorageDirectory();
}
return sdcardDir.toString();
}
/**
* Starts the animation after taking the screenshot
*/
private void startAnimation(final Runnable finisher, int w, int h, boolean statusBarVisible,
boolean navBarVisible) {
// Add the view for the animation
mScreenshotView.setImageBitmap(mScreenBitmap);
mScreenshotLayout.requestFocus();
// Setup the animation with the screenshot just taken
if (mScreenshotAnimation != null) {
mScreenshotAnimation.end();
mScreenshotAnimation.removeAllListeners();
}
mWindowManager.addView(mScreenshotLayout, mWindowLayoutParams);
ValueAnimator screenshotDropInAnim = createScreenshotDropInAnimation();
ValueAnimator screenshotFadeOutAnim = createScreenshotDropOutAnimation(w, h,
statusBarVisible, navBarVisible);
mScreenshotAnimation = new AnimatorSet();
mScreenshotAnimation.playSequentially(screenshotDropInAnim, screenshotFadeOutAnim);
mScreenshotAnimation.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
// Save the screenshot once we have a bit of time now
saveScreenshotInWorkerThread(finisher);
mWindowManager.removeView(mScreenshotLayout);
SavePicture();
// Clear any references to the bitmap
mScreenBitmap = null;
mScreenshotView.setImageBitmap(null);
}
});
mScreenshotLayout.post(new Runnable() {
@Override
public void run() {
// Play the shutter sound to notify that we've taken a screenshot
mCameraSound.play(MediaActionSound.SHUTTER_CLICK);
mScreenshotView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
mScreenshotView.buildLayer();
mScreenshotAnimation.start();
}
});
}
private ValueAnimator createScreenshotDropInAnimation() {
final float flashPeakDurationPct = ((float) (SCREENSHOT_FLASH_TO_PEAK_DURATION)
/ SCREENSHOT_DROP_IN_DURATION);
final float flashDurationPct = 2f * flashPeakDurationPct;
final Interpolator flashAlphaInterpolator = new Interpolator() {
@Override
public float getInterpolation(float x) {
// Flash the flash view in and out quickly
if (x <= flashDurationPct) {
return (float) Math.sin(Math.PI * (x / flashDurationPct));
}
return 0;
}
};
final Interpolator scaleInterpolator = new Interpolator() {
@Override
public float getInterpolation(float x) {
// We start scaling when the flash is at it's peak
if (x < flashPeakDurationPct) {
return 0;
}
return (x - flashDurationPct) / (1f - flashDurationPct);
}
};
ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
anim.setDuration(SCREENSHOT_DROP_IN_DURATION);
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
mBackgroundView.setAlpha(0f);
mBackgroundView.setVisibility(View.VISIBLE);
mScreenshotView.setAlpha(0f);
mScreenshotView.setTranslationX(0f);
mScreenshotView.setTranslationY(0f);
mScreenshotView.setScaleX(SCREENSHOT_SCALE + mBgPaddingScale);
mScreenshotView.setScaleY(SCREENSHOT_SCALE + mBgPaddingScale);
mScreenshotView.setVisibility(View.VISIBLE);
mScreenshotFlash.setAlpha(0f);
mScreenshotFlash.setVisibility(View.VISIBLE);
}
@Override
public void onAnimationEnd(android.animation.Animator animation) {
mScreenshotFlash.setVisibility(View.GONE);
}
});
anim.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float t = (Float) animation.getAnimatedValue();
float scaleT = (SCREENSHOT_SCALE + mBgPaddingScale)
- scaleInterpolator.getInterpolation(t)
* (SCREENSHOT_SCALE - SCREENSHOT_DROP_IN_MIN_SCALE);
mBackgroundView.setAlpha(scaleInterpolator.getInterpolation(t) * BACKGROUND_ALPHA);
mScreenshotView.setAlpha(t);
mScreenshotView.setScaleX(scaleT);
mScreenshotView.setScaleY(scaleT);
mScreenshotFlash.setAlpha(flashAlphaInterpolator.getInterpolation(t));
}
});
return anim;
}
private ValueAnimator createScreenshotDropOutAnimation(int w, int h, boolean statusBarVisible,
boolean navBarVisible) {
ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
anim.setStartDelay(SCREENSHOT_DROP_OUT_DELAY);
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mBackgroundView.setVisibility(View.GONE);
mScreenshotView.setVisibility(View.GONE);
mScreenshotView.setLayerType(View.LAYER_TYPE_NONE, null);
}
});
if (!statusBarVisible || !navBarVisible) {
// There is no status bar/nav bar, so just fade the screenshot away in place
anim.setDuration(SCREENSHOT_FAST_DROP_OUT_DURATION);
anim.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float t = (Float) animation.getAnimatedValue();
float scaleT = (SCREENSHOT_DROP_IN_MIN_SCALE + mBgPaddingScale)
- t * (SCREENSHOT_DROP_IN_MIN_SCALE - SCREENSHOT_FAST_DROP_OUT_MIN_SCALE);
mBackgroundView.setAlpha((1f - t) * BACKGROUND_ALPHA);
mScreenshotView.setAlpha(1f - t);
mScreenshotView.setScaleX(scaleT);
mScreenshotView.setScaleY(scaleT);
}
});
} else {
// In the case where there is a status bar, animate to the origin of the bar (top-left)
final float scaleDurationPct = (float) SCREENSHOT_DROP_OUT_SCALE_DURATION
/ SCREENSHOT_DROP_OUT_DURATION;
final Interpolator scaleInterpolator = new Interpolator() {
@Override
public float getInterpolation(float x) {
if (x < scaleDurationPct) {
// Decelerate, and scale the input accordingly
return (float) (1f - Math.pow(1f - (x / scaleDurationPct), 2f));
}
return 1f;
}
};
// Determine the bounds of how to scale
float halfScreenWidth = (w - 2f * mBgPadding) / 2f;
float halfScreenHeight = (h - 2f * mBgPadding) / 2f;
final float offsetPct = SCREENSHOT_DROP_OUT_MIN_SCALE_OFFSET;
final PointF finalPos = new PointF(
-halfScreenWidth + (SCREENSHOT_DROP_OUT_MIN_SCALE + offsetPct) * halfScreenWidth,
-halfScreenHeight + (SCREENSHOT_DROP_OUT_MIN_SCALE + offsetPct) * halfScreenHeight);
// Animate the screenshot to the status bar
anim.setDuration(SCREENSHOT_DROP_OUT_DURATION);
anim.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float t = (Float) animation.getAnimatedValue();
float scaleT = (SCREENSHOT_DROP_IN_MIN_SCALE + mBgPaddingScale)
- scaleInterpolator.getInterpolation(t)
* (SCREENSHOT_DROP_IN_MIN_SCALE - SCREENSHOT_DROP_OUT_MIN_SCALE);
mBackgroundView.setAlpha((1f - t) * BACKGROUND_ALPHA);
mScreenshotView.setAlpha(1f - scaleInterpolator.getInterpolation(t));
mScreenshotView.setScaleX(scaleT);
mScreenshotView.setScaleY(scaleT);
mScreenshotView.setTranslationX(t * finalPos.x);
mScreenshotView.setTranslationY(t * finalPos.y);
}
});
}
return anim;
}
private void notifyScreenshotError(Context context) {
}
private void saveScreenshotInWorkerThread(Runnable runnable) {
}
}
3)在MainActivity.java呼叫
mport android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final GlobalScreenshot screenshot = new GlobalScreenshot(this);
findViewById(R.id.main_btn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
screenshot.takeScreenshot(getWindow().getDecorView(), new Runnable() {
@Override
public void run() {
}
}, true, true);
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
六、AndroidManifest.xml設定許可權
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"></uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
相關推薦
android-實現手機截圖效果,儲存截圖圖片
一、準備一張圖片 拷貝screenshot_panel.9.png放在目錄drawable-xhdpi下 二、activity_main.xml 程式碼如下: <RelativeLayout xmlns:android="http://schemas.andro
android實現自定義相機效果
樓主在進行android開發時用到了自定義攝像頭拍照並將所拍攝的照片轉化成二進位制流輸出這一功能(當然程式裡也附帶將圖片儲存在sd卡里的功能),花了好多天的時間查了很多資料最後終於把它給搞出來了。。。 來~~~直接上圖~~~ 首先先搞出界面佈局來 <?xml version=
Android 實現ListView不可滾動效果
希望得到的效果是ListView不能滾動,但是最大的問題在與ListView Item還必有點選事件,如果不需要點選事件那就簡單了,直接設定ListView.setEnable(false); 如果還需要點選事件,滾動與點選都是在ListView Touc
Android 實現視覺化動態音訊柱狀圖
public class FFTActivity extends Activity implements OnClickListener{ private Button button; private ImageView imageView; private int frequency = 8000;
OpenVPN For Android實現手機刷Twitter
筆者有時候也會刷刷Twitter,或者上Facebook吹吹牛逼,目前的Android對於VPN支援實在是渣渣,用了很多免費的VPN方案都讓人慾哭無淚。於是有了自己弄一套VPN的想法,以實現筆者刷刷Twitter,吹吹牛逼的夢想! 基本配置: 1
Android 實現控制元件懸浮效果
隨著移動網際網路的快速發展,它已經和我們的生活息息相關了,在公交地鐵裡面都能看到很多人的人低頭看著自己的手機螢幕,從此“低頭族”一詞就產生了,作為一名移動行業的開發人員,我自己也是一名“低頭族”,上下班時間在公交地鐵上看看新聞來打發下時間,有時候也會看看那些受歡迎
Android實現省市區三級聯動效果Spinner
public class MainActivity extends AppCompatActivity { Spinner s_sheng; ArrayAdapter<String> adapter_sheng; ArrayAdapter<String> ada
關於Android實現TextView跑馬燈效果
在xml屬性中設定 <TextView android:width="wrap_content" android:height="wrap_content" android:singleLine="true" andr
android 實現手機方向識別
//自定義導航圖示 private BitmapDescriptor mIconLocation; //自定義感測器implements SensorEventListener private MyOrientationListener myOrientat
Android 實現ListView的彈性效果
關於在Android中實現ListView的彈性效果,有很多不同的方法,網上一搜,也有很多,下面貼出在專案中經常用到的兩種實現ListView彈性效果的方法(基本上拿來就可以用),供大家參考: 第一種比較簡單,好容易理解,只是動態改變了ListView在
Android實現刮刮卡效果
今天看到一個關於刮刮卡的庫,經過測試,感覺還不錯,使用方法也比較簡單,在這裡分享一下。 1.xml佈局:<?xml version="1.0" encoding="utf-8
Android 實現 遮罩動畫效果
為了實現遮罩效果動畫。android本身沒有提供api ,需要自己動手實現。 將view和view的parentLy進行相反方向動畫即可實現該效果: AnimatorSet animatorSet
Android實現列表抽屜展示效果
終於迎來的週末哇,深圳兩天的涼雨天終於迎來晴日。早上爬起來異常的累,哎。。每天地鐵兩小時真是強身健體啊~ 今天給大家帶來一篇關於Android UI的文章:列表Item抽屜展示效果。單說沒意思,不然大家又該說我是標題黨了。我來筆墨描述下場景: 例如當我們點選某個Item項時
android實現LED發光字效果實戰
大家好,這一篇部落格來教大家一個類似於LED鬧鐘顯示屏樣式的小案例,UI比較美觀,文末會提供下載相關資源地址供大家下載,首先我們來看一看這個案例的執行效果。 正常執行在手機中時,效果很流暢,gif上可能是由於錄製完轉碼的時候,速度調快了,所以看上去速度
圖、圖的儲存、圖的遍歷
圖(Graph)是由頂點的有窮非空集合和頂點之間的邊組成。G(V,E) V表示頂點的集合,E表示邊的集合。 在無向圖中,邊可以表示為E1={(A,D),(B,C)} 在有向圖中,頂點v1和v2的有向邊稱為弧。表示為<v1,v2> v1稱為弧尾,v2稱為弧頂。 在無向圖中,如果任意邊兩個頂點都
純C++程式碼實現將畫素矩陣儲存為bmp圖片
用C++程式碼將畫素矩陣儲存為圖片,這裡以讀取yuv序列視訊幀為例進行分析,假設4:2:0yuv序列有300幀,則首先需要將每一視訊幀儲存在一個畫素矩陣中,然後將每一個矩陣儲存為圖片,最終會有300個bmp圖片。 純C++程式碼如下: s
Android實現截圖,將截圖檔案儲存到本地資料夾
Android實現對當前介面截圖,並將截圖檔案存放至本地資料夾 首先需要動態申請兩項許可權(Android6.0後危險許可權之類的都需要動態申請),在AndroidManifest.xml中靜態新增 <uses-permission android:name="android.perm
Android實現View截圖並儲存到相簿
Android實現View截圖並儲存到相簿 一、目標 1. 效果圖 2. 下載地址 二、需求設計 三、準備工作 1. 實現View截圖 2. 儲存Bitmap到檔案
7、實現指令碼執行失敗 時自動截圖並儲存出錯資訊到檔案中
自動化指令碼如果失敗了,憑藉什麼去快速定位呢?當然是截圖和出錯資訊了,這裡就來實現這兩個功能。 方法是重寫TestListenerAdapter中的onTestFailure和onTestSkipped方法,在方法中新增截圖和儲存出錯資訊到文字的方法。 新建一個webtestListener.j
Unity iOS截圖並儲存到手機相簿總結
unity截圖方法 using System.Runtime.InteropServices; using UnityEngine; using UnityEngine.UI; public class Screenshots : MonoBehaviour {