自学android development

 
 

本文章通过runoob.com总结自己需要的知识


Intent
Intent intent = new Intent(OneActivity.this,TwoActivity.this)//OneActivity是包名,TwoActivity是要启动的Activity
第二个Activity可以通过getIntent().getComponent()方法获得该对象,调用getPackageName()获得包名,getClassName()获得类名

自定义Intent
Intent it = new Intent();
it.setAction("my_action");
it.addCategory("my_category");
startActivity(it);
在第二个Activity的Intent中添加以下代码,就能通过Intent开启第二个activity
<activity android:name=".SecondActivity"
        android:label="第二个Activity">
    <intent-filter>
        <action android:name="my_action"/>
        <category android:name="my_category"/>
        <category android:name="android.intent.category.DEFAULT"/>
    </intent-filter>           
</activity>

// 还有很多类似的用法,例如给移动客服10086拨打电话
Uri uri = Uri.parse("tel:10086");
Intent intent = new Intent(Intent.ACTION_DIAL, uri);
startActivity(intent);

Intent传递Bitmap
bitmap默认实现Parcelable接口,直接传递即可
Bitmap bitmap = null;
Intent intent = new Intent();
Bundle bundle = new Bundle();
bundle.putParcelable("bitmap", bitmap);
intent.putExtra("bundle", bundle);

Android系统在每个程序运行的时候创建一个Application对象,而且只会创建一个,所以Application 是单例(singleton)模式的一个类,而且Application对象的生命周期是整个程序中最长的,他的生命 周期等于这个程序的生命周期。如果想存储一些比静态的值(固定不改变的,也可以变),如果你想使用 Application就需要自定义类实现Application类,并且告诉系统实例化的是我们自定义的Application 而非系统默认的,而这一步,就是在AndroidManifest.xml中卫我们的application标签添加:name属性!
class MyApp extends Application {
    private String myState;
    private static MyApp instance;    
    public static MyApp getInstance(){
        return instance;
    }    
    public String getState(){
        return myState;
    }
    public void setState(String s){
        myState = s;
    }
    @Override
    public void onCreate(){
        onCreate();
        instance = this;
    }
}

}
然后在任意地方就可以直接调用:MyApp.getInstance()来获得Application的全局对象!

上面的Application就是基于单例的,单例模式的特点就是可以保证系统中一个类有且只有一个实例。 这样很容易就能实现,在A中设置参数,在B中直接访问了。这是几种方法中效率最高的。
public class XclSingleton  
{  
    //单例模式实例  
    private static XclSingleton instance = null;        
    //synchronized 用于线程安全,防止多线程同时创建实例  
    public synchronized static XclSingleton getInstance(){  
        if(instance == null){  
            instance = new XclSingleton();  
        }     
        return instance;  
    }         
    final HashMap<String, Object> mMap;  
    private XclSingleton()  
    {  
        mMap = new HashMap<String,Object>();  
    }     
    public void put(String key,Object value){  
        mMap.put(key,value);  
    }        
    public Object get(String key)  
    {  
        return mMap.get(key);  
    }        

设置参数:
XclSingleton.getInstance().put("key1", "value1");  
XclSingleton.getInstance().put("key2", "value2");  

如何在一个项目中打开另外一个项目
此方法也可做其他动作,例如返回桌面只需setAction和addCategor.打开百度就setData(Uri).

Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
ComponentName cn = new ComponentName("包名","启动activity");//ComponentName组件名称
intent.setComponent(cn);
startActivity(intent);



Activity
注意事项:
1. onPause()和onStop()被调用的前提是: 打开了一个新的Activity!而前者是旧Activity还可见的状态;后者是旧Activity已经不可见!
2. 另外,AlertDialog和PopWindow是不会触发上述两个回调方法的
3.调用finish()直接关闭当前Activity

5.0提供的新方法public void onCreat(Bundle savedInstanceState, PersistableBundle persistentState)
//需要在文件中配置Activity设置一个属性android:persistableMode="persistAcrossReboots"
一般会搭配以下两个方法来使用
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState)
public void onRestoreInstanceState(Bundle savedInstanceState, PersistableBundle persistentState)
第一个方法方法会在下述情形中被调用:
1.点击home键回到主页或长按后选择运行其他程序
2.按下电源键关闭屏幕
3.启动新的Activity
4.横竖屏切换时,肯定会执行,因为横竖屏切换的时候会先销毁Act,然后再重新创建

