如何在颤振中访问来电的电话号码?

时间:2021-05-03 12:08:34

标签: java android flutter dart

我正在尝试从来电中获取电话号码,对于 Android,我一直在尝试实现 this 答案,但我一直在努力,因为答案不完整,没有示例,而且非常抽象,对于没有任何平台频道知识的人来说很难。

我尝试过的: 我已经在 ServiceReceiver 中实现了鸽子代码,声明了一个我想更新并传递给颤振代码的变量,但是当我接到电话时,该应用程序甚至没有请求任何许可,这让我认为 onReceive () 函数在手机接到来电时不会被调用。

代码如下:

ma​​in.dart:

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import './output.dart';

void main() {
  runApp(MyApp());
}

// void onClick() async {
//   SearchRequest request = SearchRequest()..query = 'test';
//   Api api = Api();
//   SearchReply reply = await api.search(request);
//   print('reply: ${reply.result}');
// }

class MyApp extends StatefulWidget {
  // This widget is the root of your application.
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  static const platform = const MethodChannel('battery.ttsollution.com');
  String _phoneNumber = '';
  String _batteryLevel = 'Unknown battery level.';

  void onClick() async {
    SearchRequest request = SearchRequest()..query = 'test';
    Api api = Api();
    SearchReply reply = await api.search(request);
    print('reply: ${reply.result}');
  }

  Future<void> _getPhoneNumber() async {
    String phoneNumber;
    try {
      final int result = await platform.invokeMethod('getPhoneNumber');
      phoneNumber = "Phone number: $result";
    } catch (e) {
      phoneNumber = "Failed to get the phone number due to: $e";
    }
    setState(() {
      _phoneNumber = phoneNumber;
    });
  }

  Future<void> _getBatteryLevel() async {
    String batteryLevel;
    try {
      final int result = await platform.invokeMethod('getBatteryLevel');
      batteryLevel = 'Battery level at $result % .';
    } on PlatformException catch (e) {
      batteryLevel = "Failed to get battery level: '${e.message}'.";
    }

    setState(() {
      _batteryLevel = batteryLevel;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: [
              ElevatedButton(
                child: Text('Get Phone Number'),
                onPressed: onClick,
              ),
              Text(_batteryLevel),
            ],
          ),
        ),
      ),
    );
  }
}

MainActivity.java:

package com.example.phone_application_java;

import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;

import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugin.common.MethodChannel;

import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.BatteryManager;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.telephony.TelephonyManager;

public class MainActivity extends FlutterActivity {
    private static final String CHANNEL = "battery.ttsollution.com";


    @RequiresApi(api = VERSION_CODES.M)
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Pigeon.Api.setup(getFlutterEngine().getDartExecutor().getBinaryMessenger(), new ServiceReceiver.MyApi());
    }

    @Override
    public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
        super.configureFlutterEngine(flutterEngine);
        new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL)
                .setMethodCallHandler((call, result) -> {
                    // Note: this method is invoked on the main thread.
                    if (call.method.equals("getBatteryLevel")) {
                        int batteryLevel = getBatteryLevel();

                        if (batteryLevel != -1) {
                            result.success(batteryLevel);
                        } else {
                            result.error("UNAVAILABLE", "Battery level not available.", null);
                        }
                    } else {
                        result.notImplemented();
                    }
                });
    }

    private int getBatteryLevel() {
        int batteryLevel = -1;
        if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
            BatteryManager batteryManager = (BatteryManager) getSystemService(BATTERY_SERVICE);
            batteryLevel = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY);
        } else {
            Intent intent = new ContextWrapper(getApplicationContext()).registerReceiver(null,
                    new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
            batteryLevel = (intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) * 100)
                    / intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
        }

        return batteryLevel;
    }

}

ServiceReceiver.java:

package com.example.phone_application_java;

import android.annotation.SuppressLint;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.os.Bundle;

import com.example.phone_application_java.Pigeon;

public class ServiceReceiver extends BroadcastReceiver {
    static String phoneNumber = "Hiya";

    static class MyApi implements Pigeon.Api {
        @Override
        public Pigeon.SearchReply search(Pigeon.SearchRequest arg) {
            Pigeon.SearchReply reply = new Pigeon.SearchReply();
            reply.setResult(ServiceReceiver.phoneNumber);
            return reply;
        }
    }


    @SuppressLint("UnsafeProtectedBroadcastReceiver")
    @Override
    public void onReceive(Context context, Intent intent) {
        TelephonyManager telephony = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        telephony.listen(new PhoneStateListener() {
            @Override
            public void onCallStateChanged(int state, String incomingNumber) {
                super.onCallStateChanged(state, incomingNumber);
                System.out.println("incomingNumber : " + incomingNumber);
                phoneNumber = incomingNumber;
            }
        }, PhoneStateListener.LISTEN_CALL_STATE);
    }

}

AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.phone_application_java">
  <uses-permission android:name="android.permission.READ_PHONE_STATE" />
  <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
  <uses-permission android:name="android.permission.READ_CALL_LOG" />
  <application android:label="phone_application_java" android:icon="@mipmap/ic_launcher">

    <receiver android:name=".ServiceReceiver">
      <intent-filter>
        <action android:name="android.intent.action.PHONE_STATE" />
        <action android:name="android.intent.action.NEW_OUTGOING_CALL" />
      </intent-filter>
    </receiver>
      <activity android:name=".MainActivity" android:launchMode="singleTop" android:theme="@style/LaunchTheme" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:hardwareAccelerated="true" android:windowSoftInputMode="adjustResize">
        <!-- Specifies an Android theme to apply to this Activity as soon as
                 the Android process has started. This theme is visible to the user
                 while the Flutter UI initializes. After that, this theme continues
                 to determine the Window background behind the Flutter UI. -->
        <meta-data android:name="io.flutter.embedding.android.NormalTheme" android:resource="@style/NormalTheme" />
        <!-- Displays an Android View that continues showing the launch screen
                 Drawable until Flutter paints its first frame, then this splash
                 screen fades out. A splash screen is useful to avoid any visual
                 gap between the end of Android's launch screen and the painting of
                 Flutter's first frame. -->
        <meta-data android:name="io.flutter.embedding.android.SplashScreenDrawable" android:resource="@drawable/launch_background" />
        <intent-filter>
          <action android:name="android.intent.action.MAIN" />
          <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
      </activity>
      <!-- Don't delete the meta-data below.
             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
      <meta-data android:name="flutterEmbedding" android:value="2" />
  </application>
</manifest>

颤振医生:

PS E:\Flutter Projects\phone_application_java> flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[√] Flutter (Channel stable, 2.0.6, on Microsoft Windows [Version 10.0.19042.928], locale en-US)
[√] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
[√] Chrome - develop for the web
[√] Android Studio (version 4.1.0)
[√] Connected device (3 available)

• No issues found!

0 个答案:

没有答案