读一读

一、将数据存储到文件中

Context类中提供了一个openFileOutput()方法,可以将数据存储到指定的文件中。接受两个参数,第一个是文件名,第二个是文件的操作模式,主要有两种可选,MODE_PRIVATE和MODE_APPEND。MODE_ORIVATE表示覆盖内容,MODE_APPEND表示追加内容。两种模式都会在文件不存在的时候闯将文件。

public void Save(String inputText)
{
    FileOutputStream out = null;
    BufferedWriter writer = null;
    try {
        out = openFileOutput("data", Context.MODE_PRIVATE);
        writer = new BufferedWriter(new OutputStreamWriter(out));
        writer.write(inputText);
    }catch (IOException e)
    {
        e.printStackTrace();
    }
    finally {
        try{
            if(writer != null)
                writer.close();
        }catch (IOException e)
        {
            e.printStackTrace();
        }
    }
}

protected void onDestroy() {
    super.onDestroy();
    Save(edit.getText().toString());
}


二、从文件中读取数据

Context类中提供了一个openFileInput()方法,用于从文件中读取数据,接受一个文件名参数。

public String load()
{
    FileInputStream in = null;
    BufferedReader reader = null;
    StringBuilder content = new StringBuilder();
    try{
        in = openFileInput("data");
        reader = new BufferedReader(new InputStreamReader(in));
        String line = "";
        while((line = reader.readLine()) != null)
        {
            content.append(line);
        }
    }catch (IOException e)
    {
        e.printStackTrace();
    }
    finally {
        try{
            reader.close();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }

    return content.toString();
}

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView((R.layout.first_layout));

    edit = (EditText) findViewById(R.id.edit);
    String inputText = load();
    if(!TextUtils.isEmpty(inputText))
    {
        edit.setText(inputText);
        edit.setSelection(inputText.length());
        Toast.makeText(Main2Activity.this,"加载数据成功",Toast.LENGTH_SHORT).show();
    }
}

使用本地广播可以避免广播被其他任何应用程序接收到,同时广播接收器也只能接收来自本应发出的广播,这样就可以避免其他应用程序广播的污染了。

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView((R.layout.first_layout));
    
    localBroadcastManager = LocalBroadcastManager.getInstance(Main2Activity.this);
    rece = new BootCompleteReceiver();
    IntentFilter iF = new IntentFilter();
    iF.addAction("group.chicai.study.JJJ");
    localBroadcastManager.registerReceiver(rece,iF);

    Button button9 = (Button)findViewById(R.id.button9);
    button9.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent intent = new Intent("group.chicai.study.JJJ");
            localBroadcastManager.sendBroadcast(intent);
        }
    });
}

protected void onDestroy() {
    super.onDestroy();
    localBroadcastManager.unregisterReceiver(rece);
}


public class BootCompleteReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context,"啦啦啦空间啊沙发哈会计法哈克金凤凰",Toast.LENGTH_LONG).show();
    }
}

一、多个广播接收器

public class MyReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {

        Toast.makeText(context,"接受到我的广播",Toast.LENGTH_SHORT).show();
        abortBroadcast();//截断消息广播
    }
}

public class MyReceiver2 extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context,"接受自定义2",Toast.LENGTH_SHORT).show();
    }
}

二、注册广播接收器,并指定接收顺序。android:priority越高表示优先通知

<receiver
    android:name=".MyReceiver"
    android:enabled="true"
    android:exported="true">
    <intent-filter android:priority="100">
        <action android:name="group.chicai.study.MYBOASTCASE" />
    </intent-filter>
</receiver>
<receiver
    android:name=".MyReceiver2"
    android:enabled="true"
    android:exported="true"
    >
    <intent-filter android:priority="99">
        <action android:name="group.chicai.study.MYBOASTCASE" />
    </intent-filter>
</receiver>

三、发送有序广播

Button button8 = (Button)findViewById(R.id.button8);
button8.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Intent intent = new Intent("group.chicai.study.MYBOASTCASE");
        sendOrderedBroadcast(intent,null);//就是换了个方法发送
    }
});

标准广播是一种完全异步执行的广播,广播发出后,所有的广播接收器几乎都会在同一时刻接收到这条广播消息。无法被截断。

一、新建广播接收器,右键New->Other->Broadcast Receiver,就会创建一个广播接收器

package group.chicai.study;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;

public class MyReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {

        Toast.makeText(context,"接受到我的广播",Toast.LENGTH_SHORT).show();
        abortBroadcast();

    }
}

二、注册这个广播接收器的触发行为

<receiver
    android:name=".MyReceiver"
    android:enabled="true"
    android:exported="true">
    <intent-filter ><!-- 静态注册 -->
            <action android:name="group.chicai.study.MYBOASTCASE" />
    </intent-filter>
