Activity的使用

MainActivity.java

package a.b.c.myapplication;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

import androidx.activity.EdgeToEdge;
import androidx.activity.result.ActivityResult;
import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContract;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;

public class MainActivity extends AppCompatActivity
{
Button btn_start,btn_startForResult;
String logtag="hyqhyqhyq";
//老方法,通过复写onActivityResult函数来接受返回结构
// @Override
// protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data)
// {
// super.onActivityResult(requestCode, resultCode, data);
//
// if(data == null)
// {
// return;
// }
// if(resultCode == requestCode && requestCode == 234)
// {
// String ret = data.getStringExtra("key1");
// Log.i("This is ret",ret);
// }
// }
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_main);
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
btn_start = findViewById(R.id.btn_startActivity);
btn_start.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view)
{
Intent intent = new Intent(MainActivity.this, SubActivity02.class);//第一个参数:谁下发的命令,第二个参数:打开哪个Activity
startActivity(intent);
}
});
// 新方法接受返回结果
ActivityResultLauncher launcher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult result)
{
Log.i(logtag,result.getData().getStringExtra("key1"));
}
});
btn_startForResult = findViewById(R.id.btn_startActivityGetResult);
btn_startForResult.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view)
{
Intent intent = new Intent(MainActivity.this,SubActivity03.class);
// startActivityForResult(intent,234);
launcher.launch(intent);
}
});

}
}
/*ActivityResultLauncher 和 registerForActivityResult:

ActivityResultLauncher 是一个接口,用于启动目标活动并接收其结果。
registerForActivityResult 是一个新的方法,用于注册一个能够处理特定结果的 ActivityResultLauncher 实例。它接受两个参数:
第一个参数是一个 ActivityResultContract 的实例,用于指定要执行的操作类型。在这里使用的是 ActivityResultContracts.StartActivityForResult(),表示注册一个能够处理 startActivityForResult 操作的 launcher。
第二个参数是一个 ActivityResultCallback<ActivityResult> 的实例,用于处理从目标活动返回的结果。
onActivityResult 方法:

这是注册的 ActivityResultCallback 的实现部分。
当目标活动返回结果时,系统将调用 onActivityResult 方法,并传递一个 ActivityResult 对象作为参数。
在这里,通过 result.getData().getStringExtra("key1") 获取从目标活动返回的数据中名为 "key1" 的字符串数据,并将其记录到日志中。
Log.i(logtag, ...):

Log.i 是 Android 提供的日志输出方法,用于记录信息级别的日志。
logtag 应该是一个字符串常量,用于标识日志的来源或者类别。*/

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/btn_startActivity"
android:text="启动Activity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/btn_startActivityGetResult"
android:text="启动Activity并获取返回结果"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout>

SubActivity02.java

package a.b.c.myapplication;

import android.os.Bundle;
import android.util.Log;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

public class SubActivity02 extends AppCompatActivity
{

@Override
protected void onCreate(@Nullable Bundle savedInstanceState)
{
setContentView(R.layout.activity_sub02);
super.onCreate(savedInstanceState);
Log.i("This is SubActivity02","SubActivity02 onCreate");
}
}

activity_sub02.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<TextView
android:gravity="center"
android:textSize="40dp"
android:text="我是第二个Activity"
android:layout_width="match_parent"
android:layout_height="50dp"/>
</LinearLayout>

SubActivity03.java

package a.b.c.myapplication;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

import androidx.annotation.Nullable;

public class SubActivity03 extends Activity
{
TextView tv;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sub03);
tv = findViewById(R.id.tv_setResult);
tv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view)
{
Intent intent = new Intent();
intent.setClass(SubActivity03.this,MainActivity.class);
intent.putExtra("key1","这是结果1,来自SubActivity03");
setResult(234,intent);
SubActivity03.this.finish();
}
});
}
}

activity_sub03.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<TextView
android:gravity="center"
android:textSize="40dp"
android:text="我是第三个Activity"
android:id="@+id/tv_setResult"
android:layout_width="match_parent"
android:layout_height="50dp"/>
</LinearLayout>

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<TextView
android:gravity="center"
android:textSize="40dp"
android:text="我是第三个Activity"
android:id="@+id/tv_setResult"
android:layout_width="match_parent"
android:layout_height="50dp"/>
</LinearLayout>

Service介绍

Service是android系统的四大组件之一,是一种长生命周期的,没有可视化界面,运行于后台的一种服务程序