重要原则:当系统"未经你许可"时销毁了你的activity,则onSaveInstanceState会被系统调用, 这是系统的责任,因为它必须要提供一个机会让你保存你的数据(你可以保存也可以不保存)。

往这个bundle中写入数据,比如:
outState.putInt("num",1);
这样,然后你在onCreate或者onRestoreInstanceState中就可以拿出里面存储的数据,不过拿之前要判断下是否为null
savedInstanceState.getInt("num");


为Activity设置过场动画

方法一:

A跳转到B,在startActivity(intent)后面加上overridePendingTransition(R.anim.anim_in,R.anim.anim_out)

B返回A,在finish()后面加上overridePendingTransition(R.anim.anim_in,R.anim.anim_out)

方法二:

<!-- 默认Activity跳转动画 -->
<style name="default_animation" mce_bogus="1" parent="@android:style/Animation.Activity">//Activity A跳转到Activity B时Activity B进入动画
    <item name="android:activityOpenEnterAnimation">@anim/default_anim_in</item>//Activity A跳转到Activity B时Activity B进入动画
    <item name="android:activityOpenExitAnimation">@anim/anim_stay</item>//Activity A跳转到Activity B时Activity A退出动画
    <item name="android:activityCloseEnterAnimation">@anim/anim_stay</item>//Activity B返回Activity A时Activity A的进入动画
    <item name="android:activityCloseExitAnimation">@anim/default_anim_out</item>//Activity B返回Activity A时ActivityB的退出动画
</style>

然后修改AppTheme

<style name="AppTheme" mce_bogus="1" parent="@android:style/Theme.Light">
        <item name="android:windowAnimationStyle">@style/default_animation</item>
        <item name="android:windowNoTitle">true</item>
</style>

最后修改下application

<application
   android:icon="@drawable/logo"
   android:label="@string/app_name"
   android:theme="@style/AppTheme" >




Service

相关概念:
程序
:为了完成特定任务,用某种语言编写的一组指令集合(一组静态代码)
进程:运行中的程序,系统调度与资源分配的一个独立单位,操作系统会 为每个进程分配一段内存空间!程序的依次动态执行,经历代码的加载,执行, 执行完毕的完整过程!
线程:比进程更小的执行单元,每个进程可能有多条线程,线程需要放在一个 进程中才能执行,线程由程序负责管理,而进程则由系统进行调度!
多线程的理解:并行执行多个条指令,将CPU时间片按照调度算法分配给各个 线程,实际上是分时执行的,只是这个切换的时间很短,用户感觉到"同时"而已!

创建线程的三种方式:
1.继承Thread类
2.实现Runnable接口
3.实现Callable接口

可以直接这样启动:
new Thread(myThread).start(); 

当更多的时候我们喜欢使用匿名类,即下面这种写法:
new Thread(new Runnable(){
     public void run() {

     //需要执行的方法

     }
         }).start();


