一. shared preferences
1、 Shared Preferences 是什么?
Shared Preferences 类似于winform中做一些小型配置的ini文件,用来保存一些用户设置的参数。例如,可以通过它保存上一次用户所做的修改或者自定义参数设定,当再次启动程序后依然保持原有设置。
2、如何使用 Shared Preferences 获得数据?
Shared Preferences提供了getPreferences方法来获得Preferences对象,取得该对象了,即可以使用Editor取得编辑对象
3、如何使用 Shared Preferences 保存数据?
3.1 Shared Preferences支持的数据类型:
布尔值
浮点值
整形值
长整型
字符串值
上文获得Editor对象之后即可通过 Android 提供的各自操作函数进行数据提交,如:putBoolean()提交一个键值 为bool值的数据,最后通过commit方法保存这些数据。
3.2、使用getPreferences方法创建文件的模式
在 Android系统提供的API中, 获取 Preferences对象有四种类型,分别如下:
文件创建模式:Activity.MODE_APPEND
如果该文件已经存在,然后将数据写入,而不是抹掉它现有文件的末尾。
文件创建模式:MODE_PRIVATE
默认模式,在那里创建的文件只能由应用程序调用,即为私有的
文件创建模式:Activity.MODE_WORLD_READABLE
允许所有其他应用程序有读取和创建文件的权限。
文件创建模式:Activity.MODE_WORLD_WRITEABLE
允许所有其他应用程序具有写入、访问和创建的文件权限。
本例中使用到了私有的文件创建模式,来获取Preferences对象。
4、 模拟用户参数设置
在模拟的例子中,我们放了一个复选框和一个文本显示控件,然后通过播放音乐来达到模拟效果。当复选框选中时打开音乐,文本显示控件显示当前音乐为:打开,如果反选复选框则音乐停止,文本显示控件显示当前音乐为:关闭。如果你按下模拟器的返回按钮退出的同时保存当前的状态,如果复选框选中则一打开程序立刻播放音乐,反之则不播放音乐。代码如下:
主Activity
package com.chaowen; import android.app.Activity; import android.content.SharedPreferences; import android.os.Bundle; import android.view.KeyEvent; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.TextView; public class sharePreferencesDemo extends Activity { /** Called when the activity is first created. */ private TextView myTextView; private CheckBox myBox; private playMusic PLAYER=null; private boolean isplay=false; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); myTextView=(TextView)findViewById(R.id.TextView01); myBox=(CheckBox)findViewById(R.id.CheckBox01); PLAYER=new playMusic(this); /* * 文件创建模式:Activity.MODE_APPEND * 如果该文件已经存在,然后将数据写入,而不是抹掉它现有文件的末尾。 */ /* * 文件创建模式:MODE_PRIVATE * 默认模式,在那里创建的文件只能由应用程序调用,即为私有的 */ /* * 文件创建模式:Activity.MODE_WORLD_READABLE * 允许所有其他应用程序有读取和创建文件的权限。 */ /* * 文件创建模式:Activity.MODE_WORLD_WRITEABLE * 允许所有其他应用程序具有写入、访问和创建的文件权限。 */ SharedPreferences setting=getPreferences(Activity.MODE_PRIVATE); //通过key值找到value,如果不存在即返回false isplay=setting.getBoolean("isplay", false); myBox.setChecked(isplay); if(isplay){ myTextView.setText("当前的音乐播放状态:开"); isplay=true; PLAYER.Play(); }else { myTextView.setText("当前的音乐的播放状态:关"); } myBox.setOnCheckedChangeListener(new OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if(isChecked){ myTextView.setText("当前的音乐播放状态:开"); isplay=true; PLAYER.Play(); }else { myTextView.setText("当前的音乐的播放状态:关"); isplay=false; PLAYER.FreeMusc(); } } }); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if(keyCode==KeyEvent.KEYCODE_BACK){ SharedPreferences uiState=getPreferences(0); SharedPreferences.Editor editor=uiState.edit(); editor.putBoolean("isplay", isplay); editor.commit(); if(isplay){ PLAYER.FreeMusc(); } this.finish(); return true; } return super.onKeyDown(keyCode, event); } }
playMusic.java
package com.chaowen;
import java.io.IOException; import android.content.Context; import android.media.MediaPlayer; public class playMusic { public MediaPlayer music=null; private Context myContext; public playMusic(Context cc) { myContext=cc; } public void Play() { music=MediaPlayer.create(myContext, R.raw.start); music.setLooping(true); try { music.prepare(); } catch (IllegalStateException e) { // TODO: handle exception e.printStackTrace(); } catch (IOException e) { // TODO: handle exception e.printStackTrace(); } music.start(); } public void FreeMusc() { if(music!=null) { music.stop(); music.release(); } } }
main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <CheckBox android:id="@+id/CheckBox01" android:layout_width="wrap_content" android:layout_height="wrap_content"></CheckBox> <TextView android:id="@+id/TextView01" android:layout_width="wrap_content" android:layout_height="wrap_content"></TextView> </LinearLayout>
5、查看 Preferences 产生的文件
通过上面的例子和代码的实现,己经实现了我们当初期望得到的效果,如果说它像winform中的ini文件,那么它就会创建在一个地方咯。没错,下面我们就来找到它。
在每安装一个Android 应用程序时,data/data目录下都会产生一个文件夹,如果应用程序中使用了 Preferences 则会在该应用程序文件夹下产生一个shared_prefs文件夹,我们产生的文件正安静的躺在那里等着我们呢。。。。(YY中。。。),查看步骤要求:
- 必须启动模拟器,运行程序。
- 在 你使用的IDE中切换到DDMS视图,选择File Explorer标签。注意:如果你的File Explorer里面没有任何东西,请根据此步骤找回--》DDMS-在Devices标签中选择
-
- 点击Reset adb即可将你的 File Explorer还原。
- 找到/data/data目录中对应的项目文件夹下的shared_prefs文件夹
这几天在做安卓比武场第三上的定时设置壁纸效果(这个活动不错,希望大家踊跃参加),想要达到多定时的效果,就是设置多个换壁纸的效果。我使用AlarmManager进行进行定时发送换壁纸广播,出现了一个问题就是onreceive收到都是第一个广播的intent.
下面我给出关键代码而原代码,有兴趣的读者可以下载代码去运行下,你会发现一个让我昨天到两点多才睡的问题
这些是发送信息的代码
main.java
package com.wjh.test; import java.util.Calendar; import android.app.Activity; import android.app.AlarmManager; import android.app.PendingIntent; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; public class Main extends Activity implements OnClickListener { /** Called when the activity is first created. */ Button btn ; int id = 1; char a = 'a'; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); btn = (Button)findViewById(R.id.button1); btn.setOnClickListener(this); } @Override public void onClick(View v) { // TODO Auto-generated method stub Intent intent = new Intent(Main.this,MyReceive.class); //输入action intent.setAction("com.wjh.action"); //输入id intent.putExtra("id", id); //输入字符 intent.putExtra("char",a); PendingIntent pi = PendingIntent.getBroadcast(Main.this, 0, intent, 0); //设置时间 Calendar c = Calendar.getInstance(); c.setTimeInMillis(System.currentTimeMillis()); c.add(Calendar.SECOND,5); AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE); am.set(AlarmManager.RTC_WAKEUP, c.getTimeInMillis(), pi); Toast.makeText(this,"第"+id+"次发出"+id+""+a,Toast.LENGTH_SHORT).show(); id++; a++; } }
这个接受信息的代码
MyReceive.java
public class MyReceive extends BroadcastReceiver{ public static int i=0; @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub if(intent.getAction().equals("com.wjh.action")) { int id = intent.getIntExtra("id", 0); char str = intent.getCharExtra("char", 'b'); Toast.makeText(context,"第"+(++i)+"次"+ id+""+str, Toast.LENGTH_SHORT).show(); } } }
运行的结果是:
发现了吗?虽然发出的数据在变,但是接受到了都是同样的的。
昨天晚上我也被这个东西搞死了,或许你们不可能再为这个问题而烦扰了,因为我现在告诉你为什么会这样!
就是因为Broadcast,因为我们发送广播,是把一个intent弄到这里面,但是broadcast偷懒了,只要你放入
Intent是一样的,那么他发出的永远都是第一个输入的!
所以下面我们来是改变intent的action来试试效果
我们来改下main.jafva文件代码:
//输入action intent.setAction("com.wjh.action");
改成
//输入action intent.setAction("com.wjh.action"+id);
下面改下MyReceive.java的代码
将整个onReceive方法的代码改成下面的:
public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub int id = intent.getIntExtra("id", 0); char a = intent.getCharExtra("char", 'b'); Toast.makeText(context,"第"+(++i)+"次受到"+ id+""+a, Toast.LENGTH_SHORT).show(); }
那么来看看效果图吧:
看似很简单,但是如果你想要通过alarmManager进行传送数据,那么你将悲剧了,因为你收到的永远的都是第一份,所以所Broacast偷懒,那么alarmManager悲剧!
下面我给出两个例子的完整源代码附件:
显示Web网页:
Uri uri = Uri.parse("http://www.android123.com.cn"); Intent it = new Intent(Intent.ACTION_VIEW,uri); startActivity(it);
显示Google地图:
Uri uri = Uri.parse("geo:38.899533,-77.036476"); Intent it = new Intent(Intent.Action_VIEW,uri); startActivity(it);
Maps路径规划:
Uri uri = Uri.parse("http://maps.google.com/maps?f=d&saddr=startLat%20startLng&daddr=endLat%20endLng&hl=en"); Intent it = new Intent(Intent.ACTION_VIEW,URI); startActivity(it);
拨打电话:
Uri uri = Uri.parse("tel:xxxxxx"); Intent it = new Intent(Intent.ACTION_DIAL, uri); startActivity(it); Uri uri = Uri.parse("tel.xxxxxx"); Intent it =new Intent(Intent.ACTION_CALL,uri);
注意需要权限
<uses-permission id="android.permission.CALL_PHONE" />
发送SMS/MMS
Intent it = new Intent(Intent.ACTION_VIEW); it.putExtra("sms_body", "android开发网欢迎您"); it.setType("vnd.android-dir/mms-sms"); startActivity(it);
发送短信
Uri uri = Uri.parse("smsto:10086"); Intent it = new Intent(Intent.ACTION_SENDTO, uri); it.putExtra("sms_body", "10086"); //正文为10086 startActivity(it);
发送彩信
Uri uri = Uri.parse("content://media/external/images/media/10"); //该Uri根据实际情况修改,external代表外部存储即sdcard Intent it = new Intent(Intent.ACTION_SEND); it.putExtra("sms_body", "android123.com.cn"); it.putExtra(Intent.EXTRA_STREAM, uri); it.setType("image/png"); startActivity(it);
发送Email
Uri uri = Uri.parse("mailto:android123@163.com"); Intent it = new Intent(Intent.ACTION_SENDTO, uri); startActivity(it);
Intent it = new Intent(Intent.ACTION_SEND); it.putExtra(Intent.EXTRA_EMAIL, "android123@163.com"); it.putExtra(Intent.EXTRA_TEXT, "android开发网测试"); it.setType("text/plain"); startActivity(Intent.createChooser(it, "选择一个Email客户端"));
Intent it=new Intent(Intent.ACTION_SEND); String[] tos={"android123@163.com"}; //发送到 String[] ccs={"ophone123@163.com"}; //抄送 it.putExtra(Intent.EXTRA_EMAIL, tos); it.putExtra(Intent.EXTRA_CC, ccs); it.putExtra(Intent.EXTRA_TEXT, "正文"); it.putExtra(Intent.EXTRA_SUBJECT, "标题"); it.setType("message/rfc822"); //编码类型 startActivity(Intent.createChooser(it, "选择一个Email客户端"));
Email添加附件
Intent it = new Intent(Intent.ACTION_SEND); it.putExtra(Intent.EXTRA_SUBJECT, "正文"); it.putExtra(Intent.EXTRA_STREAM, "file:///sdcard/nobody.mp3"); //附件为sd卡上的nobody MP3文件 sendIntent.setType("audio/mp3"); startActivity(Intent.createChooser(it, "选择一个Email客户端"));
播放多媒体
Intent it = new Intent(Intent.ACTION_VIEW); Uri uri = Uri.parse("file:///sdcard/nobody.mp3"); it.setDataAndType(uri, "audio/mp3"); startActivity(it); Uri uri = Uri.withAppendedPath(MediaStore.Audio.Media.INTERNAL_CONTENT_URI, "1"); //从系统内部的MediaProvider索引中调用播放 Intent it = new Intent(Intent.ACTION_VIEW, uri); startActivity(it);
Uninstall卸载程序
Uri uri = Uri.fromParts("package", packageName, null); //packageName为包名,比如com.android123.apkInstaller Intent it = new Intent(Intent.ACTION_DELETE, uri); startActivity(it);
进入联系人界面
Intent intent = new Intent(); intent.setAction(Intent.ACTION_VIEW); intent.setData(People.CONTENT_URI); startActivity(intent);
查看某个联系人,当然这里是 ACTION_VIEW ,如果为选择并返回 action 改为 ACTION_PICK ,当然处理 intent 时返回需要用到 startActivityforResult
Uri personUri = ContentUris.withAppendedId(People.CONTENT_URI, ID);//最后的ID参数为联系人Provider中的数据库BaseID,即哪一行 Intent intent = new Intent(); intent.setAction(Intent.ACTION_VIEW); intent.setData(personUri); startActivity(intent);
选择一个图片
Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.addCategory(Intent.CATEGORY_OPENABLE); intent.setType("image/*"); startActivityForResult(intent, 0);