启动方式

(1)Started Service被开启的service通过其他组件调用startService()被创建,这种service可以无限地运行下去,必须调用stopSelf()方法或者其他组件调用stopService()来停止它,当service被停止时,系统会销毁它

在清单文件中注册Service

<service android:name=".service.MyService01"></service>

MainActivity.java

btn_startService = findViewById(R.id.btn_startService);
btn_startService.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view)
{
Intent intent = new Intent(MainActivity.this, MyService01.class);
startService(intent);
}
});
btn_stopService = findViewById(R.id.btn_stopService);
btn_stopService.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view)
{
Intent intent = new Intent(MainActivity.this, MyService01.class);
stopService(intent);
}
});

activity_main.xml

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btn_startService"
android:text="启动Service"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btn_stopService"
android:text="停止Service"
/>
</LinearLayout>

(2)Bounded Service被绑定地service是当其他组件(一个客户)调用bindService()来创建的,客户可以通过一个IBinder接口和service进行通信,客户可以通过unbindService()方法来关闭这种连接,一个service可以同时和多个客户绑定,当多个客户都解除绑定之后,系统会销毁service

在清单文件中注册Service

<service android:name=".service.MyBindService"></service>

MainActivity.java

注意:复制粘贴时,启动哪个activity要注意,这里卡了好久

btn_binService = findViewById(R.id.btn_bindService);
btn_binService.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view)
{
Intent intent = new Intent(MainActivity.this,MyBindService.class);
bindService(intent,conn, 0);
}
});
btn_unBindService = findViewById(R.id.btn_unbindService);
btn_unBindService.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view)
{
Intent intent = new Intent(MainActivity.this, MyBindeService.class);
try
{
unbindService(conn);
}
catch (Exception e)
{
e.printStackTrace();
}
}
});

MyBinderService.java

package a.b.c.myapplication.service;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;

import androidx.annotation.Nullable;

public class MyBindService extends Service
{
private MyBinder binder = new MyBinder();

String logTag = "MyBinderService";
public class MyBinder extends Binder
{
public MyBinder()
{
Log.i(logTag,"in MyBinder");
}

public MyBindService getService()
{
return MyBindService.this;
}
}

@Override
public void onCreate()
{
super.onCreate();
}

@Override
public void onDestroy()
{
super.onDestroy();
}

@Nullable
@Override
public IBinder onBind(Intent intent)
{
return binder;
}

@Override
public boolean onUnbind(Intent intent)
{
Log.i(logTag, "onUnbind");
return super.onUnbind(intent);
}
}

BroadcastReceiver介绍

BroadcastReceiver(广播接受器)是Android系统的四大组件之一,用于监听 / 接受 应用发出的广播消息,并做出响应

应用场景:不同组件之间通信(包括应用内 / 不同应用之间);与Android系统在特定情况下的通信(如电话呼入时、网络可用时);多线程通信

Android广播分为两个角色:广播发送者、广播接受者

实现原理

(Android中的广播使用了设计模式中的观察者模式):基于消息的发布/订阅事件模型

模型中有3个角色:

消息订阅者(广播接受者)/消息发布者(广播发布者)/消息中心(AMS,即Activity Manager Service)

广播接收者通过Binder机制在AMS注册

广播发送者通过Binder机制向AMS发送广播

AMS根据广播发送者要求,在已注册列表中,寻找合适的广播接收者(寻找依据:IntentFilter/Permission)

AMS将广播发送到合适的广播接收者相应的消息循环队列中

注册的方式分为两种:静态注册、动态注册

(1)静态注册

在AndroidManifest.xml里面通过标签声明,当此App首次启动时,系统会自动实例化mBroadReceive类,并注册到系统中,静态注册是常驻广播,不受任何组件生命周期的影响

<receiver android:name=".MyReceiver.MyReceiver"
android:exported="false">//android:exported="false" 指定了该接收器是否能被其他应用组件调用或者是从外部调用。false 表示这个接收器仅对自己的应用可见,其他应用无法直接调用它。
<intent-filter>
<action android:name="golvRuleaaa">//<intent-filter> 标签定义了接收器可以处理的广播意图(Intent)过滤器。<action> 标签用于指定接收器要处理的广播动作(Action)。在这个例子中,动作名称是 "golvRuleaaa"。这表示接收器只会对发送这个特定动作的广播进行处理。
</action>
</intent-filter>
</receiver

(2)动态注册