Android中使用Service的方式有两种:
1)StartService()启动Service
2)BindService()启动Service
相关方法详解:
onCreate():当Service第一次被创建后立即回调该方法,该方法在整个生命周期 中只会调用一次!
onDestory():当Service被关闭时会回调该方法,该方法只会回调一次!
onStartCommand(intent,flag,startId):早期版本是onStart(intent,startId), 当客户端调用startService(Intent)方法时会回调,可多次调用StartService方法, 但不会再创建新的Service对象,而是继续复用前面产生的Service对象,但会继续回调 onStartCommand()方法!
IBinder onOnbind(intent):该方法是Service都必须实现的方法,该方法会返回一个 IBinder对象,app通过该对象与Service组件进行通信!
onUnbind(intent):当该Service上绑定的所有客户端都断开时会回调该方法!
1)StartService启动Service
①首次启动会创建一个Service实例,依次调用onCreate()和onStartCommand()方法,此时Service 进入运行状态,如果再次调用StartService启动Service,将不会再创建新的Service对象, 系统会直接复用前面创建的Service对象,调用它的onStartCommand()方法!
②但这样的Service与它的调用者无必然的联系,就是说当调用者结束了自己的生命周期, 但是只要不调用stopService,那么Service还是会继续运行的!
③无论启动了多少次Service,只需调用一次StopService即可停掉Service
2)BindService启动Service
①当首次使用bindService绑定一个Service时,系统会实例化一个Service实例,并调用其onCreate()和onBind()方法,然后调用者就可以通过IBinder和Service进行交互了,此后如果再次使用bindService绑定Service,系统不会创建新的Sevice实例,也不会再调用onBind()方法,只会直接把IBinder对象传递给其他后来增加的客户端!
②如果我们解除与服务的绑定,只需调用unbindService(),此时onUnbind和onDestory方法将会被调用!这是一个客户端的情况,假如是多个客户端绑定同一个Service的话,情况如下 当一个客户完成和service之间的互动后,它调用 unbindService() 方法来解除绑定。当所有的客户端都和service解除绑定后,系统会销毁service。(除非service也被startService()方法开启)
③另外,和上面那张情况不同,bindService模式下的Service是与调用者相互关联的,可以理解为 "一条绳子上的蚂蚱",要死一起死,在bindService后,一旦调用者销毁,那么Service也立即终止!
通过BindService调用Service时调用的Context的bindService的解析 bindService(Intent Service,ServiceConnection conn,int flags)
service:通过该intent指定要启动的Service
conn:ServiceConnection对象,用户监听访问者与Service间的连接情况, 连接成功回调该对象中的onServiceConnected(ComponentName,IBinder)方法; 如果Service所在的宿主由于异常终止或者其他原因终止,导致Service与访问者间断开 连接时调用onServiceDisconnected(CompanentName)方法,主动通过unBindService() 方法断开并不会调用上述方法!
flags:指定绑定时是否自动创建Service(如果Service还未创建), 参数可以是0(不自动创建),BIND_AUTO_CREATE(自动创建)


Activity与Service通信

1.自定义Service中,自定义一个Binder类,然后将需要暴露的方法都写到该类中!
2.Service类中,实例化这个自定义Binder类,然后重写onBind()方法,将这个Binder对象返回!
3.Activity类中实例化一个ServiceConnection对象,重写onServiceConnected()方法,然后 获取Binder对象,然后调用相关方法即可!


一个简单前台服务

public void onCreate()
{
    super.onCreate();
    Notification.Builder localBuilder = new Notification.Builder(this);

    //根据自己需求定制Notification
    localBuilder.setContentIntent(PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0));
    localBuilder.setAutoCancel(false);
    localBuilder.setSmallIcon(R.mipmap.ic_cow_icon);
    localBuilder.setTicker("Foreground Service Start");
    localBuilder.setContentTitle("Socket服务端");
    localBuilder.setContentText("正在运行...");

    //调用startForeground(1, notification对象);
    startForeground(1, localBuilder.getNotification());
}




广播的应用Broadcast
定义接收广播
public class MyBroadcastReceiver extends BroadcastReceiver {
    private final String ACTION_BOOT = "com.example.broadcasttest.MY_BROADCAST";
    @Override
    public void onReceive(Context context, Intent intent) {
        if(ACTION_BOOT.equals(intent.getAction()))
        Toast.makeText(context, "收到广播了",Toast.LENGTH_SHORT).show();
    }
}
然后AndroidManifest.xml中注册下,写上Intent-filter:
<receiver android:name=".MyBroadcastReceiver">
    <intent-filter>
        <action android:name="com.example.broadcasttest.MY_BROADCAST"/>
    </intent-filter>
