这是我在这里的第一篇文章,因此,如果我不像我必须的那样完整和清晰,请不要怪我。
我对React native还是陌生的,最近我开始开发一个react native应用,该应用可以大声朗读传入的SMS。我已经实现了检索传入消息并大声阅读它们的功能……但前提是应用程序是前台。
那么,您能为我提供一些关于该主题的图书馆或教程吗?
我正在使用配备Android 9的诺基亚5。
我目前使用以下库:
我现在在互联网上搜索了一个多星期(包括Stack Overflow和this example question),但找不到所需的内容。我已经尝试过React-native-background-timer和React-native-background-job。但是我永远无法让后台计时器工作,而且React-native-background-job允许任务每15分钟执行一次(由于Android的限制)。
因此,直到今天我找到this one为止,我读了许多诸如Headless JS之类的文章,解释了如何使用this codeburst tutorial和其他库,并解释了如何开发后台服务来记录音频呼叫。我尝试对其进行调整,但是后台服务永远不会启动。
我必须告诉你,我对Java没有任何了解,因此即使基于教程和React本机文档,以下本机代码也可能包含错误。
当前,启动应用程序时,将调用服务 IncomingSMSService 。该服务是根据上面引用的Codeburst教程开发的,它依赖于Headless JS和JS函数,该函数侦听传入的消息,然后借助React-native-tts大声地读取它们。
这是这两个文件:
IncomingSMSService.java
package com.ava.service;
import android.content.Intent;
import android.os.Bundle;
import com.facebook.react.HeadlessJsTaskService;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.jstasks.HeadlessJsTaskConfig;
public class IncomingSMSService extends HeadlessJsTaskService {
@Override
protected HeadlessJsTaskConfig getTaskConfig(Intent intent) {
Bundle extras = intent.getExtras();
if (extras != null) {
return new HeadlessJsTaskConfig(
"HandleIncomingSMS",
Arguments.fromBundle(extras),
5000,
true
);
}
return null;
}
}
HandleIncomingSMS.js
import { AppRegistry } from 'react-native';
import SmsListener from 'react-native-android-sms-listener';
import Tts from 'react-native-tts';
const HandleIncomingSMS = async (taskData) => {
SmsListener.addListener(message => {
Tts.getInitStatus().then(() => {
Tts.speak(`New message from number ${message.originatingAddress} : ${message.body}`);
});
});
}
AppRegistry.registerHeadlessTask('HandleIncomingSMS', () => HandleIncomingSMS));
这些代码段在此处的BroadcastReceiver( IncomingSMSReceiver.java )中调用:
package com.ava.receiver;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import com.ava.service.IncomingSMSService;
import com.facebook.react.HeadlessJsTaskService;
import java.util.List;
public final class IncomingSMSReceiver extends BroadcastReceiver {
@Override
public final void onReceive(Context context, Intent intent) {
if (!isAppOnForeground((context))) {
Intent service = new Intent(context, IncomingSMSService.class);
context.startService(service);
HeadlessJsTaskService.acquireWakeLockNow(context);
}
}
private boolean isAppOnForeground(Context context) {
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> appProcesses =
activityManager.getRunningAppProcesses();
if (appProcesses == null) {
return false;
}
final String packageName = context.getPackageName();
for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
if (appProcess.importance ==
ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND &&
appProcess.processName.equals(packageName)) {
return true;
}
}
return false;
}
}
我也在AndroidManifest文件中请求了良好的权限,并且我这样注册了服务:
<service
android:name="com.ava.service.IncomingSMSService"
android:enabled="true"
android:label="IncomingSMSService"
/>
<receiver android:name="com.ava.receiver.IncomingSMSReceiver">
<intent-filter android:priority="0">
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
我做错了什么?我什至没有在Android开发者选项的运行服务标签中看到该服务...有什么想法吗?
预先感谢您的帮助。
阅读或观看了this one或this video之类的一些教程后,我设法使我的应用程序在前台运行。现在,它将显示一个持久性通知。
但是,我不知道如何将我的服务和我的Broadcsat接收器“链接”到该通知(目前,仅当应用程序在前台时才调用该服务)。
这是我更新的代码:
// IncomingSMSService
package com.ava.service;
import android.graphics.Color;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.ContextWrapper;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import com.facebook.react.HeadlessJsTaskService;
import com.ava.MainActivity;
import com.ava.R;
public class IncomingSMSService extends Service {
private NotificationManager notifManager;
private String CHANNEL_ID = "47";
private int SERVICE_NOTIFICATION_ID = 47;
private Handler handler = new Handler();
private Runnable runnableCode = new Runnable() {
@Override
public void run() {
Context context = getApplicationContext();
Intent myIntent = new Intent(context, IncomingSMSEventService.class);
context.startService(myIntent);
HeadlessJsTaskService.acquireWakeLockNow(context);
handler.postDelayed(this, 2000);
}
};
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
createNotificationChannel();
}
@Override
public void onDestroy() {
super.onDestroy();
}
public void createNotificationChannel() {
NotificationChannel notificationChannel = new NotificationChannel(CHANNEL_ID, "General", notifManager.IMPORTANCE_HIGH);
notificationChannel.enableLights(true);
notificationChannel.setLightColor(Color.RED);
notificationChannel.setShowBadge(true);
notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
getManager().createNotificationChannel(notificationChannel);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
this.handler.post(this.runnableCode);
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("Ava")
.setContentText("Listening for new messages...")
.setSmallIcon(R.mipmap.ic_launcher_round)
.setContentIntent(contentIntent)
.setOngoing(true)
.build();
startForeground(SERVICE_NOTIFICATION_ID, notification);
return START_NOT_STICKY;
}
private NotificationManager getManager() {
if (notifManager == null) {
notifManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
}
return notifManager;
}
}
我的headlessJS任务:
// HandleIncomingSMS.js
import SmsListener from 'react-native-android-sms-listener';
import Tts from 'react-native-tts';
import Contacts from 'react-native-contacts';
import { text } from 'react-native-communications';
module.exports = async () => {
// To lower other applications' sounds
Tts.setDucking(true);
// Prevent the TTS engine from repeating messages multiple times
Tts.addEventListener('tts-finish', (event) => Tts.stop());
SmsListener.addListener(message => {
Contacts.getAll((err, contacts) => {
if (err) throw err;
const contactsLoop = () => {
contacts.forEach((contact, index, contacts) => {
// Search only for mobile numbers
if (contact.phoneNumbers[0].label === 'mobile') {
// Format the contact number to be compared with the message.oritignatingAddress variable
let contactNumber = contact.phoneNumbers[0].number.replace(/^00/, '+');
contactNumber = contactNumber.replace(/[\s-]/g, '');
// Phone numbers comparison
if (contactNumber === message.originatingAddress) {
if (contact.familyName !== null) {
Tts.speak(`Nouveau message de ${contact.givenName} ${contact.familyName} : ${message.body}`);
} else {
// If the contact doesn't have a known family name, just say his first name
Tts.speak(`Nouveau message de ${contact.givenName} : ${message.body}`);
}
} else if (contactNumber !== message.originatingAddress && index === contacts.length) {
// If the number isn't recognized and if the contacts have been all checked, just say the phone number
Tts.speak(`Nouveau message du numéro ${message.originatingAddress} : ${message.body}`);
}
}
});
}
contactsLoop();
// Redirect to the SMS app
text(message.originatingAddress, message = false);
});
});
}
我还在AndroidManifest.xml文件中添加了良好的权限,如下所示:
...
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
...
我取得了一些进步,但我仍然受阻,因此,如果您有任何想法,请与我们分享!谢谢!