最近看到個一個透明壁紙的應(yīng)用,感覺很好玩,所以就想弄弄。
完整代碼已經(jīng)傳到github上,地址是https://github.com/SZJing/Screen
應(yīng)用下載地址https://pan.baidu.com/s/1smhfByP
? ? 其實他的思路很簡單,就是打開手機攝像頭的預(yù)覽,讓這個預(yù)覽作為壁紙。因為一直打開這攝像頭,所以又耗費資源又耗電。因此這個應(yīng)用的實際用處并不大,只是比較新奇,做來玩玩的。
這個應(yīng)用好像最初是在Google Play上的,而且下載量很高。有興趣的可以看看。
? ? ?接下來就是代碼了,我也是看著別人的代碼做的,有些甚至是直接copy的,但是我在原來的基礎(chǔ)上又增加了雙擊拍照的功能,感覺有點類似偷拍的功能了。但是偷拍被打,概不負責(zé)。
首先是AndroidMainfest.xml文件
<service
? ? android:name=".MyService"
? ? android:enabled="true"
? ? android:exported="true"
? ? android:label="@string/app_name"
? ? android:permission="android.permission.BIND_WALLPAPER">
<intent-filter>
<action android:name="android.service.wallpaper.WallpaperService"/>
</intent-filer/>
<meta-data
? ? ? ? android:name="android.service.wallpaper"
? ? ? ? android:resource="@xml/livewallpaper" />
</service>
最后的xml/livewallpape文件是要自己在res目錄下新建一個相應(yīng)的xml文件,里面配置的是圖標,具體可以看源碼。
這是要申請的權(quán)限,不過要注意照相機和內(nèi)存讀取要進行運行時權(quán)限的設(shè)置,否則程序不能使用。當(dāng)然這是6.0之后才有的。
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.SET_WALLPAPER"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
接下來就是service的代碼部分了
public class MyService extends WallpaperService {
? ? public MyService() {
? ? }
? ? @Override
? ? public Engine onCreateEngine() {
? ? ? ? return new CameraEngine();
? ? }
? ? class CameraEngine extends Engine implements android.hardware.Camera.PreviewCallback{
? ? ? ? ? ? private Camera camera;
? ? ? ? private int count = 0;
? ? ? ? private long firClick = 0;
? ? ? ? private long secClick = 0;
? ? ? ? private final int interval = 500;
? ? ? ? @Override
? ? ? ? public void onCreate(SurfaceHolder surfaceHolder){
? ? ? ? ? ? super.onCreate(surfaceHolder);
? ? ? ? ? ? startPreview();
? ? ? ? ? ? setTouchEventsEnabled(true);
? ? ? ? }
? ? ? ? @Override
? ? ? ? public void onTouchEvent(MotionEvent event) {
? ? ? ? ? ? super.onTouchEvent(event);
? ? ? ? ? ? if (event.getAction() == MotionEvent.ACTION_DOWN){
? ? ? ? ? ? ? ? count++;
? ? ? ? ? ? ? ? if (1 == count){
? ? ? ? ? ? ? ? ? ? firClick = System.currentTimeMillis();
? ? ? ? ? ? ? ? }else if (2 == count){
? ? ? ? ? ? ? ? ? ? secClick = System.currentTimeMillis();
? ? ? ? ? ? ? ? ? ? if (secClick? - firClick
? ? ? ? ? ? ? ? ? ? ? ? camera.autoFocus(new Camera.AutoFocusCallback() {
? ? ? ? ? ? ? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? ? ? ? ? ? ? public void onAutoFocus(boolean success, Camera camera) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? camera.takePicture(null,null,mPicture);
? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? });
? ? ? ? ? ? ? ? ? ? }else {
? ? ? ? ? ? ? ? ? ? ? ? firClick = secClick;
? ? ? ? ? ? ? ? ? ? ? ? count = 1;
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? secClick = 0;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? // 時間處理:點擊拍照,長按拍照
? ? ? ? }
? ? ? ? private Camera.PictureCallback mPicture = new Camera.PictureCallback() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void onPictureTaken(byte[] data, Camera camera) {
? ? ? ? ? ? ? ? File pictureFile = new File(Environment.getExternalStorageDirectory(),System.currentTimeMillis()+".jpg");
? ? ? ? ? ? ? ? try{
? ? ? ? ? ? ? ? ? ? FileOutputStream fos = new FileOutputStream(pictureFile);
? ? ? ? ? ? ? ? ? ? fos.write(data);
? ? ? ? ? ? ? ? ? ? fos.close();
? ? ? ? ? ? ? ? ? ? count = 0;
? ? ? ? ? ? ? ? ? ? firClick = 0;
? ? ? ? ? ? ? ? ? ? startPreview();
? ? ? ? ? ? ? ? }catch (Exception e){
? ? ? ? ? ? ? ? ? ? Log.i("qwdfdf","保存失敗");
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? };
? ? ? ? @Override
? ? ? ? public void onDestroy() {
? ? ? ? ? ? super.onDestroy();
? ? ? ? ? ? stopPreview();
? ? ? ? }
? ? ? ? @Override
? ? ? ? public void onVisibilityChanged(boolean visible) {
? ? ? ? ? ? if (visible) {
? ? ? ? ? ? ? ? startPreview();
? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? stopPreview();
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? public void startPreview() {
? ? ? ? ? ? camera = Camera.open();
? ? ? ? ? ? camera.setDisplayOrientation(90);
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? camera.setPreviewDisplay(getSurfaceHolder());
? ? ? ? ? ? } catch (IOException e) {
? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? }
? ? ? ? ? ? camera.startPreview();
? ? ? ? }
? ? ? ? /**
? ? ? ? * 停止預(yù)覽
? ? ? ? */
? ? ? ? public void stopPreview() {
? ? ? ? ? ? if (camera != null) {
? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? camera.stopPreview();
? ? ? ? ? ? ? ? ? ? camera.setPreviewCallback(null);
? ? ? ? ? ? ? ? ? ? // camera.lock();
? ? ? ? ? ? ? ? ? ? camera.release();
? ? ? ? ? ? ? ? } catch (Exception e) {
? ? ? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? camera = null;
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? @Override
? ? ? ? public void onPreviewFrame(byte[] data, android.hardware.Camera camera) {
? ? ? ? ? ? ? ? camera.addCallbackBuffer(data);
? ? ? ? }
? ? }
}
看著很多,但是其實好理解。首先是要繼承WallpaperService,接下來是重寫他的onCreateEngine方法,這個是必須重寫的。我們在其中實例化自己的一個類,并讓它繼承Engine。
在這個類中我們就要設(shè)置預(yù)覽,要預(yù)覽就得有SurfaceHolder。同時我們也要設(shè)置他的點擊事件,(這是我自己加的)在onTouchEvent中就是判斷是否是兩次連續(xù)的點擊事件。這里注意的是,拍照用的是takePicture,他會回調(diào)PictureCallback,在這個回調(diào)完成之后我們需要重新開始預(yù)覽,要不然留下的是我們拍照的照片。但是這也存在一些小問題,就是重新預(yù)覽會有一點卡頓,這也是需要改進的地方。
最后我們在MainActivity中申請權(quán)限,開始服務(wù)就好了。這還有點注意的是啟動服務(wù)高版本的只能用顯示啟動,不能隱式啟動,否則會報錯。
完整代碼已經(jīng)傳到github上,地址是https://github.com/SZJing/Screen
應(yīng)用下載地址https://pan.baidu.com/s/1smhfByP