Android源码项目学习

一.天气预报应用

1.spinner的应用

citySpinner=(Spinner)findViewById(R.id.citySpinner);

//设置Spinner的适配器来规定其内容及格式                      Context        Spinner中每一项的布局                         数据源,这里是数组
ArrayAdapter<String> adapter=new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item,ConstData.cities);

//设置Spinner的总体布局
adapter.setDropDownViewResource(android.R.layout.simple_dropdown_item_1line);
citySpinner.setAdapter(adapter);


2.解析XML

通过向google发送一个请求,出现一个关于所选城市天气状况的XML,获得,解析并设置

//获得XML文件的内容,属于IO部分                                                    获得对应URL的输入流

InputStreamReader isr=new InputStreamReader(url.openStream(),"GBK");

InputSource is=new InputSource(isr);      //这一步是为了后面SAX解析



JAVA基础知识:怎么样把inputStream转换为String

BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));   
StringBuilder sb = new StringBuilder();   
 String line = null;   
 while ((line = reader.readLine()) != null) 
sb.append(line + "\n"); 
System.out.print(sb.toString());



//三步得到XMLReader对象

SAXParserFactory spf=SAXParserFactory.newInstance();

SAXParser sp=spf.newSAXParser();

XMLReader xr=sp.getXMLReader();

//设置xr对象的ContentHandler             MyContentHandler继承自DefaultHandler,其中规定了解析对应XML文件的算法

xr.setContentHandler(new MyContentHandler());

xr.parse(is);


//规定XML处理规则的Handler

public class MyContentHandler extends DefaultHandler{

               public void startElement(String uri, String localName, String qName,Attributes attributes) throws SAXException {

                                      //localName代表标签的名字,attributes代表标签的属性         顺带一说字符串的比较用localName.equals("condition")

               }

               

               public voidendElement(String uri, String localName, String qName,Attributes attributes) throws SAXException {

                                    

               }

               public void startDocument() throws SAXException {


       }

               public void endDocument() throws SAXException {

      }

}


3.动态更新布局

//将解析获得的数据动态显示在Activity上,每一个布局对应一天的天气
//这样的布局可以直接用在main.xml布局文件中,标签为<zxc.android.CityWeather.SingleWeatherInfo>
class SingleWeatherInfoView extends LinearLayout{
        private ImageView imageView;
        private TextView textView;
        public SingWeaherInfoVIew(Context context){
               imageView=new ImageView(context);
               textView=new TextView(context);
               this.addView(imageView);
               this.addView(textView);
        }
    
       public void setImageView(String Icon){
                  //从url获得图片生成位图
                URL url=new URL(Icon);
                URLConnection conn=url.openConnection();
                conn.connect();
                InputStream is=conn.getInputStream();
               BufferedInputStream bis=new BufferedInputStream(is);
               Bitmap img=BitmapFactory.decodeStream(bis);
                 bis.close();
                  is.close();
                imageView,setBitmap(img);
       }

        public void setTextView(String text){
              textView.setText(text);
        }
}


总结:薄弱部分在于JAVA IO方面缺乏了解。

JAVA IO File知识补习:

//File构造函数

File(String Path)   File(String Path,String fileName)  File(File dirObj,String fileName)  File(URI uriObj)

File file=new File(/sdcard/data/);

System.out.print(file.getName());      

//还有比较重要的方法  file.getPath()   file.getAbsolutePath()   file.getParent()   file.exists()  file.canWrite()  file.canRead()

//file.isFile()  file.isDirectory()   file.lastModified()   文件大小file.length()   file.renameTo(File new Name);   file.delete()

//如果一个File确定是文件夹   可以用file.listFiles()来返回其下的文件对象数组   file.list()返回储存文件名的数组

//如果要设置listFiles所返回的文件类型  用一个类实现FilenameFilter对象,重写boolean accept()方法  调用时候file.list(new Filter("txt"));

//创建文件夹file.mkdirs();   路径中所有不存在的文件夹都会被创建


JAVA IO 字节流 字符流补习:

字节流InputStream OutputStream

在与字节和其他二进制对象打交道时用字节流

1.FileInputStream可以从文件读取字节

//FileInputStream(String path)  FileInputStream(File fileObj)

FileInputStream fileInputStream=new FileInputStream("1.txt");

fileInputStream.read(n)来读取n个字节   fileInputStream.available()来显示剩余可读字节数