在代码中通过调用Context的regisertReceiver()方法进行动态注册BroadReceiver,注册广播后,要在相应位置记得销毁广播,即在onPause()中unregisertReceiver(mBroadcastReceiver),当此Activity实例化时,会动态将MyBroadcastReceiver注册到系统中,当此Activity销毁时,动态注册的MyBroadReceiver将不再接受到相应的广播

注意:动态广播最好在Activity中的onResume()注册、onPause注销。

原因:

对于动态广播,有注册就必然得有注销,否则会导致内存泄露

重复注册、重复注销也不允许

动态注册是非常驻广播,灵活,跟随组件的生命周期变化

在AndroidManifest.xml中注册,并设置优先级(静态注册)

<receiver android:name=".MyReceiver.OrderReceiver01"
android:exported="false">
<intent-filter android:priority="1000">
<action android:name="golvRuleaaa">
</action>
</intent-filter>
</receiver>
<receiver android:name=".MyReceiver.OrderReceiver02"
android:exported="false">
<intent-filter android:priority="500">
<action android:name="golvRuleaaa">
</action>
</intent-filter>
</receiver>
<receiver android:name=".MyReceiver.OrderReceiver03"
android:exported="false">
<intent-filter android:priority="200">
<action android:name="golvRuleaaa">
</action>
</intent-filter>
</receiver>

在MainActivity中动态注册

OrderReceiver01 orderReceiver01 = new OrderReceiver01();
OrderReceiver02 orderReceiver02 = new OrderReceiver02();
OrderReceiver03 orderReceiver03 = new OrderReceiver03();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("golvRuleaaa");
registerReceiver(orderReceiver01, intentFilter);
registerReceiver(orderReceiver02,intentFilter);
registerReceiver(orderReceiver03,intentFilter);

MainActivity.java(包括了无序广播和有效广播)

btn_sendBroadcast = findViewById(R.id.btn_broadcast);
btn_sendBroadcast.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view)
{
Intent intetnt = new Intent(MainActivity.this, MyReceiver.class);
intetnt.setAction("guolvRuleaaa");
intetnt.putExtra("key2","这是无序广播内容1");
sendBroadcast(intetnt);
}
});

OrderReceiver01 orderReceiver01 = new OrderReceiver01();
OrderReceiver02 orderReceiver02 = new OrderReceiver02();
OrderReceiver03 orderReceiver03 = new OrderReceiver03();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("guolvRuleaaa");
registerReceiver(orderReceiver01, intentFilter);
registerReceiver(orderReceiver02,intentFilter);
registerReceiver(orderReceiver03,intentFilter);

btn_orderBroadcast = findViewById(R.id.btn_orderBroadcast);
btn_orderBroadcast.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view)
{
Intent intent = new Intent();
intent.setAction("guolvRuleaaa");
String data = "这是原始数据";
Bundle extData = new Bundle();

sendOrderedBroadcast(intent,null,new MyReceiver(),null,0,data,extData);
}
});

MyReceiver.java

package a.b.c.myapplication.MyReceiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class MyReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
if(action.equals("guolvRuleaaa"))
{
//Log.i("MyReceiver",intent.getStringExtra("key2"));
String data = getResultData();
Log.i("OrderReceiver01","接受到内容,"+data);
}
}
}

OrderReceiver01.java

package a.b.c.myapplication.MyReceiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class OrderReceiver01 extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
if(action.equals("guolvRuleaaa"))
{
String data = getResultData();
Log.i("OrderReceiver01","接受到内容,"+data);
setResultData("内容已经被修改OrderReceive01修改");
//Log.i("OrderReceiver01",intent.getStringExtra("key2"));
}

}
}

OrderReceiver02.java

package a.b.c.myapplication.MyReceiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class OrderReceiver02 extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
if(action.equals("guolvRuleaaa"))
{
String data = getResultData();
Log.i("OrderReceiver02","接受到内容,"+data);
setResultData("内容已经被修改OrderReceive02修改");
//Log.i("OrderReceiver01",intent.getStringExtra("key2"));
}

}
}

OrderReceiver03.java

package a.b.c.myapplication.MyReceiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class OrderReceiver03 extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
if(action.equals("guolvRuleaaa"))
{
String data = getResultData();
Log.i("OrderReceiver03","接受到内容,"+data);
setResultData("内容已经被修改OrderReceive03修改");
//Log.i("OrderReceiver01",intent.getStringExtra("key2"));
}

}
}