从一年开始,我一直在研究物联网产品,所附的应用程序工作正常。现在我无法在更高版本的android中以编程方式接受调用。功能对产品非常重要。任何帮助都非常感谢。
在安全补丁更新 2016年11月之前,Runtime.getRunTime.exec("Command")
正常以编程方式接受呼叫。
Runtime.getRuntime().exec("input keyevent " +Integer.toString(KeyEvent.KEYCODE_HEADSETHOOK));
如何在Nougat版本的android中实现它。
寻找任何类型的黑客。
我已经为增强功能打开了一个帖子。
注意* 如果您中的任何一方遇到同样的问题,请向Android Dev Team
请求加入并提供规定以获得用户的运行时权限。按照上面提到的URL来请求。
答案 0 :(得分:8)
由于我也在研究物联网产品,这是我遇到的最大问题之一,但经过一些研究,我认为我找到了解决这个问题的方法,或者你可以说一个简单的黑客。 我已经在几个版本的多个设备中测试了这个hack,并发现大多数设备都在响应。只有三星设备没有响应,一些华为设备和一些Oppo设备也没有响应。(我还在寻找这些设备的东西)。
我注意到Android提供了访问通知的一项功能。您可以使用 NotificationListenerService 来读取通知并对其执行某些操作。 它提供了一些覆盖方法:
onNotificationPosted()
onNotificationRemoved()
getActiveNotifications()
...等
这是一个代码: 创建一个扩展NotificationListenerService的服务
class NLService extends NotificationListenerService {
@Override
public void onNotificationPosted(StatusBarNotification sbn) {
....
}
@Override
public void onNotificationRemoved(StatusBarNotification sbn) {
....
}
在AndroidMenifest中,将此服务添加为:
<service
android:name=".NLService"
android:label="@string/app_name"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
<intent-filter>
<action
android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
这将允许您的应用程序阅读收到的任何通知。
现在,这是主要代码:
在onNotificationPosted(StatusBarNotification sbn)中添加以下代码:
@Override
public void onNotificationPosted(StatusBarNotification sbn) {
try {
if (sbn.getNotification().actions != null) {
for (Notification.Action action : sbn.getNotification().actions)
{
Log.e(TAG, "" + action.title);
if (action.title.toString().equalsIgnoreCase("Answer")) {
Log.e(TAG, "" + true);
PendingIntent intent = action.actionIntent;
try {
intent.send();
} catch (PendingIntent.CanceledException e) {
e.printStackTrace();
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
多数民众赞成!
全部设置,运行应用程序和三星以外的设备,无论哪个显示来电通知,使用应答和拒绝/拒绝操作按钮,都可以接听电话。
要打开通知访问设置并允许您的应用程序阅读通知,请使用:
Intent intent = new
Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
startActivity(intent);
为此创建一个POC,让我知道它是如何工作的。
如果有帮助,请标记我的答案。
另外,如果您能为Samsung Devices提供相同的解决方案,请更新。
由于
答案 1 :(得分:0)
有点黑客,您可以使用accessibility service接听电话。要启用辅助功能服务,您必须在设置 - 辅助功能 - 您的服务上启用您的服务。
首先,将typeWindowContentChanged添加到accessibilityEventTypes。
<accessibility-service
android:accessibilityEventTypes="typeViewClicked|typeViewFocused|typeViewScrolled|typeWindowContentChanged|typeWindowStateChanged"
android:packageNames="com.example.android.myFirstApp, com.example.android.mySecondApp"
android:accessibilityFeedbackType="feedbackSpoken"
android:notificationTimeout="100"
android:settingsActivity="com.example.android.apis.accessibility.TestBackActivity"
android:canRetrieveWindowContent="true"
/>
使用事件或&#34;显示文字&#34;做一些事情。或&#34;内容说明&#34;。
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
// Do something with Click or Focused event
final int eventType = event.getEventType();
String eventText = null;
switch(eventType) {
case AccessibilityEvent.TYPE_VIEW_CLICKED:
eventText = "Focused: ";
break;
case AccessibilityEvent.TYPE_VIEW_FOCUSED:
eventText = "Focused: ";
break;
}
eventText = eventText + event.getContentDescription();
// Traverse all items in screen.
// Do something with text.
AccessibilityNodeInfo info = getRootInActiveWindow();
int index;
int count = info.getChildCount();
AccessibilityNodeInfo child;
for (index = 0; index < count; index++) {
child = info.getChild(index);
if (child.getText() != null)
Log.d(TAG, "text: " + child.getText().toString() + " " + child.getContentDescription());
// perform Click
//if (child.isClickable());
//child.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
}
是的,我知道这不是解决问题的优雅方式。这是一种黑客行为。
答案 2 :(得分:0)
要使用按钮接听电话,请在检测到来电时设置标志:
if(state==TelephonyManager.CALL_STATE_RINGING){
shouldAnswerCallViaNotification = true;
} else {
shouldAnswerCallViaNotification = false;
}
现在,在NSLogService类中创建一个列表
static ArrayList<StatusBarNotification> statusBarNotifications;
并在onNotificationPosted()中将StatusBarNotification添加到列表中,
@Override
public void onNotificationPosted(StatusBarNotification sbn) {
if (HomeScreen.shouldAnswerCallViaNotification) {
if (statusBarNotifications == null) {
updateNotificationList();
}
statusBarNotifications.add(sbn);
} else {
updateNotificationList();
}
}
public static ArrayList<StatusBarNotification> getAllNotifications() {
return statusBarNotifications;
}
public static void updateNotificationList() {
if (statusBarNotifications != null)
statusBarNotifications = null;
statusBarNotifications = new ArrayList<StatusBarNotification>();
}
在您的主屏幕中,点击按钮,然后拨打performNotificationOperation(NLService.getAllNotifications());
这是此方法的定义:
private void performNotificationOperation(ArrayList<StatusBarNotification> activeNotifications) {
if (activeNotifications.size()> 0) {
main_Loop:
for (StatusBarNotification notification : activeNotifications) {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (notification.getNotification().actions != null) {
for (Notification.Action action : notification.getNotification().actions) {
// Log.e(TAG, "" + action);
Log.e(TAG, "" + action.title);
if (action.title.toString().equalsIgnoreCase("Answer")) {
Log.e(TAG, "" + true);
PendingIntent intent = action.actionIntent;
try {
intent.send();
} catch (PendingIntent.CanceledException e) {
e.printStackTrace();
}
break main_Loop;
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
try {
NLService.updateNotificationList();
} catch (Exception e) {
e.printStackTrace();
}
}
答案 3 :(得分:0)
根据“ Vishal Sharma ”的答案,我们可以动态获取操作按钮标题,以支持其他语言:
@Override
public void onNotificationPosted(StatusBarNotification sbn) {
try {
if (sbn.getNotification().actions != null) {
Notification.Action[] notificationAction=sbn.getNotification().actions;
//Log.e(G.TAG, "" +notificationAction + " =>"+notificationAction.length);
String rejectTitle=""+notificationAction[0].title;
String acceptTitle=""+notificationAction[1].title;
for (Notification.Action action : notificationAction){
if (action.title.toString().equalsIgnoreCase(acceptTitle)) {
PendingIntent intent = action.actionIntent;
try {
intent.send();
} catch (PendingIntent.CanceledException e) {
e.printStackTrace();
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}