FileOutputStream可以向文件写入字节

//FileOutputStream(String path) FileOutputStream(File fileObj)   FileOutputStream(String path,boolean append) //FileOutputStream(String,path,boolean append)   如果append为true,则文件以添加形式打开

FileOutputStream fileOutputStream=new FileOutputStream("1.txt");   //这个1.txt现在可能还不存在,在文件开始写的时候会创建

byte buf[]="HelloWorld";

for(int i=0;i<buf.size();i++)

fileOutputStream.write(buf[i]);       //一次只能写入一个字节,若要一次输入多个字节,可以用ByteArrayOutputStream

2.BufferedInputStream/BufferedOutputStream缓冲流

一个缓冲流允许Java一次对多个字节执行I/O操作,提高了性能

//BufferedInputStream(InputStream inputStream)  BufferedInputStream(InputStream inputStream,int bufSize)  

BufferedInputStream可以把InputStream包装成缓冲流,从而提高性能

字符流Reader Writer

在与字符,字符串打交道的时候使用字符流,因为字节流不能直接处理Unicode字符

Reader,Writer       //其read(),write()方法读取下一个字符

CharArrayReader,CharArrayWriter

BufferedReader,BufferedWriter  //使用缓冲来增强功能,bufferedReader.readLine()非常好用


二.文件管理应用

大致思路:
1.通过一个路径(???)创建一个File,通过File.listFile()返回得到的文件数组,将其设置在listView上     //根路径只需要"/"
2.每一个listViewItem的点击事件来判断是否为文件,若为文件夹,进行下一步搜索,若为文件,进行对应的处理 
 //如何按照不同的文件类型设置不同item的layout  
3.设置每个文件的长按弹出菜单,对文件进行打开,重命名,删除等操作
//对应文件的打开有通用的规则?

1.设置ListView的adapter

ListView需要设置一个规定每一个item样式和数据源的adapter,可以是ArrayAdapter SimpleAdapter  都是继承自 BaseAdapter
class IconTextAdapter extends BaseAdapter(){
private List<IconText> dirEntries=null;   //设置私有的List来记录得到的Files信息
public IconTextAdapter(Context context,List<IconText> dirs){
}
//需要重写几个方法getCount();getitem();   getItemId()    以及其父类Adapter的getView()方法,这个是设置每个item的layout 
}
//自定义一个layout继承自LinearLayout来做item的layout
class IconTextView extends LinearLayout{
ImageView img=null;TextView txt=null;
public  IconTextView(Context context,IconText file)   //通过构造函数把信息设置生成控件在view中
}
最后在主activity中设置setListAdapter(new IconTextAdapter(this,dirEntries));            //这个dirEntries是File [] dirEntries=new File("/").listFiles();

2.打开各种媒体的文件

Intent intent=new Intent();
intent.setAction(android.content.Intent.ACTION_VIEW);      //setAction里面VIEW大多是想用户展示的东西
//其实这里setAction就是发送广播,只不过接收广播的是android系统已经定义好的BroadCastReceiver
intent.setDataAndType(Uri.fromFile(file),"image/*");  //   "video/*"视频           "audio/*"音乐       用这种格式系统会默认用不同Dialog来处理文件
startActivity(intent);

3.创建Menu菜单选项

public boolean onCreateOptionsMenu(Menu menu){
              // menu.add(groupId,ItemId,order,显示的文本)
                 menu.add(0,0,0,"新建文件夹").setIcon(R.drawable.addfolder);
                 menu.add(0,1,0,"根目录").setIcon(R.drawable.root);
}

public boolean onOptionsItemSelected(MenuItem item){
               //通过item.getItemId()确定选择的菜单项,然后进行相应的操作
}

4.创建文件点击菜单选项

点击文件判断点击的isFile()为true时进行创建文件点击菜单的选项
new AlertDialog.Buider(FileManager.this).setTitle()
                           .setItems(menu,listener)                                                  //String[] menu={"打开","重命名","删除","复制","剪切"};
                           .show();
