第二天 存储文件
TextUtils.isEmpty(var) 判断某个量var是否为空
“zhangtao”.equals(var) 判断var是否等于zhangtao
android:password="true" 表单设置成密码样式
private CheckBox check; check.isChecked() 选项被选中的判断
写文件:
FileOutputStream fos = new FileOutputStream(file);
fos.write(str.getBytes());
程序数据的根目录 /data/data/项目包名/
android studio 导入jar包 http://jingyan.baidu.com/article/e6c8503c7190b7e54f1a1893.html 要切换到project模式下操作,否则看不到libs包。删除包的话就是直接到项目目录下,找到libs包,删除即可。
Android Studio中调出DDMS的方法是按工具栏上的小绿色机器人,可以找到File Explorer
如果在程序中写 File file = new File("a.txt"); 这是要直接创建在应用程序的目录下,这是创建不成功的。应用程序的目录在 data/app/ 下,这个目录是不允许创建文件的。
每个应用都为其创建了一个文件 在/data/data/包名 下,这个才是其存放数据的文件夹。比如,File file = new File(""/data/data/com.example.zhangtao/info.txt""); 这样才是可以的。
context.getFilesDir(); // 帮助我们返回 data/data/包名/files 目录 例如: File file = new File(context.getFilesDir(),"context.txt");
context.getCacheDir(); 帮助我们返回 data/data/包名/cache 目录
利用context 直接写文件,可以不用context.getFilesDir(); 如下代码:(会自动保存在data/data/包名/files 目录下)
FileOutputStream fos = context.openFileOutput("private.txt",Context.MODE_PRIVATE);
fos.write("aabb".getBytes());
fos.close();
别的应用读取另外一个应用的文件,文件路径必须写死了。不可采用context的api,否则会读取到本应用的路径
MODE_PRIVATE 这是默认的形式,配置文件只允许本程序和享有本程序ID的程序的访问 0
MODE_WORLD_READABLE 允许其他的应用程序读文件 1
MODE_WORLD_WRITEABLE 允许其他的应用程序写文件 2 这俩好像过期了,不知用何取代
MODE_MULTI_PROCESS 主要用于多任务,2.3版本当多个进程共同访问的时候,必须指定这个标签
一个错误,待究:
如果在方法外定义 Context context; 然后方法内调用 context.openFileOutput() 则报错
把Context context作为参数则没有问题。
文件的权限:私有文件 别的应用既不可读也不可写。可读文件 别的应用只可读 不可写 。 可写文件 别的应用只可写,不可读。可读可写文件,别的应用既可读又可写,也即创建文件时,权限部分的格式是:Context.MODE_WORLD_READABLE+Context.MODE_WORLD_WRITEABLE
存储文件到SD卡,必须在manifest.xml文件中添加uses permission权限android.permission.WRITE_EXTERNAL_STORAGE 权限。
在4.0以前版本,读sd卡是不需要权限的。在4.0以后版本,考虑到这个问题:在 开发者选项 -- 对SD卡进行读写保护 有这个选项,勾选之后,读取sd卡数据也需要权限了。此时,必须加上android.permission.READ_EXTERNAL_STORAGE 权限之后 ,才可以读
即在manifest.xml文件中添加:<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE "> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE ">
Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState() SD卡是否挂载的判断
File file = new File(Environment.getExternalStorageDirectory(),"sd.txt"); 在SD卡目录创建文件的代码
// 在DDMS(Android Device Monitor)中 文件是保存在 /storage/sdcard/ 目录下的
另外,其实 Enviroment.getDataDirectory() 其实就是得到手机data的目录 类同用Context API 得到的目录,可相互比较一下
SharedPreferences存储
public void writeSP(View view){
SharedPreferences sp = getSharedPreferences("config",Context.MODE_PRIVATE); --- 将生成 data/data/包名/shared_prefs/config.xml 文件 注意,此时不会生成,只是在最后commit之后才会创建
SharedPreferences.Editor editor = sp.edit(); -- 获取编辑器
editor.putString("username","zhangtao"); -- 存储
editor.putInt("age",36); -- 存储
editor.commit(); -- 类似事务,提交
}
public void readSP(View view){
SharedPreferences sp = getSharedPreferences("config",Context.MODE_PRIVATE); -- 获取 config.xml文件
String username = sp.getString("username",""); -- 第二项是若是取不到的默认值
Integer age = sp.getInt("age",0);
Toast.makeText(this,username+age,Toast.LENGTH_SHORT).show();
}
android 生成xml文件
第一种方式:
StringBuffer sb = new StringBuffer();
sb.append("<?xml version="1.0" encoding="utf-8" ");
sb.append().......
.................
然后再按照通常的方法创建输出流写入即可。
fos.write(sb.toString().getBytes());
第二种方式是用XmlSerializer 方式,待研
常说序列化,何为序列化,也即信息从内存写到文件里去。
/*
* 利用XML序列化的方法 XmlSerializer serializer = Xml.newSerializer(); 生成XML文件
* */
public void createXML(View view){
try {
File file = new File(Environment.getExternalStorageDirectory(),"sms.xml");
FileOutputStream fos = new FileOutputStream(file);
XmlSerializer serializer = Xml.newSerializer(); // 创建xml序列化器
serializer.setOutput(fos,"utf-8");
serializer.startDocument("utf-8",true);
serializer.startTag(null,"province"); // null 指的是命名空间为空
serializer.attribute(null,"id","shandong");
serializer.startTag(null,"city");
serializer.text("rizhao");
serializer.endTag(null,"city");
serializer.startTag(null,"zipcode");
serializer.text("0633");
serializer.endTag(null,"zipcode");
serializer.startTag(null,"city");
serializer.text("jinan");
serializer.endTag(null,"city");
serializer.startTag(null,"zipcode");
serializer.text("0531");
serializer.endTag(null,"zipcode");
serializer.endTag(null, "province");
serializer.endDocument();
} catch (Exception e) {
e.printStackTrace();
} finally {
Toast.makeText(this,"you have do it sucessfully!",Toast.LENGTH_SHORT).show();
}
}
public void readXML(View view){
List<String> cities = null;
try {
File file = new File(Environment.getExternalStorageDirectory(),"sms.xml");
FileInputStream fis = new FileInputStream(file);
XmlPullParser parser = Xml.newPullParser(); // 创建pull解析器
parser.setInput(fis,"utf-8");
int type = parser.getEventType();
while (type != XmlPullParser.END_DOCUMENT){
switch (type){
case XmlPullParser.START_TAG:
if ("province".equals(parser.getName())) { // 解析到全局开始的标签
cities = new ArrayList<String>(); // 初始化list
} else if ("city".equals(parser.getName())){
cities.add(" city: "+parser.nextText());
} else if ("zipcode".equals(parser.getName())){
cities.add(" zipcode: "+parser.nextText());
}
break;
case XmlPullParser.END_TAG:
if ("province".equals(parser.getName())){
Toast.makeText(this,cities.toString(),Toast.LENGTH_LONG).show();
}
}
type = parser.next(); }
} catch (Exception e) {
e.printStackTrace(); }
}
关于xml解析的内容,详情可查看 http://blog.csdn.net/andyhuabing/article/details/8036340
第三天 数据库及内容提供者 (ContentProvider)
1、自定义SQLiteOpenHelper,需注意;必须实现 onCreate 和 onUpgrade 方法 以及 构造方法。构造方法中有Context参数,必须在方法外 自定义helper类内部,定义一个属性 private Context myContext ,然后在构造方法中,赋值Context属性 myContext = context; 否则会出错!
Android Studio中插入代码的快速方法是 Alt + Insert 键
定义数据库 SQLiteDatabase db ,执行sql语句的语法是 db.execSQL(sql) ,sql语句的写法与mysql中基本相同、
创建数据库的流程就是,利用自定义的SQLiteHelper 来进行,如下:
MySQLiteOpenHelper myHelper = new MySQLiteOpenHelper(this,"zhangtao.db",null,1); zhangtao.db 数据库 1为数据库版本
myHelper.getWritableDatabase(); // 这个过程应该会? 创建数据库zhangtao.db ,同时,会执行自定义helper中覆写的onCreate()方法,若此方法中定义的执行的创建表的语句,则表会创建( db.execSQL(sql) 方法)
该方法的返回值是一个SQLiteDatabase ,即要进行数据库增删改查,应该首先获取数据库。
如果此时想再在zhangtao.db中创建另外一个表,可以首先在自定义的helper中,覆写onUpgrade方法,将建表语句写进去,然后
MySQLiteOpenHelper myHelper = new MySQLiteOpenHelper(this,"zhangtao.db",null,2); myHelper.getWritableDatabase();
这样,因为数据库版本更新了,再次调用 myHelper.getWritableDatabase();的时候,会执行onUpgrade方法,就会把预先定义在其中的 新增加表的语句执行。
SQLiteDatabase数据库的增删改查
首先获取数据库
myHelper = new MySQLiteOpenHelper(this,"zhangtao.db",null,2);
SQLiteDatabase db = myHelper.getWritableDatabase();
利用ContentValues来添加值,此类支持键值对的存储。如下示例
增:
values.put("name","liudehua");
values.put("age",54);
values.put("intro","pop star");
db.insert("people",null,values); // 必须在此插入people表,否则后面values清空了 或者 是值被替代了
values.clear();
values.put("name","guofucheng");
values.put("age",50);
values.put("intro","model and pop star");
long result = db.insert("people",null,values); // 操作失败的话 会返回 -1
删:int result = db.delete("people","id = ?",new String[]{"4"}); 操作失败也是返回 -1
改:int result = db.update("people",values,"id = ?",new String[]{"3"}); 需要首先构建要更新的ContentValues值
查:
Cursor cursor = db.rawQuery("select * from people where id > ?",new String[]{"1"});
if(cursor.moveToFirst()){
do {
String name = cursor.getString(cursor.getColumnIndex("name"));
String age = cursor.getString(cursor.getColumnIndex("age"));
String intro = cursor.getString(cursor.getColumnIndex("intro"));
Log.d("query result","name is: "+name+" age is: "+age+" intro is: "+intro);
} while (cursor.moveToNext());
}
需要构建Cursor 以及利用原生sql查询的rawQuery方法 ,循环取值的 cursor.moveToFirst() cursor.moveToNext() cursor.getString(cursor.getColumnIndex("name")) 等
第六天 广播
1、自定义广播的方式
首先
Intent intent = new Intent();
intent.setAction("com.mavict.customBroadcast"); // 自定义的action,要定义在广播中
sendBroadcast(intent);
然后,自定义接受者com.example.day6.MyReceiver,继承BroadcastReceiver,覆写如下方法,处理获得广播之后的行为。
@Override
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
Toast.makeText(context,"获得到了自定义的广播事件", Toast.LENGTH_SHORT).show();
}
在manifest.xml文件中定义自定义的Receiver
<receiver android:name="com.example.day6.MyReceiver" >
<intent-filter>
<action android:name="com.mavict.customBroadcast" />
</intent-filter>
</receiver>
注意 intent-filter 中的action
第九天 Fragment等
1、特点
fragment是轻量级的activity, 不需要在清单文件中配置。可以在一个Activity中同时出现多个Fragment,并且一个Fragment也可以在多个Activity中使用;
在Activity运行过程中,可以添加、移除或者替换Fragment;
Fragment可以响应自己的输入事件,并且有自己的生命周期,它们的生命周期会受宿主Activity的生命周期影响。
2、静态创建两个fragment
A 步骤 在显示布局main_activity.xml文件中定义fragment标签 fragment1 fragment2 -------- <fragment ..... />
B 继承Fragment,创建两个类 Fragment1 Fragment2 。注意名称要和上面xml中标签的名字一致。同时另外创建两个xml布局文件(设为f1.xml f2.xml),以为这两个Fragment类创建布局视图
C 类 Fragment1 Fragment2 中,覆写 onCreateView 方法,同时返回 return inflater.inflate(R.layout.f1,null ) ; return inflater.inflate(R.layout.f2,null ) ; 即为两个fragment创建了视图
到此OK
3、动态创建fragment
A、可以不在main_activity.xml文件中定义任何fragment标签,而只在Activity类中动态的添加或删除fragment
B、Activity中的代码如下
//1.判断当前手机的朝向
int width = getWindowManager().getDefaultDisplay().getWidth();
int height = getWindowManager().getDefaultDisplay().getHeight();
Fragment1 fragment1 = new Fragment1();
Fragment2 fragment2 = new Fragment2();
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
if(width>height){
ft.replace(android.R.id.content, fragment1); //水平方向 android.R.id.content指的是当前Activity所在的那个视图。也可为xml文件中的LinearLayout等设置id,然后调用这些id,则会在相应视图中加fragment
}else{ ft.replace(android.R.id.content, fragment2); }
ft.commit();
}
4、利用Fragment创建选项卡
通常选项卡是用ViewPager实现的。但是用Fragment也是可以实现的。也即点击不同的标签,加载不同的fragment即可。例如下代码
public void onClick(View v) {
ft = fm.beginTransaction();
switch (v.getId()) {
case R.id.tab1: ft.replace(R.id.content, new Fragment1());
break;
case R.id.tab2:
ft.replace(R.id.content, new Fragment2());
break;
case R.id.tab3:
ft.replace(R.id.content, new Fragment3());
break;
case R.id.tab4:
ft.replace(R.id.content, new Fragment4());break;
}
ft.commit();
}
R.id.content 是main_activity.xml中的一块显示内容区域的LinearLayout的id
5、两个Fragment之间的通讯。比如点击 Fragment1中的按钮,修改Fragment2中的文本
在类Fragment1中的onCreateView覆写方法中,添加如下代码
View view = inflater.inflate(R.layout.fragment1, null); // 得到fragment1的视图View
Button button = (Button) view.findViewById(R.id.bt); // 通过上面得到的fragment1的视图view,找到fragment1上面的按钮
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
System.out.println("在fragment里面相应了点击事件");
Fragment2 f2 = (Fragment2) getActivity().getFragmentManager().findFragmentById(R.id.fragment2);
// getActivity(). 是指当前得到当前fragment1所绑定的activity(fragment2也绑定在内),再通过Activity的方法getFragmentManager().得到Fragment的Manager,再去通过findFragmentById得到fragment2(当然fragment2的id要事先在main_activity.xml中有定义) 这样就得到了Fragment2
f2.setText("内容变化了..."); // 通过调用Fragment2中内部定义的方法,来修改其内的文本
}
});
添加关于ViewPager的内容
第一步,在xml布局文件中(例如 guide.xml),定义ViewPager的标签,如下:
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
第二步,创建 ViewPager的自定义数据适配器MyPageAdapter,通过继承PageAdapter类,并覆写如下方法实现:
private List<View> views; // 用来盛放 多个页卡的View
public MyPagerAdapter(List<View> views) {
this.views = views;
}
// 实例化(初始化)页卡
@Override
public Object instantiateItem(ViewGroup container, int position) {
container.addView(views.get(position));
return views.get(position);
}
// 销毁页卡
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView(views.get(position));
//super.destroyItem(container, position, object);
}
@Override
public int getCount() {
if (views != null){ return views.size(); }
return 0;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return (view == object); // 官方提示这样写
}
第三步,Guide.java类中(implements ViewPager.OnPageChangeListener ),做如下设置,实现选项卡
private ViewPager viewPager;
private MyPagerAdapter myPagerAdapter;
private List<View> views; // 页卡视图List
private View view1,view2,view3; // 要装载的页卡视图
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.guide);
initView(); // 初始化视图
initData(); // 初始化数据
}
// 初始化视图
private void initView(){
// 将轮播视图装载入views
LayoutInflater inflater = LayoutInflater.from(this);
view1 = inflater.inflate(R.layout.guide1,null);
view2 = inflater.inflate(R.layout.guide2,null);
view3 = inflater.inflate(R.layout.guide3,null);
//view4 = inflater.inflate(R.layout.guide4,null);
views = new ArrayList<View>();
views.add(view1);
views.add(view2);
views.add(view3);
//views.add(view4);
// 实例化adapter
viewPagerAdapter = new ViewPagerAdapter(views);
// 获取viewPager
viewPager = (ViewPager) findViewById(R.id.viewpager);
}
// 初始化数据
private void initData(){
// 设置adapter进viewPager
viewPager.setAdapter(viewPagerAdapter);
// 设置 viewPager的监听
viewPager.setOnPageChangeListener(this);
}
完工 OK