因为安卓的知识点较多。平时动看看西看看,easy把东西搞混和搞忘,因此放在这里集中起来,长期更新。
一、AlarmManager的使用
1、AlarmManager。顾名思义,就是“提醒”,是Android中经常使用的一种系统级别的提示服务,在特定的时刻为我们广播一个指定的Intent。简单的说就是我们设定一个时间,然后在该时间到来时,AlarmManager为我们广播一个我们设定的Intent,通常我们使用 PendingIntent,PendingIntent能够理解为Intent的封装包,简单的说就是在Intent上在加个指定的动作。在使用Intent的时候,我们还须要在运行startActivity、startService或sendBroadcast才干使Intent实用。而PendingIntent的话就是将这个动作包括在内了。
定义一个PendingIntent对象。
PendingIntent pi = PendingIntent.getBroadcast(this,0,intent,0);
2、AlarmManager的经常用法有三个:
(1)set(int type,long startTime。PendingIntent pi);
该方法用于设置一次性闹钟,第一个參数表示闹钟类型,第二个參数表示闹钟运行时间,第三个參数表示闹钟响应动作。
(2)setRepeating(int type,long startTime。long intervalTime,PendingIntent pi)。
该方法用于设置反复闹钟。第一个參数表示闹钟类型。第二个參数表示闹钟首次运行时间,第三个參数表示闹钟两次运行的间隔时间。第三个參数表示闹钟响应动作。
(3)setInexactRepeating(int type,long startTime,long intervalTime。PendingIntent pi);
该方法也用于设置反复闹钟,与第二个方法相似,只是其两个闹钟运行的间隔时间不是固定的而已。
3、三个方法各个參数详悉:
(1)int type: 闹钟的类型。经常使用的有5个值:AlarmManager.ELAPSED_REALTIME、 AlarmManager.ELAPSED_REALTIME_WAKEUP、AlarmManager.RTC、 AlarmManager.RTC_WAKEUP、AlarmManager.POWER_OFF_WAKEUP。
AlarmManager.ELAPSED_REALTIME表示闹钟在手机睡眠状态下不可用,该状态下闹钟使用相对时间(相对于系统启动開始),状态值为3。
AlarmManager.ELAPSED_REALTIME_WAKEUP表示闹钟在睡眠状态下会唤醒系统并运行提示功能,该状态下闹钟也使用相对时间,状态值为2;
AlarmManager.RTC表示闹钟在睡眠状态下不可用,该状态下闹钟使用绝对时间。即当前系统时间,状态值为1;
AlarmManager.RTC_WAKEUP表示闹钟在睡眠状态下会唤醒系统并运行提示功能,该状态下闹钟使用绝对时间。状态值为0;
AlarmManager.POWER_OFF_WAKEUP表示闹钟在手机关机状态下也能正常进行提示功能,所以是5个状态中用的最多的状态之中的一个,该状态下闹钟也是用绝对时间,状态值为4。只是本状态好像受SDK版本号影响,某些版本号并不支持;
(2)long startTime: 闹钟的第一次运行时间。以毫秒为单位。能够自己定义时间,只是一般使用当前时间。须要注意的是,本属性与第一个属性(type)密切相关,假设第一个參数对 应的闹钟使用的是相对时间(ELAPSED_REALTIME和ELAPSED_REALTIME_WAKEUP),那么本属性就得使用相对时间(相对于 系统启动时间来说)。比方当前时间就表示为:SystemClock.elapsedRealtime()。假设第一个參数相应的闹钟使用的是绝对时间 (RTC、RTC_WAKEUP、POWER_OFF_WAKEUP),那么本属性就得使用绝对时间。比方当前时间就表示 为:System.currentTimeMillis()。
(3)long intervalTime:对于后两个方法来说。存在本属性,表示两次闹钟运行的间隔时间。也是以毫秒为单位。
(4)PendingIntent pi: 绑定了闹钟的运行动作,比方发送一个广播、给出提示等等。
PendingIntent是Intent的封装类。
须要注意的是,假设是通过启动服务来实现闹钟提 示的话,PendingIntent对象的获取就应该採用Pending.getService(Context c,int i,Intent intent,int j)方法。假设是通过广播来实现闹钟提示的话,PendingIntent对象的获取就应该採用 PendingIntent.getBroadcast(Context c,int i,Intent intent,int j)方法;假设是採用Activity的方式来实现闹钟提示的话。PendingIntent对象的获取就应该採用 PendingIntent.getActivity(Context c,int i,Intent intent,int j)方法。假设这三种方法错用了的话。尽管不会报错,可是看不到闹钟提示效果。
4.举例说明:定义一个闹钟,5秒钟反复响应。
(1)MainActivity,在onCreate中完毕:
- //创建Intent对象,action为ELITOR_CLOCK,附加信息为字符串“你该打酱油了”
- Intent intent = new Intent("ELITOR_CLOCK");
- intent.putExtra("msg","你该打酱油了");
- //定义一个PendingIntent对象,PendingIntent.getBroadcast包括了sendBroadcast的动作。
- //也就是发送了action 为"ELITOR_CLOCK"的intent
- PendingIntent pi = PendingIntent.getBroadcast(this,0,intent,0);
- //AlarmManager对象,注意这里并非new一个对象,Alarmmanager为系统级服务
- AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
- //设置闹钟从当前时间開始,每隔5s运行一次PendingIntent对象pi。注意第一个參数与第二个參数的关系
- // 5秒后通过PendingIntent pi对象发送广播
- am.setRepeating(AlarmManager.RTC_WAKEUP,System.currentTimeMillis(),5*1000,pi);
那么启动MainActivity之后,因为定义了AlarmManager am,而且调用了am.setRepeating(...)函数,则系统每隔5s将会通过pi启动intent发送广播。其action为ELITOR_CLOCK。所以我们须要在Manifest.xml中注冊一个receiver,同一时候自定义一个广播接收器类。
(2)定义一个广播接收器类MyReceiver,重写onReceive()函数。
- public class MyReceiver extends BroadcastReceiver
- {
- @Override
- public void onReceive(Context context, Intent intent)
- {
- // TODO Auto-generated method stub
- Log.d("MyTag", "onclock......................");
- String msg = intent.getStringExtra("msg");
- Toast.makeText(context,msg,Toast.LENGTH_SHORT).show();
- }
- }
(3)在Manifest.xml中注冊广播接收器:
- <receiver android:name=".MyReceiver">
- <intent-filter>
- <action android:name="ELITOR_CLOCK" />
- </intent-filter>
- </receiver>
二、Fragment的使用方法
在Activity用Fragment替换之前已有的布局须要填充满的话。改动Fragment里面返回的布局。
<pre name="code" class="java"> public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // TODO Auto-generated method stub Log.i(Tag, "onCreateView"); View view = LayoutInflater.from(getActivity()).inflate(R.layout.f1, null); // layout = new FrameLayout(getActivity()); view.setLayoutParams(new FrameLayout.LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); return view; }
(1)首先了解其生命周期
onAttach(Activity)
当Fragment与Activity发生关联时调用。
onCreateView(LayoutInflater, ViewGroup,Bundle)
创建该Fragment的视图
onActivityCreated(Bundle)
当Activity的onCreate方法返回时调用
onDestoryView()
与onCreateView想相应,当该Fragment的视图被移除时调用
onDetach()
与onAttach相相应,当Fragment与Activity关联被取消时调用
注意:除了onCreateView,其它的全部方法假设你重写了,必须调用父类对于该方法的实现。
(2)静态使用
定义好Fragment类,加入至xml布局中。
(3)动态使用
- FragmentManager fm = getFragmentManager();
- FragmentTransaction transaction = fm.beginTransaction();
- mWeixin = new ContentFragment();
- transaction.replace(R.id.id_content, mWeixin);
- transaction.addToBackStack(null);
- transaction.commit();
(4)通信
由于全部的Fragment都是依附于Activity的,所以通信起来并不复杂,大概归纳为:
a、假设你Activity中包括自己管理的Fragment的引用,能够通过引用直接訪问全部的Fragment的public方法
b、假设Activity中未保存不论什么Fragment的引用,那么没关系,每一个Fragment都有一个唯一的TAG或者ID,能够通过getFragmentManager.findFragmentByTag()或者findFragmentById()获得不论什么Fragment实例。然后进行操作。
c、在Fragment中能够通过getActivity得到当前绑定的Activity的实例,然后进行操作。
注:假设在Fragment中须要Context,能够通过调用getActivity(),假设该Context须要在Activity被销毁后还存在,则使用getActivity().getApplicationContext()。
(5)处理配置变化
当你执行之后。不断的旋转屏幕,你会发现每旋转一次屏幕。屏幕上就多了一个FragmentOne的实例,而且后台log会打印出很多套生命周期的回调。
- 07-20 08:18:46.651: E/FragmentOne(1633): onCreate
- 07-20 08:18:46.651: E/FragmentOne(1633): onCreate
- 07-20 08:18:46.651: E/FragmentOne(1633): onCreate
- 07-20 08:18:46.681: E/FragmentOne(1633): onCreateView
- 07-20 08:18:46.831: E/FragmentOne(1633): onCreateView
- 07-20 08:18:46.891: E/FragmentOne(1633): onCreateView
那么怎样解决呢:
事实上通过检查onCreate的參数Bundle savedInstanceState就能够推断,当前是否发生Activity的又一次创建:
默认的savedInstanceState会存储一些数据,包含Fragment的实例:通过打印能够看出:
- 07-20 08:23:12.952: E/FragmentOne(1782): Bundle[{android:fragments=android.app.FragmentManagerState@40d0b7b8, android:viewHierarchyState=Bundle[{android:focusedViewId=2131230721, android:views=android.util.SparseArray@40d0af68}]}]
- 所以。我们简单改一下代码,仅仅有在savedInstanceState==null时,才进行创建Fragment实例:
- package com.zhy.zhy_fragments;
- import android.app.Activity;
- import android.app.FragmentManager;
- import android.app.FragmentTransaction;
- import android.os.Bundle;
- import android.util.Log;
- import android.view.Window;
- public class MainActivity extends Activity
- {
- private static final String TAG = "FragmentOne";
- private FragmentOne mFOne;
- @Override
- protected void onCreate(Bundle savedInstanceState)
- {
- super.onCreate(savedInstanceState);
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- setContentView(R.layout.activity_main);
- Log.e(TAG, savedInstanceState+"");
- if(savedInstanceState == null)
- {
- mFOne = new FragmentOne();
- FragmentManager fm = getFragmentManager();
- FragmentTransaction tx = fm.beginTransaction();
- tx.add(R.id.id_content, mFOne, "ONE");
- tx.commit();
- }
- }
- }
如今不管进行多次旋转都仅仅会有一个Fragment实例在Activity中。
如今还存在一个问题。就是又一次绘制时,Fragment发生重建。原本的数据怎样保持?
事实上和Activity类似,Fragment也有onSaveInstanceState的方法。在此方法中进行保存数据,然后在onCreate或者onCreateView或者onActivityCreated进行恢复都能够。
因为篇幅原因,就不贴測试代码了。
三、Popwindow的使用
popwindow可实现导航栏上的弹出菜单。
主要注意下面几点:
(1)找准定位。
通过产生事件的View,获取其Y坐标,加上其本身的高度就是弹出框的Y坐标;获取View的X。即是弹出框的X。
获取位置:
int is[] = new int[2];
v.getLocationOnScreen(is);
在该位置显示:
popupWindow.showAtLocation(v, Gravity.NO_GRAVITY, screenWidth - 10- (popupWindow.getWidth() / 2), h + v.getHeight());
(3)若没有弹出
加入以下语句
ColorDrawable cd = new ColorDrawable(-0000); popupWindow.setBackgroundDrawable(cd);// 加上这句试一试
四、用Action指定活动并用列表显示出来
(1)查询相关的activity
String markString = "com.aretha.demobundle.DEMO"; PackageManager packageManager; List<ResolveInfo> list;
packageManager = getPackageManager(); list = packageManager.queryIntentActivities(new Intent(markString), PackageManager.GET_META_DATA);(2)用适配器显示信息
((TextView) view.findViewById(android.R.id.text1)).setText(info .loadLabel(packageManager));(3)监听列表,跳转到相关的Activity中去
ResolveInfo info = list.get(arg2); ActivityInfo activityInfo = info.activityInfo; Intent intent = new Intent(); intent.setComponent(new ComponentName(activityInfo.packageName, activityInfo.name)); startActivity(intent);</span>