其中 OnClickListener listener=new DialogInterface.OnClickListener(){
                                  public void onClick(DialogInterface dialog,int which){
                                             
                                  }


总结:对Java 集合部分不熟悉.

Java 集合框架知识补习: 
Collection接口是集合框架的基础,最核心的一些方法add(obj)  clear() contains() equals()等
List接口扩展了Collection,使用基于0的索引,列表可以包含重复的元素
           比如ArrayList<E>             //在Java中标准数组是固定长度的,而ArrayList可以动态的增减长度
           比如LinkedList 实现了链表数据结构
Set接口扩展了Coleection,不允许存在重复的元素,                   比如扩展了Set的SortedSet接口,是升序排列的Set
Queue队列接口扩展了Collection,先进先出    peak()返回顶部元素  remove()删除顶部的元素   比如Deque双端队列

Map映射接口是存储键值对的对象,最核心的一些方法containsKey(Object k)  containsValue(Object v)  get(Object k)   put(K k,V v)  size()
          比如HashMap<String,int> map=new HashMap<String,int>();
                   Hashtable功能与HashMap类似,但不允许null键和null值,而且是同步的(Syncronized)


三.定时情景设置

大概思路:1.设定定时器(???)        2.获得情景设置的接口        3.做出UI界面来控制

1.TabWidget选项卡菜单的设定

class RingProject extends TabActivity{//主activity继承TabActivity
            private TabHost tabHost;            //主要通过TabHost对象来设置整个TabActivity
            public void onCreate(..){
                        tabHost=getTabHost(); 
                        tabHost.addTab(tabHost.newTabSpec("tab1")  //添加一张选项卡名为tab1
                                       .setIndicator("第一个选项卡显示文字",getResources().getDrawable(R.drawable.icon))   //设置这张选项卡的样子
                                       .setContent(R.id.RadioGroup01));    //设置选项卡下面正文部分显示的内容,参数是一个Layout
                        tabHost.addTab(tabHost.newTabSpec("tab_test2")
                   .setIndicator("定时情景模式",getResources().getDrawable(R.drawable.timeprofile))
                   .setContent(R.id.RelativeLayout01));
                        tabHost.addTab(tabHost.newTabSpec("tab_test3")
                   .setIndicator("自定义情景模式",getResources().getDrawable(R.drawable.addprofile))
                   .setContent(R.id.AbsoluteLayout03));
                       tabHost.setBackgroundResource(R.drawable.bg);
                       tabHost.setCurrentTab(0);    //设置当前的tab
                       tabHost.setOnTabChangedListener(new onTabChangeListener{
                                        //当上面的选项图标点击改变的动作
                                        //设定tabHost.setCurrentTab使下面的内容变化
                       });

                       //RadioGroup01下的各个RadioButton被选中的时候执行的方法
                       group01.setOnCheckedChangeListener(new OnCheckedChangeListener(){
                                    public void onCheckedChanged(RadioGroup group,int checkedId){
                                                          //选中的RadioButton改变时候要执行的事件
                                     }
                       });
           }
  
}

2.BroadCastReceiver设置及定义

BroadCastReceiver可以在不同应用程序之间进行信息的传输
在需要发送消息的地方Intent intent=new Intent("someWordsWantedReceiverCanRecognise");  // intent发送方向可以理解为android系统
 //所希望接受的BroadCastReceiver会辨认上述字符串
sendBroadCast(intent);                                                            //发送广播
//当intent发送后,按照intent中字符串来查找一个个BroadCastReceiver对象,找到哪个是目标BroadCastReceiver

class RingBroadCastReciever extends BroadCastReceiver{
                 //设置一些全局的常量表示这个BroadCastReceiver能辨认的几种消息
                 //之所以把这些变量前面都加上包名,是防止与其他程序的BroadCastReceiver的字符冲突,其必须与Manifest.xml中filter中的一致
                 public static final String VIBRATE_CHANGED = "copy.android.RingProject.VIBRATE_CHANGED";
                 public static final String SILENT_CHANGED= "copy.android.RingProject.SILENT_CHANGED";
                 public static final String RV_CHANGED= "copy.android.RingProject..RV_CHANGED";
                 
                 public void onReceive(Context context,Intent intent){
                              //BroadCastReceiver在接受到Intent后要进行的动作
                  }
}

PS:四大组件之一的BroadCastReceiver在使用前也是要在Manifest.xml文件中进行注册的,形式如下
       也是正在这里规定了对应intent所携带的字符串
<receiver android:name="RingBroadcastReceiver">
            <intent-filter>
               <action android:name="com.yarin.android.RingProject.RV_CHANGED" />
               <action android:name="com.yarin.android.RingProject.RING_CHANGED" />
               <action android:name="com.yarin.android.RingProject.VIBRATE_CHANGED" />
               <action android:name="com.yarin.android.RingProject.SILENT_CHANGED" />
            </intent-filter>
</receiver>

也可以动态的进行注册
RingBroadCastReciever   rbcr=new RingBroadCastReceiver();
IntentFilter intentFilter=new IntentFilter();
intentFilter.addAction("copy.android.RingProject.VIBRATE_CHANGED"); 
registerReceiver(rbcr,intentFilter);   //注册进android的Receiver队列中,一般在onStart时注册,在onStop时注销unregisterReceiver()

3.设置定时功能--使用AlarmManager来实现(官方建议:关于计划的操作最好用Handler实现)

在布局文件中放置了一个TimePicker控件,从其中换算出到现在的时间
Data now=new Date();
long hour=timePicker.getCurrentHour()-date.getHours();  //TimePicker控件显示的时间到现在时间的小时差
long minute=timePicker.getCurrentMinute()-date.getMinutes();   //分钟差
long second=date.getSeconds();
long timeLeft=(hour*60+minute)*60*1000-second*1000;  //获得还有多少毫秒

//AlarmManager可以完成在一段时间后执行什么操作,或者间隔一段时间循环执行的操作,在时间到了,警告出现时,与AlamManager相关的BroadCastReceiver就已经自动进行注册了,所以就会启动相关intent
mAlarmManager=(mAlarmManager)getSystemService(Context.ALARM_SERVICE);   //获得系统的mAlarmManager
//mAlarmManager的set需要一个PendingIntent,即挂起的intent,所以先创建PendingIntent
PendingIntent pi=new PendingIntent.getBroadcast(this,0,intent,0);  
//这里的intent就是上面的Intent intent=new Intent("someWordsWantedReceiverCanRecognise"); 


mAlarmManager.set(AlarmManager.RTC_WAKEUP,leftTime,pt);


4.设置手机为响铃,震动,静音

在RIngBroadCastReceiver的onReceive(Context context,Intent intent)方法中设置
AudioManager am=(AudioManager)context.getSystemService(AUDIO_SERVICE);
am.setRingMode(AudioManager.RINGER_MODE_NORMAL);     //AudioManager.RINGER_MODE_VIBRATE设置响铃还是震动
audio.setVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER, AudioManager.VIBRATE_SETTING_OFF);
audio.setVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION, AudioManager.VIBRATE_SETTING_OFF);