</receiver>
//动态注册
intentFilter = new IntentFilter();
intentFilter.addAction("group.chicai.study.MYBOASTCASE");
MyReceiver my = new MyReceiver();
registerReceiver(my,intentFilter);

三、发送广播

Button button8 = (Button)findViewById(R.id.button8);
button8.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Intent intent = new Intent("group.chicai.study.MYBOASTCASE");
        sendBroadcast(intent);
    }
});


同样的,系统上定义了很多检查状态改变的action,可以让接收器去注册这个行为,这样当系统的某些状态改变时,就会触发这些接收器了。例如:网络改变的监督-android.net.conn.CONNECTIVITY_CHANGE


public class SystemUtil {
    /*
    *获取电量 context为UnityPlayer.currentActivity 。
     */
    public static float MonitorBatteryState(Context context)
    {
        IntentFilter iFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
        Intent intent = context.registerReceiver(null, iFilter);
        int rawLevel = intent.getIntExtra("level", 0);      //获得当前电量
        int scale = intent.getIntExtra("scale", 0);         //获得总电量
        //int status = intent.getIntExtra("status", 0);       //电池充电状态
        return (float)rawLevel / (float)scale;
    }

    //获取Wifi信号强度 context为UnityPlayer.currentActivity 。
    @SuppressWarnings("deprecation")
    public static int ObtainWifiInfo(Context context)
    {
        int strength = 0;
        WifiManager wifiManager = (WifiManager)context.getSystemService(WIFI_SERVICE);
        WifiInfo info = wifiManager.getConnectionInfo();
        if(info.getBSSID() != null)
        {
            //链接信号强度
            strength = WifiManager.calculateSignalLevel(info.getRssi(), 5);
        }
        return  strength;
    }

    //获取手机网络信号 context为UnityPlayer.currentActivity 。
    public static int getMobileSignLevel(Context context)
    {
        int dbm = -1;
        int level = 0;
        TelephonyManager tm = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
        List<CellInfo> cellInfoList = tm.getAllCellInfo();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1)
        {
            if (null != cellInfoList)
            {
                for (CellInfo cellInfo : cellInfoList)
                {
                    if (cellInfo instanceof CellInfoGsm)
                    {
                        CellSignalStrengthGsm cellSignalStrengthGsm = ((CellInfoGsm)cellInfo).getCellSignalStrength();
                        level = cellSignalStrengthGsm.getLevel();
                    }
                    else if (cellInfo instanceof CellInfoCdma)
                    {
                        CellSignalStrengthCdma cellSignalStrengthCdma = ((CellInfoCdma)cellInfo).getCellSignalStrength();
                        level = cellSignalStrengthCdma.getLevel();
                    }
                    else if (cellInfo instanceof CellInfoWcdma)
                    {
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2)
                        {
                            CellSignalStrengthWcdma cellSignalStrengthWcdma = ((CellInfoWcdma)cellInfo).getCellSignalStrength();
                            level =  cellSignalStrengthWcdma.getLevel();
                        }
                    }
                    else if (cellInfo instanceof CellInfoLte)
                    {
                        CellSignalStrengthLte cellSignalStrengthLte = ((CellInfoLte)cellInfo).getCellSignalStrength();
                        level = cellSignalStrengthLte.getLevel();
                    }
                }
            }
        }

        return level;
    }
}

可以在AndroidManifiest.xml文件中设置活动的启动模式

<activity android:name=".Main23Activity"
    android:launchMode="singleTop">
</activity>


一共有四种启动模式:

一、standard,Android默认的启动模式,对于这种活动,每次启动都会创建一个新的实例到返回栈中。

二、singleTop,对于这种模式的活动,启动时会先去返回栈栈顶中检查是否是这个活动,是的话就直接使用它,否则就会创建新的实例。

三、singleTask,对于这种模式的活动,只要返回栈中存在这个活动,都会启用它,如果没有才会创建新的实例。

四、singleInstance,对于这种模式的活动,会使用一个单独的返回栈来管理这种活动。

图片.png


Android的活动是可以层叠的。Android使用任务(Task)来管理活动,一个任务就是一组存放在栈里的活动的集合,这个栈叫做返回栈。

图片.png


活动类中定义了7个回调方法,覆盖了活动生命周期的每一个环节。

onCreate(),它会在活动第一次被创建的时候调用,在这里完成活动的初始化操作,比如加载布局、绑定事件等。

onStart(),它会在活动由不可见变为可见的时候调用。

onResume(),它会在活动准备好和用户交互的时候调用。此时活动一定位于返回栈的栈顶,并且处于运行状态。

