【移動(dòng)應(yīng)用開發(fā)技術(shù)】android中對(duì)截圖事件進(jìn)行監(jiān)聽的原理是什么_第1頁
【移動(dòng)應(yīng)用開發(fā)技術(shù)】android中對(duì)截圖事件進(jìn)行監(jiān)聽的原理是什么_第2頁
【移動(dòng)應(yīng)用開發(fā)技術(shù)】android中對(duì)截圖事件進(jìn)行監(jiān)聽的原理是什么_第3頁
【移動(dòng)應(yīng)用開發(fā)技術(shù)】android中對(duì)截圖事件進(jìn)行監(jiān)聽的原理是什么_第4頁
免費(fèi)預(yù)覽已結(jié)束,剩余1頁可下載查看

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

【移動(dòng)應(yīng)用開發(fā)技術(shù)】android中對(duì)截圖事件進(jìn)行監(jiān)聽的原理是什么

這篇文章給大家介紹android中對(duì)截圖事件進(jìn)行監(jiān)聽的原理是什么,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助。1.監(jiān)聽截屏圖片所在目錄變化(FileObserver)2.監(jiān)聽媒體庫的變化(ContentObserver)

上面兩種方法均不是萬能的,需要結(jié)合使用才能達(dá)到良好的效果,首先看看如何監(jiān)控目錄在android中,我們可以通過FileObserver來監(jiān)聽目錄變化,先來看看如何使用private

static

final

File

DIRECTORY_PICTURES

=

new

File(Environment.getExternalStorageDirectory(),

Environment.DIRECTORY_PICTURES);

private

static

final

File

DIRECTORY_DCIM

=

new

File(Environment.getExternalStorageDirectory(),

Environment.DIRECTORY_DCIM);

if

(manufacturer.equalsIgnoreCase("xiaomi"))

{

DIRECTORY_SCREENSHOT

=

new

File(DIRECTORY_DCIM,

"Screenshots");

}

else

{

DIRECTORY_SCREENSHOT

=

new

File(DIRECTORY_PICTURES,

"Screenshots");

}

FILE_OBSERVER

=

new

FileObserver(DIRECTORY_SCREENSHOT.getPath(),

FileObserver.ALL_EVENTS)

{

@Override

public

void

onEvent(int

event,

String

path)

{

if

(event

==

FileObserver.CREATE)

{

String

newPath

=

new

File(DIRECTORY_SCREENSHOT,

path).getAbsolutePath();

Log.d(TAG,

"path:

"

+

newPath);

}

}

};我們對(duì)指定目錄的指定事件監(jiān)聽即可,當(dāng)事件被觸發(fā)時(shí)onEvent會(huì)回調(diào)。這里我們只關(guān)心目錄中有沒有新的文件生成???:在實(shí)踐中發(fā)現(xiàn),并不是所有手機(jī)都允許如此監(jiān)聽或者說都能收到回調(diào)。有的手機(jī)上面無法收到CREATE事件,但是可以收到其他事件。我還發(fā)現(xiàn),有的時(shí)候收到的事件并沒有在FileObserver中定義,比如32768!下面是Linux中相應(yīng)event對(duì)應(yīng)的含義,32768=IN_IGNORED,但是為什么會(huì)ignore,并不清楚。/lxr/http/source/include/linux/inotify.h?a=m68k#L45還遇到過1073741856(1073741856=0x40000000|0x20,即IN_OPEN|IN_ISDIR)和1073741840(1073741840=0x40000000|0x10,即IN_CLOSE_NOWRITE|IN_ISDIR)???:不同手機(jī),監(jiān)聽的目錄并不一致。小米需要監(jiān)聽Environment.DIRECTORY_DCIM,其他監(jiān)聽Environment.DIRECTORY_PICTURES即可。關(guān)于FileObserver這里再多說兩句,F(xiàn)ileObserver無法進(jìn)行遞歸監(jiān)聽,也就是說,我們監(jiān)聽的文件夾中如果有子文件夾,并且我們想知道其中變化,這種方式是不可行的。需要手動(dòng)對(duì)子文件進(jìn)行操作。另外,當(dāng)我們監(jiān)聽的目錄/文件被刪除后又重新建立了一個(gè)同名的目錄/文件,之前的FileObserver不會(huì)繼續(xù)工作,需要重新設(shè)置監(jiān)聽才行。還要注意,F(xiàn)ileObserver回調(diào)并不在主線程中,而是在FileObserver線程中。鑒于上述原因,我們還要使用方法2,監(jiān)聽媒體庫變化。這個(gè)方法使用ContentObserver即可。private