四.新浪微博应用开发

1.设置开机画面

应用程序的入口,设置好一个显示各种ImageView的布局就好,再设置一下Activity的背景图片

2.存储OAuth认证-----操作SQLite数据库

//采用OAuth认证,需要先得到用户的UserID,Access Token,Access Secret这三样数据才能调用新浪开放接口
//因此每次应用打开时检验SQLite数据库中是否存放有对应数据,如果没有,获得它们并存入数据库
//这里使用SQLiteOpenHelper类来操作数据库
//SQLiteOpenHeler在实例化的时候会要求数据库名,所以一个SQLiteOpenHelper对应一个database
class MySQLiteHelper extends SQLiteOpenHelper{
          ...    onCreate(SQLitedatabase db){
                       //在openHelper创建时候要执行的操作,这里创建一个users表
                       db.exec("create table users(.......)");
                 }
                 onUpgrade(){
                         
                 }
}


再封装成一些基本的方法
//查找数据库中是否存在对应user_id的用户
public boolean existsUser(String user_id){
       使用db.query(...)的函数
       Cursor cursor=db.quert(.....);   //query出来的数据需要使用cursor来处理,cursor.moveToFirst();
                     //while(!cursor.isAfterLast()){    System.out.println(cursor.getString(0));  //括号里0,1,2代表列的索引
}
//数据库插入新的用户
public long newUser(UserInfo user_info){
      使用db.insert(......);
}
//更新用户的OAuth协议内容
public long updateUser(String user_id,String token,String token_secret){
        db.update(........);                  //也可以使用db.exec(sql) 但是在这个函数没有返回值,不能知道是否操作成功
}
//更新用户的昵称和头像
public long updateUser(String nickName,Bitmap bitmap,String user_id){
}

3.获得OAuth认证


posted @ 2012-02-16 00:59  nightkidzxc  阅读(354)  评论(0编辑  收藏  举报