onPause(),这个方法在系统准备去启动或恢复另一个活动的时候调用。通常做一些释放资源和保存关键数据的操作,执行速度要快。

onStop(),这个方法在活动完全不可见的时候调用,和onPause的主要区别在于,启动的活动为对话框时,onPause会执行,onStop不会执行

onDestroy(),这个方法在活动被销毁之前调用,之后活动的状态将变为销毁状态。

onRestart(),这个方法在活动由停止状态变为运行状态之前调用,也就是活动被重新启动了。

图片.png


一、向下一个活动传递数据

Button button3 = (Button) findViewById(R.id.button3);
button3.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Intent intent = new Intent(Main2Activity.this,Main23Activity.class);
        intent.putExtra("name","chicai");//向intent添加参数,key,value形式
        startActivity(intent);
    }
});
public class Main23Activity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main23);
        Intent intent = getIntent();
        TextView text = (TextView) findViewById(R.id.textView);
        text.setText(intent.getStringExtra("name"));
    }
}



二、向上一个活动传递数据

Button button3 = (Button) findViewById(R.id.button3);
button3.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Intent intent = new Intent(Main2Activity.this,Main23Activity.class);
        intent.putExtra("name","chicai");
        startActivityForResult(intent,1);//意思了开启一个活动用来获取结果的,1是用来辨识不同的这种Activity
    }
});
//用这个活动设置返回结果,然后结束就会传递到上一个活动了
public class Main23Activity extends AppCompatActivity {
    @Override
    protected void onStart() {
        super.onStart();
        Button button = (Button)findViewById(R.id.button7);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent();
                intent.putExtra("return_val","memeda");
                setResult(RESULT_OK,intent);//设置结果
                finish();
            }
        });
    }
}
//返回上一个活动,通过onActivityResult接收
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch(requestCode)
    {
        case 1:
            if(resultCode == RESULT_OK)
            {
                String str = data.getStringExtra("return_val");
                TextView text = (TextView) findViewById(R.id.textView2);
                text.setText(str);
            }
            break;

    }
}

例如我要在浏览器中打开一个网址,我们就可以这样写一个Intent。当手机上的应用有声明这个Action为android.intent.action.VIEW并且data的声明的scheme为http的活动时,就会被相应的激活。

Button button5 = (Button)findViewById(R.id.button5);
button5.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Intent intent = new Intent(Intent.ACTION_VIEW);//android.intent.action.VIEW
        intent.setData(Uri.parse("http://www.chicai.group"));//设置一个uri
        startActivity(intent);
    }
});


intent.setData对应的声明就是data标签写的属性 :

android:scheme用于指定数据的协议部分,如http

android:host用于指定数据的主机名部分,如www.chicai.group

android:port用于指定数据的端口部分

android:path用于指定主机名和端口之后的部分

android:mimeType用于指定可以处理的数据类型,允许使用通配符的方式进行指定。

<intent-filter>  
<action android:name="android.intent.action.VIEW"/>  
<category android:name="android.intent.category.DEFAULT" />  
<category android:name="android.intent.category.BROWSABLE" />  
<data android:scheme="http" android:host="主机名" android:path="/open"/>  
</intent-filter>


再例如打电话:

Button button6 = (Button)findViewById(R.id.button6);
button6.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Intent intent = new Intent(Intent.ACTION_DIAL);
        intent.setData(Uri.parse("tel:10086"));
        startActivity(intent);
    }
});

Intent是Android程序中各组件之间进行交互的一种重要方式,不仅可以指明当前组件想要执行的动作,还可以在不同组件之间传递数据。Intent一般可被用于启动活动、启动服务以及发送光比等场景。可以通过Intent从一个活动跳转到另外一个活动,实现活动和活动之间的交换。


一、显式Intent

Button button3 = (Button) findViewById(R.id.button3);
button3.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        //第一个参数为启动活动的上下文,第二个为需要启动的目标活动
        Intent intent = new Intent(Main2Activity.this,Main23Activity.class);
        startActivity(intent);//启动目标活动
    }
});



二、隐式Intent

在配置文件AndroidManifest.xml中,配置一些activity的参数,通过这些行为参数来让Android来判断是否启动这个活动。需要同时满足这些条件才会激活这个活动。category是可以添加多个的。

<activity android:name=".Main23Activity">
    <intent-filter>
        <action android:name="group.chicai.study.ACTION_START"></action>
        <category android:name="android.intent.category.DEFAULT"></category>
    </intent-filter>
</activity>
Button button4 = (Button) findViewById(R.id.button4);
button4.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Intent intent = new Intent("group.chicai.study.ACTION_START");
        intent.addCategory("android.intent.category.DEFAULT");
        startActivity(intent);
    }
});