本程序主要实现了:
1.使用AssetManager将assets目录中的文件复制到SD卡的指定位置
2.使用AlarmManager全局定时器,周期性的启动指定组件切换壁纸
3.使用SharedPreferences,将用户个性化的设置保存到手机(例如壁纸切换频率)
4.使用自定义标题栏
5.使用了GestureDetector手势检测器,允许用户滑动切屏
6.使用了overridePendingTransition,在切屏的时候有动画效果
程序运行效果图:
程序代码:
ChangeWallpaper.java:
package com.jph.changewallpaper; import java.io.File; import com.jph.util.Const; import com.jph.util.CopyFolder; import android.os.Bundle; import android.os.Environment; import android.app.Activity; import android.app.AlarmManager; import android.app.PendingIntent; import android.app.Service; import android.content.Intent; import android.content.SharedPreferences; import android.view.GestureDetector; import android.view.KeyEvent; import android.view.Menu; import android.view.MotionEvent; import android.view.View; import android.view.GestureDetector.OnGestureListener; import android.view.View.OnClickListener; import android.view.Window; import android.widget.CompoundButton; import android.widget.ImageButton; import android.widget.Toast; import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.ToggleButton; /** * Describe:</br> * </br>帮你换壁纸 * </br>本程序主要实现了: * </br>1.使用AssetManager将assets目录中的文件复制到SD卡的指定位置 * </br>2.使用AlarmManager全局定时器,周期性的启动指定组件切换壁纸 * </br>3.使用SharedPreferences,将用户个性化的设置保存到手机(例如壁纸切换频率) * </br>4.使用自定义标题栏 * </br>5.使用了GestureDetector手势检测器,允许用户滑动切屏 * </br>6.使用了overridePendingTransition,在切屏的时候有动画效果 * </br>@author jph * </br>Date:2014.08.05 * * */ public class ChangeWallpaper extends Activity implements OnGestureListener{ //定义手势检测器实例 GestureDetector detector; // 定义AlarmManager对象 AlarmManager alarmManager; ToggleButton btnSwitch; ImageButton btnSetting; Intent intent; PendingIntent pi; //表示是不是第一次使用该应用 boolean isFirstUse; //是不开启了自动切换壁纸 boolean isLaunch; //壁纸切换别的频率 int frequency; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //设置自定义标题栏标志 ,该语句必须放在setContentView之前 requestWindowFeature(Window.FEATURE_CUSTOM_TITLE); setContentView(R.layout.main); //设置自定义标题栏,改句必须放在setContentView之后 getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.title); btnSwitch=(ToggleButton)findViewById(R.id.btnSwitch); btnSetting=(ImageButton)findViewById(R.id.btnSetting); btnSetting.setOnClickListener(listener); //初始化手势检测器 detector=new GestureDetector(this,this); // 指定启动ChangeService组件 intent = new Intent(ChangeWallpaper.this,ChangeService.class); // 创建PendingIntent对象 pi=PendingIntent.getService(ChangeWallpaper.this, 0, intent, 0); //获取系统的AlarmManager对象 alarmManager=(AlarmManager)getSystemService(Service.ALARM_SERVICE); //初始化程序配置 iniApp(); btnSwitch.setOnCheckedChangeListener(new OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { // TODO Auto-generated method stub isLaunch=isChecked; if (isChecked) { launchChangeService(); }else { // 取消对pi的调度 alarmManager.cancel(pi); } } }); } //启动切换壁纸 protected void launchChangeService() { // TODO Auto-generated method stub // 设置每隔5秒执行pi代表的组件一次 alarmManager.setRepeating(AlarmManager.RTC_WAKEUP , 0, frequency, pi); Toast.makeText(ChangeWallpaper.this, "壁纸定时更换启动成功啦", Toast.LENGTH_SHORT).show(); } OnClickListener listener=new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub switch (v.getId()) { case R.id.btnSetting: showSetting(); break; default: break; } } }; //初始化应用,如果第一次使用,则将asset下的壁纸拷贝到SD卡上 private void iniApp() { // TODO Auto-generated method stub //获取系统的SharedPreferences对象 SharedPreferences preferences=getSharedPreferences("config", MODE_PRIVATE); //获取配置文件中的isFirstUse isFirstUse=preferences.getBoolean("isFirstUse", true); //获取配置文件中的frequency切换频率,默认五秒 frequency=preferences.getInt(Const.SETING_FREQUENCY_Str, 5000); if (isFirstUse) {//如果第一次使用,则将asset下的壁纸拷贝到SD卡上 //如果手机插入了SD卡,且程序有读取SD卡的权限 if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { //获取手机SD卡的目录 File sdCardDir=Environment.getExternalStorageDirectory(); String path=null; try { path=sdCardDir.getCanonicalPath()+File.separator+"wallpaper"; } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } CopyFolder cf=new CopyFolder(ChangeWallpaper.this, "wpics", path); cf.start();//启动线程 } } } //显示程序设置界面 protected void showSetting() { // TODO Auto-generated method stub //启动设置界面 Intent intent=new Intent(ChangeWallpaper.this, SettingActivity.class); startActivityForResult(intent,Const.REQUESTCODE_FOR_SETTING); //设置切换动画,从右边进入,左边退出 overridePendingTransition(R.anim.right_in, R.anim.left_out); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { // TODO Auto-generated method stub switch (requestCode) { case Const.REQUESTCODE_FOR_SETTING://如果从设置界面返回 if (isLaunch) {//如果已经启动了自动且换壁纸 //获取配置信息 iniApp(); launchChangeService(); } break; default: break; } } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { // TODO Auto-generated method stub switch (keyCode) { case KeyEvent.KEYCODE_MENU://当按下菜单键跳转到设置界面 showSetting(); break; default: break; } return super.onKeyDown(keyCode, event); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.change_wallpaper, menu); return true; } @Override public boolean onTouchEvent(MotionEvent event) { // TODO Auto-generated method stub //将触碰事件交给GestureDetector处理 return detector.onTouchEvent(event); } @Override public boolean onDown(MotionEvent e) { // TODO Auto-generated method stub return false; } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { // TODO Auto-generated method stub //如果想右滑动的距离大于50mm if (e1.getX()-e2.getX()>50) { showSetting(); } return false; } @Override public void onLongPress(MotionEvent e) { // TODO Auto-generated method stub } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { // TODO Auto-generated method stub return false; } @Override public void onShowPress(MotionEvent e) { // TODO Auto-generated method stub } @Override public boolean onSingleTapUp(MotionEvent e) { // TODO Auto-generated method stub return false; } }
ChangeService.java(ChangeService切换壁纸类):
package com.jph.changewallpaper; import java.io.File; import java.util.ArrayList; import com.jph.util.CopyFolder; import android.app.Service; import android.app.WallpaperManager; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Environment; import android.os.IBinder; import android.widget.Toast; /** * Describe:</br> * </br>ChangeService切换壁纸类 * </br>获取SD卡的指定指定目录下的图片 * </br>使用WallpaperManager来更换当前壁纸 * </br>@author jph * </br>Date:2014.08.05 * * */ public class ChangeService extends Service { //定义一个存放图片名的数组 String []fileNames; //定义一个存放图片路径的集合 ArrayList<String>picPaths=new ArrayList<String>(); // 定义系统的壁纸管理服务 WallpaperManager wManager; // 定义当前所显示的壁纸 int current = 0,flag=0; //创建一个CopyFolder类的对象 CopyFolder cf=null; public ChangeService() { // TODO Auto-generated constructor stub super(); } @Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); //初始化WallpaperManager wManager = WallpaperManager.getInstance(this); if (picPaths.isEmpty()) {//如果picPaths中还没有照片 getPicPath(); } flag++; Toast.makeText(ChangeService.this, "flag:"+flag,Toast.LENGTH_SHORT).show(); System.out.println("=========================="); System.out.println( "flag:"+flag); } @Override public int onStartCommand(Intent intent, int flags, int startId) { // TODO Auto-generated method stub System.out.println("=========================="); System.out.println( "onStartCommand:"+flag); // 如果到了最后一张,系统重新开始 if(current >picPaths.size()) current = 0; try { //将指定路径的图片转换成bitmap Bitmap bitmap=BitmapFactory.decodeFile(picPaths.get(current++).toString()); // 改变壁纸 wManager.setBitmap(bitmap); } catch (Exception e) { e.printStackTrace(); } return START_STICKY; } //从SD卡的根目录下的wallpaper文件夹中读出图片路径到picPaths集合中 public void getPicPath(){ System.out.println("=========================="); System.out.println( "getPicPath:"+flag); //如果手机插入了SD卡,且程序有读取SD卡的权限 if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { //获取手机SD卡的目录 File sdCardDir=Environment.getExternalStorageDirectory(); String path=null; try { path=sdCardDir.getCanonicalPath()+File.separator+"wallpaper"; } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } File file=new File(path); fileNames=file.list(); //如果wallpaper目录不存在或为空则将assets目录下的壁纸复制到wallpaper目录下 if (fileNames==null||fileNames.length==0) { if (cf==null) { cf=new CopyFolder(ChangeService.this, "wpics", path); cf.start();//启动线程 } } picPaths.clear();//清空集合中的数据 for (String picName:fileNames) { if (isPicture(picName)) { //将图片的完整路径添加到picPaths中 picPaths.add(path+File.separator+picName); } } } } /** * 判断文件类型是否为图片 * @param fileName String 用于判断的文件名 * @return boolean * */ public boolean isPicture(String fileName) { //存放图片格式的数组 String []limit=new String[]{".png",".jpg",".gif",".jpeg" + ".bmp",".PNG",".JPG",".GIF",".JPEG",".BMP"}; for (String str:limit) { if (fileName.endsWith(str)) {//如果指定文件名为以上其中一种格式则返回true return true; } } return false; } @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return null; } }SettingActivity.java(设置菜单界面类)
package com.jph.changewallpaper; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import com.jph.util.Const; import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.os.Bundle; import android.view.GestureDetector.OnGestureListener; import android.view.GestureDetector; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.SimpleAdapter; /** * Describe:</br> * </br>设置菜单界面类 * </br>将用户个性化的设置保存到SharedPreferences中 * </br>@author jph * </br>Date:2014.08.05 * */ public class SettingActivity extends Activity implements OnGestureListener{ private AlertDialog dialog; private AlertDialog.Builder builder; ListView list; //设置菜单标题 String []itemTitles; //设置菜单图标 int []itemIcos; //壁纸切换频率 String frequencyString; //定义手势检测器实例 GestureDetector detector; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.setting); //初始化手势检测器 detector=new GestureDetector(this,this); list=(ListView)findViewById(R.id.list); //初始化ListView initList(); } private void initList() { // TODO Auto-generated method stub //获取itemTitles.xml中的选项标题和图标 itemTitles=getResources().getStringArray(R.array.itemTitles); itemIcos=new int[]{R.drawable.setting_fre,R.drawable.setting_fs ,R.drawable.setting_redefault,R.drawable.setting_abuot}; List<Map<String,Object>>listItems=new ArrayList<Map<String,Object>>(); for (int i = 0; i < itemTitles.length; i++) { Map<String, Object>listItem=new HashMap<String, Object>(); listItem.put("imgItemIco", itemIcos[i]); listItem.put("txtItemTitle", itemTitles[i]); listItems.add(listItem); } SimpleAdapter adapter=new SimpleAdapter(SettingActivity.this,listItems, R.layout.line, new String[]{"imgItemIco","txtItemTitle"}, new int[]{R.id.imgItemIco,R.id.txtItemTitle}); list.setAdapter(adapter); list.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { // TODO Auto-generated method stub switch (position) { case 0: //设置壁纸切换的屏幕 setFrequency(); break; case 1: displayPattern(); break; case 2: break; case 3: about(); break; default: break; } } }); } //设置壁纸的显示方式 protected void displayPattern() { // TODO Auto-generated method stub final String item[]=new String[]{"平铺","拉伸","裁切","默认"}; DialogInterface.OnClickListener sListener=new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { frequencyString=item[which]; } }; builder=new AlertDialog.Builder(this); builder.setSingleChoiceItems(item, -1, sListener); dialog=builder.create(); dialog.setTitle("请设置壁纸显示方式"); //创建按键监听器 DialogInterface.OnClickListener listener=new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { if(which==DialogInterface.BUTTON_POSITIVE) {//按下确定 dialog.dismiss(); if (frequencyString.endsWith("秒")) { frequencyString=frequencyString.replace("秒", ""); //将String转换成int int frequency=Integer.parseInt(frequencyString)*1000; alterConfig(Const.SETING_FREQUENCY,frequency); }else if (frequencyString.endsWith("分钟")) { frequencyString=frequencyString.replace("分钟", ""); //将String转换成int int frequency=Integer.parseInt(frequencyString)*1000*60; alterConfig(Const.SETING_FREQUENCY,frequency); } }else if(which==DialogInterface.BUTTON_NEGATIVE){//按下取消 dialog.dismiss(); } } }; dialog.setButton(DialogInterface.BUTTON_POSITIVE, "确定",listener); dialog.setButton(DialogInterface.BUTTON_NEGATIVE, "取消",listener); dialog.show(); } //关于 protected void about() { // TODO Auto-generated method stub LayoutInflater inflater=LayoutInflater.from(this); LinearLayout layout=(LinearLayout) inflater.inflate(R.layout.about, null); AlertDialog dialog=new AlertDialog.Builder(SettingActivity.this).create(); dialog.setTitle("关于"); dialog.setIcon(R.drawable.smile); dialog.setView(layout); dialog.show(); } //设置显示频率 protected void setFrequency() { // TODO Auto-generated method stub final String item[]=new String[]{"3秒","5秒","10秒","20秒","30秒","1分钟","5分钟","10分钟"}; DialogInterface.OnClickListener sListener=new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { frequencyString=item[which]; } }; builder=new AlertDialog.Builder(this); builder.setSingleChoiceItems(item, -1, sListener); dialog=builder.create(); dialog.setTitle("请设置壁纸切换的频率"); //创建按键监听器 DialogInterface.OnClickListener listener=new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { if(which==DialogInterface.BUTTON_POSITIVE) {//按下确定 dialog.dismiss(); if (frequencyString.endsWith("秒")) { frequencyString=frequencyString.replace("秒", ""); //将String转换成int int frequency=Integer.parseInt(frequencyString)*1000; alterConfig(Const.SETING_FREQUENCY,frequency); }else if (frequencyString.endsWith("分钟")) { frequencyString=frequencyString.replace("分钟", ""); //将String转换成int int frequency=Integer.parseInt(frequencyString)*1000*60; alterConfig(Const.SETING_FREQUENCY,frequency); } }else if(which==DialogInterface.BUTTON_NEGATIVE){//按下取消 dialog.dismiss(); } } }; dialog.setButton(DialogInterface.BUTTON_POSITIVE, "确定",listener); dialog.setButton(DialogInterface.BUTTON_NEGATIVE, "取消",listener); dialog.show(); } //修改配置文件 protected void alterConfig(int flag, int frequency) { // TODO Auto-generated method stub SharedPreferences preferences=getSharedPreferences("config", MODE_PRIVATE); //获取SharedPreferences对应的Editor Editor editor=preferences.edit(); switch (flag) { case Const.SETING_FREQUENCY: editor.putInt(Const.SETING_FREQUENCY_Str, frequency); break; default: break; } editor.commit(); } @Override public boolean onTouchEvent(MotionEvent event) { // TODO Auto-generated method stub //将触碰事件交给GestureDetector处理 return detector.onTouchEvent(event); } @Override public boolean onDown(MotionEvent e) { // TODO Auto-generated method stub return false; } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { // TODO Auto-generated method stub //如果向左滑动距离大于50mm if (e2.getX()-e1.getX()>50) { Intent intent=getIntent(); setResult(Activity.RESULT_OK, intent); this.finish(); overridePendingTransition(R.anim.left_in, R.anim.right_out); } return false; } @Override public void onLongPress(MotionEvent e) { // TODO Auto-generated method stub } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { // TODO Auto-generated method stub return false; } @Override public void onShowPress(MotionEvent e) { // TODO Auto-generated method stub } @Override public boolean onSingleTapUp(MotionEvent e) { // TODO Auto-generated method stub return false; } }工具类:
CopyFolder.java(复制assets中的文件到SD卡的指定位置)
package com.jph.util; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import android.content.Context; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; /** * Describe:</br> * </br>从assets项目目录中复制文件及目录 * </br>本类启用了一个新线程用于处理复制文件的耗时任务 * </br>当所有的复制完成或复制文件出错时通知UI线程 * </br>@author JPH * </br>Date:2014.07.30 * */ public class CopyFolder extends Thread { //定义两个常量用于表示复制文件成功的标识 public final static int COPY_FALSE=0x123,COPY_SUCCESS=0x456; String newPath,oldPath; Context context; public CopyFolder() { // TODO Auto-generated constructor stub } /** * 从assets目录中复制整个文件夹内容 * @param context Context 使用CopyFiles类的Activity * @param oldPath String 原文件路径 如:img * @param newPath String 复制后路径 如:xx:/bb/cc */ public CopyFolder(Context context,String oldPath,String newPath) { this.context=context; this.oldPath=oldPath; this.newPath=newPath; } @Override public void run() { // TODO Auto-generated method stub copyFilesFassets(context,oldPath,newPath); SharedPreferences prference=context.getSharedPreferences("config", Context.MODE_PRIVATE); Editor editor=prference.edit(); editor.putBoolean("isFirstUse", false);//写入使用标识 editor.commit();//最后不要忘记将存入的数据进行提交 // MainActivity.handler.sendEmptyMessage(COPY_SUCCESS); } /** * 从assets目录中复制整个文件夹内容 * @param context Context 使用CopyFiles类的Activity * @param oldPath String 原文件路径 如:/aa * @param newPath String 复制后路径 如:xx:/bb/cc */ public void copyFilesFassets(Context context,String oldPath,String newPath) { try { String fileNames[] = context.getAssets().list(oldPath);//获取assets目录下的所有文件及目录名 if (fileNames.length > 0) {//如果是目录 File file = new File(newPath); file.mkdirs();//如果文件夹不存在,则递归 for (String fileName : fileNames) { copyFilesFassets(context,oldPath + "/" + fileName,newPath+"/"+fileName); } } else {//如果是文件 InputStream is = context.getAssets().open(oldPath); FileOutputStream fos = new FileOutputStream(new File(newPath)); byte[] buffer = new byte[1024]; int byteCount=0; while((byteCount=is.read(buffer))!=-1) {//循环从输入流读取 buffer字节 fos.write(buffer, 0, byteCount);//将读取的输入流写入到输出流 } fos.flush();//刷新缓冲区 is.close(); fos.close(); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); //如果捕捉到错误则通知UI线程 // MainActivity.handler.sendEmptyMessage(COPY_FALSE); } } }
Const.java(常量类:提供程序中用到的主要常量)
package com.jph.util; /** * Describe:</br> * </br>常量类 * </br>提供程序中用到的主要常量 * </br>@author jph * </br>Date:2014.08.05 * */ public class Const { //壁纸切换频率标识 public final static int SETING_FREQUENCY=0x0001; public final static String SETING_FREQUENCY_Str="frequency"; //SettingActivity的请求码 public final static int REQUESTCODE_FOR_SETTING=0x123; public Const() { // TODO Auto-generated constructor stub } }
AndroidManifest.xml配置清单:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.jph.changewallpaper" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="18" /> <!-- 在SD卡中创建与删除文件权限 --> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <!-- 向SD卡写入数据权限 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <!-- 授予用户修改壁纸的权限 --> <uses-permission android:name="android.permission.SET_WALLPAPER" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.jph.changewallpaper.ChangeWallpaper" android:label="@string/app_name" android:theme="@style/style_title"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name="com.jph.changewallpaper.SettingActivity"></activity> <!-- 注册 ChangeService--> <service android:name="com.jph.changewallpaper.ChangeService"></service> </application> </manifest>