static

final

ContentObserver

CONTENT_OBSERVER

=

new

ContentObserver(HANDLER)

{

@Override

public

void

onChange(boolean

selfChange,

Uri

uri)

{

//記得先檢查讀文件的權(quán)限

ContentResolver

resolver

=

GeneralInfoHelper.getContext().getContentResolver();

if

(uri.toString().matches(MediaStore.Images.Media.EXTERNAL_CONTENT_URI

+

"(/\\d+)?"))

{

Cursor

cursor

=

resolver.query(uri,

PROJECTION,

null,

null,

MediaStore.MediaColumns.DATE_ADDED

+

"

DESC");

if

(cursor

!=

null

&&

cursor.moveToFirst())

{

//完整路徑

String

newPath

=

cursor.getString(cursor.getColumnIndex(MediaStore.MediaColumns.DATA));

File

file

=

new

File(newPath);

//file.exists()

判斷文件是否存在

}

if

(cursor

!=

null)

{

cursor.close();

}

}

}

};

getContentResolver().registerContentObserver(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,

true,

CONTENT_OBSERVER);坑3:實(shí)踐中發(fā)現(xiàn),并不是所有手機(jī)都是監(jiān)聽相同的Uri,有的帶數(shù)字,有的不帶???:查詢數(shù)據(jù)庫時(shí)記得按MediaStore.MediaColumns.DATE_ADDED字段排序,注意,這個(gè)時(shí)間單位是秒,不是毫秒坑5:即使排了序,你拿到的仍然有可能不是正確的,在魅族E2上面出現(xiàn)了這個(gè)問題。但是當(dāng)我刪除了魅族E2截圖文件夾之后,一切又恢復(fù)正常了……這里我做了一個(gè)簡單的判斷,如何DATE_ADDED和當(dāng)前時(shí)間相差兩秒以內(nèi),那么從數(shù)據(jù)庫查出的這條數(shù)據(jù)我視為有效坑6:當(dāng)用戶刪除了截圖文件夾的時(shí)候,媒體庫此時(shí)會(huì)更新,所以此時(shí)onChange會(huì)收到大量回調(diào),所以這里需要判斷判斷文件是否存在??赡苡腥藭?huì)問,為什么不直接用第二種方法?原因有2,首先從坑5可以看出第二種方法也并非100%有效,其次,這種方法速度很慢,通常會(huì)有2-3秒的延遲。而第一種方法如果有效,通常都會(huì)比后者快很多。好了,障礙基本掃清,下面開始融合兩種方法首先使用成員變量記錄截圖文件路徑private

static

String

sScreenshotPath;當(dāng)方法1或者方法2收到結(jié)果時(shí),用收到的結(jié)果與sScreenshotPath對(duì)比,如果是同一個(gè)文件,那么就無需再次通知了,否則則進(jìn)行通知。邏輯太簡單,代碼就不寫了。但是實(shí)際情況是不會(huì)這么樂觀的???:在實(shí)踐中發(fā)現(xiàn),有的系統(tǒng)不直接保存截圖,而是先生成一個(gè)隱藏文件,比如叫.截圖.jpg,然后再修改文件名(去掉“.”)。這種情況下,我們可能就會(huì)收到兩次用戶截圖事件的回調(diào)(方法1和方法2都可能收到回調(diào)),但實(shí)際用戶只截了一次。這里我做了一個(gè)特殊處理,在判斷是否是同一個(gè)文件時(shí),只判斷文件名,而不去管文件的完整路徑也不管文件是否隱藏(也就是不比較文件名前面的“.”)//僅靠文件名而不是全路徑判斷是否為同一個(gè)截圖文件,因?yàn)橛行┫到y(tǒng)對(duì)截圖有move操作

private

static

boolean

isSameFile(String

newPath)

{

if

(TextUtils.isEmpty(sScreenshotPath))

{

return

false;

}

return

TextUtils.equals(removePrefixDot(new

File(sScreenshotPath).getName()),

removePrefixDot(new

File(newPath).getName()));

}

private

static

String

removePrefixDot(@NonNull

St

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論