0

I'm building a call screener app for Android using the CallScreeningService API. When I run the app, it registers the service OK but when I call the emulator, I get the following exception:

Java.Lang.RuntimeException: 'Unable to create service com.katoapps.callblocker.CallBlockerService: java.lang.ClassNotFoundException: Didn't find class "com.katoapps.callblocker.CallBlockerService" on path: DexPathList[[zip file "/data/app/~~OvboC6Rbk2k7eFeBnJFlKg==/com.katoapps.callblocker-aJoY2QavLWrfwVyoFIXSMA==/base.apk"],nativeLibraryDirectories=[/data/app/~~OvboC6Rbk2k7eFeBnJFlKg==/com.katoapps.callblocker-aJoY2QavLWrfwVyoFIXSMA==/lib/x86_64, /data/app/~~OvboC6Rbk2k7eFeBnJFlKg==/com.katoapps.callblocker-aJoY2QavLWrfwVyoFIXSMA==/base.apk!/lib/x86_64, /system/lib64, /system_ext/lib64]]'

Here's CallBlockerService (located in /Platforms/Android/CallBlockerService.cs)

namespace CallBlocker;

using Android.App;
using Android.Telecom;

[Service(Exported = true, Permission = "android.permission.BIND_SCREENING_SERVICE")]
[IntentFilter(new string[] { "android.telecom.CallScreeningService" })]
public class CallBlockerService : CallScreeningService
{
    public override void OnScreenCall(Call.Details callDetails)
    {
    }
}

The main activity that registers the service:

using Android.App;
using Android.App.Roles;
using Android.Content;
using Android.Content.PM;
using Android.OS;

namespace CallBlocker;

[Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)]
public class MainActivity : MauiAppCompatActivity
{
    private static int REQUEST_ID = 1;

    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        RoleManager roleManager = (RoleManager)GetSystemService(RoleService);
        Intent intent = roleManager.CreateRequestRoleIntent(RoleManager.RoleCallScreening);
        StartActivityForResult(intent, REQUEST_ID);
    }

    protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
    {
        if (requestCode == REQUEST_ID)
        {
            if (resultCode == Result.Ok)
            {
                // Your app is now the call screening app
            }
            else
            {
                // Your app is not the call screening app
            }
        }
    }
}

The android manifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.katoapps.callblocker">
    <application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true" android:label="Call Blocker">
        <service android:name=".CallBlockerService"
                android:exported="true"
                android:permission="android.permission.BIND_SCREENING_SERVICE">
            <intent-filter>
                <action android:name="android.telecom.CallScreeningService" />
            </intent-filter>
        </service>
    </application>
    <uses-sdk android:minSdkVersion="29" />

</manifest>

And the project info (not sure if it's relevant)

<Project Sdk="Microsoft.NET.Sdk">

    <PropertyGroup>
        <TargetFrameworks>net7.0-android;</TargetFrameworks>
        <OutputType>Exe</OutputType>
        <RootNamespace>CallBlocker</RootNamespace>
        <UseMaui>true</UseMaui>
        <SingleProject>true</SingleProject>
        <ImplicitUsings>enable</ImplicitUsings>

        <!-- Display name -->
        <ApplicationTitle>CallBlocker</ApplicationTitle>

        <!-- App Identifier -->
        <ApplicationId>com.katoapps.callblocker</ApplicationId>
        <ApplicationIdGuid>025a85bb-9e56-4624-a3cf-3797a5a01bd2</ApplicationIdGuid>

        <!-- Versions -->
        <ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
        <ApplicationVersion>1</ApplicationVersion>

        <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">29.0</SupportedOSPlatformVersion>
    </PropertyGroup>

    <PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net7.0-android|AnyCPU'">
      <ApplicationId>com.katoapps.callblocker</ApplicationId>
    </PropertyGroup>

    <PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net7.0-android|AnyCPU'">
      <ApplicationId>com.katoapps.callblocker</ApplicationId>
    </PropertyGroup>

    <ItemGroup>
        <!-- App Icon -->
        <MauiIcon Include="Resources\AppIcon\appicon.svg" ForegroundFile="Resources\AppIcon\appiconfg.svg" Color="#512BD4" />

        <!-- Splash Screen -->
        <MauiSplashScreen Include="Resources\Splash\splash.svg" Color="#512BD4" BaseSize="128,128" />

        <!-- Images -->
        <MauiImage Include="Resources\Images\*" />
        <MauiImage Update="Resources\Images\dotnet_bot.svg" BaseSize="168,208" />

        <!-- Custom Fonts -->
        <MauiFont Include="Resources\Fonts\*" />

        <!-- Raw Assets (also remove the "Resources\Raw" prefix) -->
        <MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
    </ItemGroup>

    <ItemGroup>
        <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="7.0.0" />
    </ItemGroup>

</Project>

Why is the app not finding my CallBlockerService?

1 Answer 1

2

Decompiling the APK revealed this Android manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" android:compileSdkVersion="33" android:compileSdkVersionCodename="13" package="com.katoapps.callblocker" platformBuildVersionCode="33" platformBuildVersionName="13">
    <application android:label="Call Blocker" android:icon="@mipmap/appicon" android:name="crc6474c5bb46df487c36.MainApplication" android:debuggable="true" android:allowBackup="true" android:supportsRtl="true" android:extractNativeLibs="true" android:roundIcon="@mipmap/appicon_round" android:appComponentFactory="androidx.core.app.CoreComponentFactory">
        <service android:name="com.katoapps.callblocker.CallBlockerService" android:permission="android.permission.BIND_SCREENING_SERVICE" android:exported="true">
            <intent-filter>
                <action android:name="android.telecom.CallScreeningService"/>
            </intent-filter>
        </service>
        <service android:name="crc6474c5bb46df487c36.CallBlockerService" android:permission="android.permission.BIND_SCREENING_SERVICE" android:exported="true">
            <intent-filter>
                <action android:name="android.telecom.CallScreeningService"/>
            </intent-filter>
        </service>
...
    </application>
</manifest>

The compiler modifies the Android manifest and adds the service automatically under a GUID name, so the fix was to simply remove my service from the manifest.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.