我用android stduio做了一个简单的创意电话和短信应用程序,要求:
1.具有创意的电话拨打,电话接听和短信发送,收到短信
2.正确使用手机传感器
3.掌握监听事件
效果:
activity_main
<?xml version="1.0" encoding="utf-8"?>
<ScrollView 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:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<EditText
android:id="@+id/et_phone_number"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="手机号码"
android:inputType="phone"
android:padding="10dp"
android:background="@android:drawable/editbox_background" />
<include
android:id="@+id/dialpad_layout"
layout="@layout/dialpad_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp" />
<EditText
android:id="@+id/et_message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="短信内容"
android:inputType="textMultiLine"
android:padding="10dp"
android:background="@android:drawable/editbox_background"
android:layout_marginTop="16dp" />
<Button
android:id="@+id/btn_call"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="拨打电话"
android:layout_marginTop="16dp" />
<Button
android:id="@+id/btn_send_sms"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="发送短信"
android:layout_marginTop="16dp" />
<TextView
android:id="@+id/incoming_call_textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="接收到的电话:"
android:textSize="18sp"
android:layout_marginTop="16dp" />
<TextView
android:id="@+id/received_sms_text_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="接收到的短信:"
android:textSize="18sp"
android:layout_marginTop="16dp" />
</LinearLayout>
</ScrollView>
再创建一个新的xml叫做dialpad_layout,并加上以下代码:
<?xml version="1.0" encoding="utf-8"?>
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:rowCount="4"
android:columnCount="3"
android:padding="16dp"
android:background="#FFFFFF">
<!-- Add your buttons here -->
<!-- Add this code inside the GridLayout -->
<Button
android:id="@+id/button1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_columnWeight="1"
android:layout_rowWeight="1"
android:background="?attr/selectableItemBackground"
android:textColor="@android:color/black"
android:text="1"
android:onClick="onClick" />
<Button
android:id="@+id/button2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:text="2"
android:background="?attr/selectableItemBackground"
android:textColor="@android:color/black"
android:onClick="onClick" />
<Button
android:id="@+id/button3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:text="3"
android:background="?attr/selectableItemBackground"
android:textColor="@android:color/black"
android:onClick="onClick" />
<!-- Row 2 -->
<Button
android:id="@+id/button4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:text="4"
android:background="?attr/selectableItemBackground"
android:textColor="@android:color/black"
android:onClick="onClick" />
<Button
android:id="@+id/button5"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:text="5"
android:background="?attr/selectableItemBackground"
android:textColor="@android:color/black"
android:onClick="onClick" />
<Button
android:id="@+id/button6"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:text="6"
android:background="?attr/selectableItemBackground"
android:textColor="@android:color/black"
android:onClick="onClick" />
<!-- Row 3 -->
<Button
android:id="@+id/button7"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:text="7"
android:background="?attr/selectableItemBackground"
android:textColor="@android:color/black"
android:onClick="onClick" />
<Button
android:id="@+id/button8"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:text="8"
android:background="?attr/selectableItemBackground"
android:textColor="@android:color/black"
android:onClick="onClick" />
<!-- Row 4 -->
<Button
android:id="@+id/button9"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:text="9"
android:background="?attr/selectableItemBackground"
android:textColor="@android:color/black"
android:onClick="onClick" />
<Button
android:id="@+id/button_hash"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:text="*"
android:background="?attr/selectableItemBackground"
android:textColor="@android:color/black"
android:onClick="onClick" />
<Button
android:id="@+id/button0"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:text="0"
android:background="?attr/selectableItemBackground"
android:textColor="@android:color/black"
android:onClick="onClick" />
<Button
android:id="@+id/button_star"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:text="#"
android:background="?attr/selectableItemBackground"
android:textColor="@android:color/black"
android:onClick="onClick" />
<Button
android:id="@+id/button_delete"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_columnWeight="1"
android:layout_rowWeight="1"
android:text="删除"
android:textSize="18sp"
android:background="?attr/selectableItemBackground"
android:textColor="@android:color/black"
android:onClick="onClick" />
<!-- Add the rest of the buttons (2-9, 0, *, and #) following the same structure -->
</GridLayout>
接下来让我们写java代码,首先是MainActivity
package com.example.callhj;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.Telephony;
import android.telephony.PhoneStateListener;
import android.telephony.SmsManager;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import android.telephony.TelephonyManager;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private boolean userDeniedDefaultSmsApp = false;
// 请求权限的请求码
private static final int PERMISSION_REQUEST_CODE = 100;
private static final int SET_DEFAULT_SMS_APP_REQUEST = 1;
private static final int PERMISSIONS_REQUEST_READ_PHONE_STATE = 1;
// 用于显示接收到的短信的 TextView
private TextView mReceivedSmsTextView;
// 用于接收来电的广播接收器
private IncomingCallReceiver incomingCallReceiver;
// 用于接收短信的广播接收器
private IncomingSmsReceiver incomingSmsReceiver;
// 用于显示来电号码的 TextView
private TextView incomingCallTextView;
// 声明UI组件变量
TextView tvIncomingCall, tvIncomingSms;
EditText etPhoneNumber, etMessage;
Button btnCall, btnSendSms;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 获取 UI 组件
incomingCallTextView = findViewById(R.id.incoming_call_textview);
mReceivedSmsTextView = findViewById(R.id.received_sms_text_view);
tvIncomingCall = findViewById(R.id.incoming_call_textview);
tvIncomingSms = findViewById(R.id.received_sms_text_view);
etPhoneNumber = findViewById(R.id.et_phone_number);
etMessage = findViewById(R.id.et_message);
btnCall = findViewById(R.id.btn_call);
btnSendSms = findViewById(R.id.btn_send_sms);
Button button1 = findViewById(R.id.button1);
Button buttonDelete = findViewById(R.id.button_delete);
checkReadPhoneStatePermission();
button1.setOnClickListener(this);
buttonDelete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
EditText phoneNumberEditText = findViewById(R.id.et_phone_number);
String currentNumber = phoneNumberEditText.getText().toString();
if (currentNumber.length() > 0) {
phoneNumberEditText.setText(currentNumber.substring(0, currentNumber.length() - 1));
phoneNumberEditText.setSelection(currentNumber.length() - 1);
}
}
});
// 注册一个新的 BroadcastReceiver,以便在接收到来电广播时更新 UI
LocalBroadcastManager.getInstance(this).registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String incomingNumber = intent.getStringExtra(IncomingCallReceiver.EXTRA_INCOMING_NUMBER);
incomingCallTextView.setText("接收到的电话:" + incomingNumber);
}
}, new IntentFilter(IncomingCallReceiver.ACTION_INCOMING_CALL));
// 创建 IncomingSmsReceiver 实例,并注册到 Telephony.Sms.Intents.SMS_RECEIVED_ACTION 广播
incomingSmsReceiver = new IncomingSmsReceiver(this);
registerReceiver(incomingSmsReceiver, new IntentFilter(Telephony.Sms.Intents.SMS_RECEIVED_ACTION));
// 如果运行 Android 6.0 或以上版本,请求所需权限
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String[]{
Manifest.permission.CALL_PHONE,
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.SEND_SMS,
Manifest.permission.RECEIVE_SMS,
Manifest.permission.READ_SMS
}, PERMISSION_REQUEST_CODE);
}
// 注册一个广播接收器来接收发送短信的 Intent
registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String sender = intent.getStringExtra("sender");
String messageBody = intent.getStringExtra("message_body");
updateReceivedSmsTextView(sender, messageBody);
}
}, new IntentFilter("com.example.callhj.INCOMING_SMS"));
// 获取传感器管理器,并注册加速度传感器的监听器
SensorManager sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
Sensor accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sensorManager.registerListener(new ShakeListener(), accelerometer, SensorManager.SENSOR_DELAY_NORMAL);
// 设置拨打电话按钮的点击事件
btnCall.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
callPhoneNumber(etPhoneNumber.getText().toString());
}
});
// 设置发送短信按钮的点击事件
btnSendSms.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
sendSms(etPhoneNumber.getText().toString(), etMessage.getText().toString());
}
});
}
@Override
public void onClick(View v) {
EditText phoneNumberEditText = findViewById(R.id.et_phone_number);
String currentNumber = phoneNumberEditText.getText().toString();
switch (v.getId()) {
case R.id.button1:
currentNumber += "1";
break;
case R.id.button2:
currentNumber += "2";
break;
case R.id.button3:
currentNumber += "3";
break;
case R.id.button4:
currentNumber += "4";
break;
case R.id.button5:
currentNumber += "5";
break;
case R.id.button6:
currentNumber += "6";
break;
case R.id.button7:
currentNumber += "7";
break;
case R.id.button8:
currentNumber += "8";
break;
case R.id.button9:
currentNumber += "9";
break;
case R.id.button0:
currentNumber += "0";
break;
case R.id.button_star:
currentNumber += "*";
break;
case R.id.button_hash:
currentNumber += "#";
break;
default:
break;
}
phoneNumberEditText.setText(currentNumber);
phoneNumberEditText.setSelection(currentNumber.length());
}
private void checkReadPhoneStatePermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
&& checkSelfPermission(Manifest.permission.READ_PHONE_STATE)
!= PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.READ_PHONE_STATE},
PERMISSIONS_REQUEST_READ_PHONE_STATE);
} else {
setupPhoneStateListener();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == PERMISSIONS_REQUEST_READ_PHONE_STATE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
setupPhoneStateListener();
} else {
Toast.makeText(this, "需要电话状态权限才能获取来电号码", Toast.LENGTH_SHORT).show();
}
}
}
private void setupPhoneStateListener() {
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
telephonyManager.listen(new PhoneStateListener() {
@Override
public void onCallStateChanged(int state, String phoneNumber) {
if (state == TelephonyManager.CALL_STATE_RINGING) {
incomingCallTextView.setText("接收到的电话:" + phoneNumber);
}
}
}, PhoneStateListener.LISTEN_CALL_STATE);
}
// onResume() 函数在活动恢复时调用,检查当前应用是否是默认短信应用,如果不是,则尝试将其设置为默认短信应用
@Override
protected void onResume() {
super.onResume();
if (!isDefaultSmsApp() && !userDeniedDefaultSmsApp) {
setDefaultSmsApp();
}
}
// 检查当前应用是否是默认短信应用
private boolean isDefaultSmsApp() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
final String defaultSmsPackageName = Telephony.Sms.getDefaultSmsPackage(this);
final String packageName = getPackageName();
return packageName.equals(defaultSmsPackageName);
}
return false;
}
// 将当前应用设置为默认短信应用
private void setDefaultSmsApp() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
Intent intent = new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);
intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, getPackageName());
startActivityForResult(intent, SET_DEFAULT_SMS_APP_REQUEST);
}
}
// 处理 startActivityForResult() 的结果
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == SET_DEFAULT_SMS_APP_REQUEST) {
if (isDefaultSmsApp()) {
// 成功设置为默认短信应用
Toast.makeText(this, "成功设置为默认短信应用", Toast.LENGTH_SHORT).show();
} else {
// 用户拒绝将应用设置为默认短信应用
Toast.makeText(this, "用户拒绝将应用设置为默认短信应用", Toast.LENGTH_SHORT).show();
userDeniedDefaultSmsApp = true;
}
}
}
// ShakeListener 类实现了加速度传感器的监听器接口,用于检测是否摇晃手机并拨打电话
class ShakeListener implements SensorEventListener {
// 摇晃阈值
private static final int SHAKE_THRESHOLD = 800;
// 上次更新时间
private long lastUpdate;
// 上次 x、y、z 的值
private float lastX, lastY, lastZ;
@Override
public void onSensorChanged(SensorEvent event) {
long currentTime = System.currentTimeMillis();
if ((currentTime - lastUpdate) > 100) {
long diffTime = (currentTime - lastUpdate);
lastUpdate = currentTime;
float x = event.values[0];
float y = event.values[1];
float z = event.values[2];
// 计算加速度变化速度
float speed = Math.abs(x + y + z - lastX - lastY - lastZ) / diffTime * 10000;
// 如果加速度变化速度超过阈值,就拨打电话
if (speed > SHAKE_THRESHOLD) {
callPhoneNumber(etPhoneNumber.getText().toString());
}
lastX = x;
lastY = y;
lastZ = z;
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// Not needed for this example
}
}
// 拨打电话
private void callPhoneNumber(String phoneNumber) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CALL_PHONE}, 1);
} else {
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setData(Uri.parse("tel:" + phoneNumber));
startActivity(callIntent);
}
}
// 发送短信
private void sendSms(String phoneNumber, String message) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.SEND_SMS) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.SEND_SMS}, 2);
} else {
SmsManager smsManager = SmsManager.getDefault();
smsManager.sendTextMessage(phoneNumber, null, message, null, null);
Toast.makeText(getApplicationContext(), "发送成功", Toast.LENGTH_LONG).show();
}
}
// 注销广播接收器
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(incomingCallReceiver);
unregisterReceiver(incomingSmsReceiver);
}
// 更新接收到的短信的 TextView
private void updateReceivedSmsTextView(String sender, String messageBody) {
String newText = "來自: " + sender + "\n短信: " + messageBody + "\n\n";
mReceivedSmsTextView.append(newText);
}
}
请注意复制的时候要更改一下包名,接下来新建一个java class,叫做IncomingCallReceiver类用来接听电话
package com.example.callhj;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.TelephonyManager;
import android.util.Log;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
public class IncomingCallReceiver extends BroadcastReceiver {
public static final String ACTION_INCOMING_CALL = "com.example.callhj.ACTION_INCOMING_CALL";
public static final String EXTRA_INCOMING_NUMBER = "com.example.callhj.EXTRA_INCOMING_NUMBER";
@Override
public void onReceive(Context context, Intent intent) {
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
String incomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
Bundle extras = intent.getExtras();
if (extras != null) {
for (String key : extras.keySet()) {
Log.d("IncomingCallReceiver", "Key: " + key + ", Value: " + extras.get(key));
}
}
// 发送包含来电号码的本地广播
Intent localIntent = new Intent(ACTION_INCOMING_CALL);
localIntent.putExtra(EXTRA_INCOMING_NUMBER, incomingNumber);
LocalBroadcastManager.getInstance(context).sendBroadcast(localIntent);
}
}
}
再新建一个java class叫做IncomingSmsReceiver类用来接受短信
package com.example.callhj;import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.provider.Telephony;
import android.telephony.SmsMessage;public class IncomingSmsReceiver extends BroadcastReceiver {
private Context mContext; // 上下文对象
public IncomingSmsReceiver() {
this.mContext = null;
}
public IncomingSmsReceiver(Context context) {
mContext = context; // 初始化上下文对象
}
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Telephony.Sms.Intents.SMS_RECEIVED_ACTION)) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
Object[] pdus = (Object[]) bundle.get("pdus");
if (pdus != null) {
SmsMessage[] messages = new SmsMessage[pdus.length];
StringBuilder messageBody = new StringBuilder();
String sender = "";
for (int i = 0; i < pdus.length; i++) {
messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
messageBody.append(messages[i].getMessageBody());
if (sender.isEmpty()) {
sender = messages[i].getOriginatingAddress();
}
}
if (mContext != null) {
handleIncomingSms(sender, messageBody.toString());
}
}
}
}
}
// 处理接收到的短信
private void handleIncomingSms(String sender, String messageBody) {
// 在此处处理收到的短信,例如发送广播或更新 UI
// 示例:发送广播给您的 Activity,以便更新 UI
Intent smsReceivedIntent = new Intent("com.example.callhj.INCOMING_SMS");
smsReceivedIntent.putExtra("sender", sender);
smsReceivedIntent.putExtra("message_body", messageBody);
mContext.sendBroadcast(smsReceivedIntent);
}
}
接下来在AndroidManifest.xml中添加权限
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
添加位置:
再添加广播注册代码:
<receiver
android:name=".IncomingCallReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
<receiver
android:name=".IncomingSmsReceiver"
android:permission="android.permission.BROADCAST_SMS"
android:exported="true">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
添加位置,开始和结束的位置:
最后请用真机测试,步骤:
- 首先,在您的手机上启用开发人员选项。通常,这可以在设置中找到。打开设置,然后找到“关于手机”或“设备信息”,然后多次点击“版本号”,直到您看到一条消息,说明您已经成为开发人员。
- 接下来,在设置中找到“开发人员选项”,并启用“USB调试”。这将允许您将手机连接到计算机并通过 Android Studio 进行调试。
- 将手机连接到计算机,使用 USB 数据线将手机连接到计算机的 USB 端口。
- 在 Android Studio 中,单击工具栏上的“运行”按钮,并选择您要运行的应用程序。
- 在运行配置中选择您的手机作为目标设备。
- 然后,您应该能够在手机上看到您的应用程序正在运行,并可以在 Android Studio 中查看日志输出和调试信息。
然后你应该可以运行项目了,此项目有一个小瑕疵,就是别人打电话的时候,只能显示null,而不能正确显示电话号码,其他功能均正常,如果有任何疑问,欢迎留言