</receiver>
发送广播
sendBroadcast(new Intent("com.example.broadcasttest.MY_BROADCAST"));



内容提供者ContentProvide
uri的获取很重要,uri是通过android存储访问框架(Storage Access Framework)SAF得到的,uri是资源路径
读取收件箱的信息

private void getMsgs(){
    Uri uri = Uri.parse("content://sms/");
    ContentResolver resolver = getContentResolver();
    //获取的是哪些列的信息
    Cursor cursor = resolver.query(uri, new String[]{"address","date","type","body"}, null, null, null);
    while(cursor.moveToNext())
    {
        String address = cursor.getString(0);
        String date = cursor.getString(1);
        String type = cursor.getString(2);
        String body = cursor.getString(3);
        System.out.println("地址:" + address);
        System.out.println("时间:" + date);
        System.out.println("类型:" + type);
        System.out.println("内容:" + body);
    }
    cursor.close();
}
需添加权限
<uses-permission android:name="android.permission.READ_SMS"/>//收信息的权限
<uses-permission android:name="android.permission.READ_CONTACTS"/>//写信息的权限

往收件箱里写信息
private void insertMsg() {
    ContentResolver resolver = getContentResolver();
    Uri uri = Uri.parse("content://sms/");
    ContentValues conValues = new ContentValues();
    conValues.put("address", "123456789");
    conValues.put("type", 1);
    conValues.put("date", System.currentTimeMillis());
    conValues.put("body", "no zuo no die why you try!");
    resolver.insert(uri, conValues);
}

客户端调用,并获取返回的Uri
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private static final int READ_REQUEST_CODE = 1;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button btn_show = (Button) findViewById(R.id.btn_show);
        btn_show.setOnClickListener(this);
    }
    @Override
    public void onClick(View v) {
        Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        intent.setType("image/*");
        startActivityForResult(intent, READ_REQUEST_CODE);
    }
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == READ_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
            Uri uri;
            if (data != null) {
                uri = data.getData();
            }
        }
    }
}//客户端返回uri可以调用

根据uri获取文件参数
public void dumpImageMetaData(Uri uri) {
    Cursor cursor = getContentResolver()
            .query(uri, null, null, null, null, null);
    try {
        if (cursor != null && cursor.moveToFirst()) {
            String displayName = cursor.getString(
                    cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
            //输出display
            int sizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE);
            String size = null;
            if (!cursor.isNull(sizeIndex)) {
                size = cursor.getString(sizeIndex);
            }else {
                size = "Unknown";
            }
            //输出size
        }
    }finally {
        cursor.close();
    }
}//返回的是选中文字的名字和大小

根据Uri获得Bitmap
private Bitmap getBitmapFromUri(Uri uri) throws IOException {
        ParcelFileDescriptor parcelFileDescriptor =
        getContentResolver().openFileDescriptor(uri, "r");
        FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
        Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);
        parcelFileDescriptor.close();
   return image;
}//该方法可以根据uri显示图片

根据Uri获取输入流
private String readTextFromUri(Uri uri) throws IOException {
    InputStream inputStream = getContentResolver().openInputStream(uri);
    BufferedReader reader = new BufferedReader(new InputStreamReader(
            inputStream));
    StringBuilder stringBuilder = new StringBuilder();
    String line;
    while ((line = reader.readLine()) != null) {
        stringBuilder.append(line);
    }
    fileInputStream.close();
    parcelFileDescriptor.close();
    return stringBuilder.toString();
}

创建新文件以及删除文件:
private void createFile(String mimeType, String fileName) {
    Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
    intent.addCategory(Intent.CATEGORY_OPENABLE);
    intent.setType(mimeType);
    intent.putExtra(Intent.EXTRA_TITLE, fileName);
    startActivityForResult(intent, WRITE_REQUEST_CODE);
}
可在onActivityResult()中获取被创建文件的uri
删除文件:
前提是Document.COLUMN_FLAGS包含SUPPORTS_DELETE
DocumentsContract.deleteDocument(getContentResolver(), uri);



                
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值