經(jīng)過兩天的研究,
思路:投屏到電腦,然后windows窗體截圖。
具體思路是:可以使用投屏軟件,把安卓屏幕投到電腦上,然后根據(jù)句柄,截取windows窗口截圖
于是,我根據(jù)思路,,研究出來了使用python【當(dāng)然如果精通其它語言,不會(huì)python,可以根據(jù)上面的思路自行寫代碼】,寫出了可運(yùn)行的python代碼。
下面是具體方式
一、安裝ADB,SCRCPY。
ADB的安裝就不說了,還需要安卓手機(jī)開發(fā)者設(shè)置:里面打開USB調(diào)試開關(guān)。諸君自行搜索
SCRCPY是github上star最多的開源投屏
scrcpy使用:
下載:https://github.com/Genymobile/scrcpy/releases/tag/v1.25

解壓縮
設(shè)置windows環(huán)境變量->系統(tǒng)變量->path->添加一個(gè)指向解壓縮后的文件夾路徑
打開cmd
命令提示符cmd中輸入 【scrcpy -s 安卓手機(jī)序列號(hào)】
然后scrcpy就會(huì)彈出安卓投屏了
二、python代碼
思路:使用os調(diào)用系統(tǒng)cmd打開安卓投屏,找到安卓投屏窗口句柄,根據(jù)句柄進(jìn)行窗口截圖
使用庫:os庫,win32gui庫,PILLOW庫
os庫是python默認(rèn)庫,不需要安裝
win32gui庫,不能直接pip install win32gui【它不支持python3.9,最多僅支持3.6】
正確install代碼:
pip install -i https://pypi.doubanio.com/simple/ pypiwin32
pillow庫:網(wǎng)上很多教程,自行搜索
三、具體代碼如下:
import time,os,datetime
from PIL import Image
import win32gui, win32ui, win32api, win32con
hwnd_title = dict()#獲取windows窗口句柄+標(biāo)題
def cut_pic_by_filename_XY(filename, x1, y1, x2, y2): # 根據(jù)圖片路徑,打開圖片,并裁剪圖片【從x1,y1到x2,y2】,然后保存裁剪出來的圖片到硬盤
img = Image.open(filename) ## 打開filename文件,并賦值給img
imgSize = img.size # 大小/尺寸
w = img.width # 圖片的寬
h = img.height # 圖片的高
f = img.format # 圖像格式
region = img.crop((x1, y1, x2, y2)) # 裁剪圖片【從x1,y1到x2,y2】
current_date = datetime.datetime.now().strftime('%Y%m%d')#提取日期
save_path_dir = "./image/save_image/" + current_date
if not os.path.exists(save_path_dir):#文件夾不存在,則創(chuàng)建文件夾
os.makedirs(save_path_dir)
str_time = str(int(time.time()))#提取時(shí)間戳
pic_filename = filename.split("/")[-1]#提取路徑中的文件名
region.save(save_path_dir + "/" + str_time + pic_filename) ## 將裁剪下來的圖片保存到 時(shí)間戳+文件名.png
return save_path_dir + "/" + str_time + pic_filename#返回文件路徑
def _get_all_hwnd(hwnd, mouse):
if win32gui.IsWindow(hwnd) and win32gui.IsWindowEnabled(hwnd) and win32gui.IsWindowVisible(hwnd):
hwnd_title.update({hwnd: win32gui.GetWindowText(hwnd)})
def window_capture(filename, hwnd):#窗口截屏
#hwnd = 0 # 窗口的編號(hào),0號(hào)表示當(dāng)前活躍窗口
# 根據(jù)窗口句柄獲取窗口的設(shè)備上下文DC(Divice Context)
hwndDC = win32gui.GetWindowDC(hwnd)
# 根據(jù)窗口的DC獲取mfcDC
mfcDC = win32ui.CreateDCFromHandle(hwndDC)
# mfcDC創(chuàng)建可兼容的DC
saveDC = mfcDC.CreateCompatibleDC()
# 創(chuàng)建bigmap準(zhǔn)備保存圖片
saveBitMap = win32ui.CreateBitmap()
# 獲取監(jiān)控器信息
MoniterDev = win32api.EnumDisplayMonitors(None, None)
w = MoniterDev[0][2][2]
h = MoniterDev[0][2][3]
w2 = 600#設(shè)置截圖的X軸寬度【可根據(jù)截圖保存的文件filename查看,然后實(shí)際調(diào)整】
? ? h2 = 1080#設(shè)置截圖的Y軸高度【可根據(jù)截圖保存的文件filename查看,然后實(shí)際調(diào)整】
# print w,h #圖片大小
# 為bitmap開辟空間
saveBitMap.CreateCompatibleBitmap(mfcDC, w2, h2)
# 高度saveDC,將截圖保存到saveBitmap中
saveDC.SelectObject(saveBitMap)
# 截取從左上角(0,0)長(zhǎng)寬為(w,h)的圖片
saveDC.BitBlt((0, 0), (w2, h2), mfcDC, (0, 0), win32con.SRCCOPY)
saveBitMap.SaveBitmapFile(saveDC, filename)
#上面的截圖尺寸不行,我就自己寫了一個(gè)精確截圖的def,其中x1,y1,x2,y2,諸君自行對(duì)比窗口截圖
backpng = cut_pic_by_filename_XY(filename, 10, 45, 590, 1070)
return backpng
#可以運(yùn)行以下注釋的代碼,獲得手機(jī)的序列號(hào),諸君可自行提取自己的手機(jī)序列號(hào)
#cmdstr = "adb devices"
#backstr = os.popen(cmdstr).read()
#print(backstr)
device_name = "b038bc0b"
device_n = ' -s ' + device_name
#scrcpy --crop設(shè)定屏幕=1080*1920并且偏移坐標(biāo)為 (0,0)
#這里的--crop命令就是老版本的-c命令,新版本升級(jí)了,-c命令是錯(cuò)誤的了。
#然而:網(wǎng)上面的所有有關(guān)scrcpy命令的教程文檔,全部還是-c命令,真雞兒扯淡,害我查半天
#-m 1024 限制畫面分辨率=1024
#-b 4M修改視頻碼率=4M
# --window-x 100 --window-y 200 --window-width 405 --window-height 720設(shè)定窗體起始坐標(biāo),設(shè)置窗體寬和高
win_title = "MY_Test1"
#注意這里是windows窗體標(biāo)題,最好每次打開的windows窗體標(biāo)題不同,否則多個(gè)窗體標(biāo)題一樣的話
#會(huì)出現(xiàn)錯(cuò)誤,找不到句柄
cmdstr = "scrcpy" + device_n + " --crop=1080:1920:0:0 --window-title "
cmdstr = cmdstr + win_title
cmdstr = cmdstr + " -m 1024 -b 4M"
os.popen(cmdstr)#打開scrcpy
time.sleep(3)#等待3秒,等待窗體徹底彈出
win32gui.EnumWindows(_get_all_hwnd, 0)#獲取所有windows窗口句柄
hwnd = 0
for wnd in hwnd_title.items():#循環(huán)獲取所有的windows句柄
print(wnd)#句柄值示例:(325674,"MI 5"):前面是windows句柄ID,后面是windows窗口標(biāo)題
get_win_title = str(wnd[1])
if win_title == get_win_title:#根據(jù)windows窗口標(biāo)題判斷,是不是需要截圖的窗口。
hwnd = wnd[0]
break
print("windows句柄ID:", hwnd)
cut_image_file = './image/scrcpy' + str(device_name) + '.png'
get_png = window_capture(cut_image_file, hwnd)#對(duì)windows窗體進(jìn)行截圖
print(get_png)
#關(guān)閉windows窗體
#win32gui.PostMessage(hwnd, win32con.WM_CLOSE, 0, 0)
如上,可以截屏。
錄屏的話:scrcpy有個(gè)錄屏啟動(dòng)命令,直接使用該命令啟動(dòng)scrcpy,然后操作scrcpy彈出的投屏窗口,scrcpy會(huì)保存操作視頻
scrcpy -s 手機(jī)序列號(hào) --record file.mp4
代碼沒仔細(xì)研究,諸君可自行研究。思路:os用上述代碼,操作cmd打開scrcpy,然后python控制鼠標(biāo)scrcpy彈出的窗口,在該窗口上點(diǎn)擊,滑動(dòng)等等具體的操作,最后看file.mp4
看到有兄弟問了,黑屏的時(shí)候還是黑的,這是因?yàn)樵揂PP使用了FLAG_SECURE,兩個(gè)都禁了【截屏錄屏】和【投屏】.
Android代碼是這樣:
在Activity的onCreate事件中,setFlags【禁止截屏錄屏】注冊(cè)廣播接收器,監(jiān)聽投屏事件【禁止投屏】
import android.app.Activity;
import android.content.Context;
import android.content.IntentFilter;
import android.media.projection.MediaProjectionManager;
import android.os.Bundle;
import android.view.WindowManager;
public class MainActivity extends Activity {
private ScreenCaptureBroadcastReceiver receiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 禁止截屏
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
// 注冊(cè)廣播接收器,監(jiān)聽投屏事件
receiver = new ScreenCaptureBroadcastReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_SCREEN_ON);
intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
registerReceiver(receiver, intentFilter);
}
@Override
protected void onDestroy() {
super.onDestroy();
// 注銷廣播接收器
unregisterReceiver(receiver);
}
// 廣播接收器類,用于監(jiān)聽投屏事件
private class ScreenCaptureBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// 檢測(cè)到投屏事件發(fā)生
if (Intent.ACTION_SCREEN_ON.equals(intent.getAction()) ||
Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) {
// 禁用投屏功能
MediaProjectionManager mediaProjectionManager = (MediaProjectionManager)
getSystemService(Context.MEDIA_PROJECTION_SERVICE);
if (mediaProjectionManager != null) {
mediaProjectionManager.stopScreenCapture();
}
}
}
}
}
如果僅僅禁止截屏錄屏的話,可以用我上文的:投屏到電腦的辦法,可以解決
如果是用MediaProjectionManager監(jiān)聽投屏的話:
MediaProjectionManager是Android提供的一個(gè)類,用于管理屏幕捕捉(Screen Capture)功能。
請(qǐng)注意,使用MediaProjectionManager需要申請(qǐng)android.permission.CAPTURE_VIDEO_OUTPUT權(quán)限,并且只能在Android 5.0(API級(jí)別21)及以上的設(shè)備上使用。此外,屏幕捕捉功能通常在需要進(jìn)行屏幕錄制、屏幕分享等場(chǎng)景下使用,并非所有應(yīng)用都需要使用或禁用該功能。
你可以嘗試把該APP的CAPTURE_VIDEO_OUTPUT權(quán)限關(guān)閉【中文權(quán)限名:捕獲視頻輸出】,有很多手機(jī)找不到該權(quán)限,
不過關(guān)閉權(quán)限也未必管用,
有哪位同學(xué)知道的,可以給個(gè)文章地址,不過這涉及系統(tǒng)權(quán)限的修改,我估計(jì)要root手機(jī),然后裝xposed框架,然而,我對(duì)于xposed框架不熟,有會(huì)的同學(xué),不妨留言。
還有物理辦法:A手機(jī)操作,B手機(jī)在旁打開相機(jī)錄制。文章來源:http://www.zghlxwxcb.cn/news/detail-402301.html
諸君自行研究吧。文章來源地址http://www.zghlxwxcb.cn/news/detail-402301.html
到了這里,關(guān)于安卓APP限制截屏錄屏解決方案的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!