Can't start an activity from a cordova plugin using .aar files - android-activity

I am trying to write a simple cordova-plugin for android, but I am stuck into a crash that I don't know how to resolve.
I basically followed these steps to create simple plugin and it worked fine.
http://www.mat-d.com/site/tutorial-creating-a-cordova-phonegap-plugin-for-android-app/
Yet, my plugin must call an activity that is packaged as an .aar file. Basically I have a full blown application with java/layouts that needs to be triggered by the plugin.
I followed these steps to add my .aar file to the android build of cordova.
Cordova plugin development - adding aar
It also worked. Now, I have so far in my plugin structure these files (admittedly is pretty hacked right now since I kept most of original names):
in my yourFile.gradle I have this:
repositories{
jcenter()
flatDir{
dirs 'libs'
}
}
dependencies {
compile(name:'mylittlelibrary-release', ext:'aar')
compile 'com.android.volley:volley:1.0.0'
}
android {
packagingOptions {
exclude 'META-INF/NOTICE'
exclude 'META-INF/LICENSE'
}
}
and the main part of my "CoolPlugin.java" looks like this:
public class CoolPlugin extends CordovaPlugin {
public CoolPlugin() {}
public void initialize(CordovaInterface cordova, CordovaWebView webView) {
super.initialize(cordova, webView);
}
public boolean execute(final String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
cordova.getActivity().runOnUiThread(new Runnable() {
public void run() {
final Context context = cordova.getActivity().getApplicationContext();
try {
Intent intent = new Intent(context, testv.com.mylittlelibrary.MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
cordova.getActivity().startActivity(intent);
} catch (Exception e) {
String errorText = e.toString();
Toast toast = Toast.makeText(context, errorText, duration);
toast.show();
}
My "mylittlelibrary-release.aar" has its main activity under the namespace "testv.com.mylittlelibrary" so the MainActivity.java looks like this:
package testv.com.mylittlelibrary;
import android.content.Context;
import android.support.v7.app.AppCompatActivity;
import com.android.volley.*;
import com.android.volley.toolbox.*;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
etc...
I was reading the thread below, and looks like I need in somehow register the main activity of my aar file.
open an activity from a CordovaPlugin
I am not totally sure how to do this, so I went inside the auto-generated AndroidManifest.xml under
C:\cordova\hello\platforms\android\AndroidManifest.xml
and hacked the activity with the namespace inside as such:
<?xml version='1.0' encoding='utf-8'?>
<manifest android:hardwareAccelerated="true" android:versionCode="1" android:versionName="0.0.1" package="com.example.hello" xmlns:android="http://schemas.android.com/apk/res/android">
<supports-screens android:anyDensity="true" android:largeScreens="true" android:normalScreens="true" android:resizeable="true" android:smallScreens="true" android:xlargeScreens="true" />
<uses-permission android:name="android.permission.INTERNET" />
<application android:hardwareAccelerated="true" android:icon="#drawable/icon" android:label="#string/app_name" android:supportsRtl="true">
<activity android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale" android:label="#string/activity_name" android:launchMode="singleTop" android:name="MainActivity" android:theme="#android:style/Theme.DeviceDefault.NoActionBar" android:windowSoftInputMode="adjustResize">
<intent-filter android:label="#string/launcher_name">
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:label="#string/activity_name"
android:launchMode="singleTop"
android:name="testv.com.mylittlelibrary.MainActivity">
</activity>
</application>
<uses-sdk android:minSdkVersion="17" android:targetSdkVersion="23" />
</manifest>
I installed the plugin and ran the app using:
cordova plugin add c:/CoolPlugin/
cordova build android
cordova run android
there is button in the html file that triggers the plugin, which then triggers my activity as you see on the "MainActivity" of the "mylittlelibrary-release.aar" file.
Yet, I keep getting this crash. I believe the android plugin cannot resolve the namespace properly and throws this exception.
com.example.hello E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.hello, PID: 13119
java.lang.NoClassDefFoundError: Failed resolution of: Ltestv/com/mylittlelibrary/MainActivity;
at CoolPlugin$1.run(CoolPlugin.java:59)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:5835)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
I also believe is has something to do with the proper registering the MainActivity under the testv.com.mylittlelibrary. But I can't figure out how to do in in cordova. I need to resolve this, so I am glad to give you points of my reputation for a solid answer that unblocks me.
thank you.

nevermind, it was simple mistake. The library missed some imports and a theme. This fixed the issue.
Manifest:
android:theme="#style/Theme.AppCompat.Light"
Gradle:
dependencies {
compile(name:'mylittlelibrary-release', ext:'aar')
compile 'com.android.support:support-v13:23.1.0'
compile 'com.android.support:support-v4:23.1.0'
compile 'com.android.support:gridlayout-v7:23.1.1'
compile 'com.android.support:appcompat-v7:23.1.0'
compile 'com.android.support:design:23.1.0'

Related

How to set the android:export to false in the package manifest file

I build the app using flutter, give the .apk file to penetration testing.How resolve these issues?
i can't see these Service and Broadcast Receiver in the android manifest file
If you want to find android:exported=true in AndroidManifested.xml you just need to goto :
<manifest>
...
<application>
...
<activity>
android:name="com.example.app.MainActivity" //find the MainActivity activity
android:exported="true" //here it is
...
</activity>
</application>
</manifest>

flutter Can't get APK

I want to get .apk from my project, but I've got an error from my grade.
I've removed my .gradle file and installed it again, but I still can't get .apk.
I've got this :
android\app\src\main\AndroidManifest.xml:25: Error: AudioService must extend android.app.Service [Instantiatable]
<service android:name="com.ryanheise.audioservice.AudioService"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
H:\podkadeh\android\app\src\main\AndroidManifest.xml:35: Error: MediaButtonReceiver must extend android.content.BroadcastReceiver [Instantiatable]
<receiver android:name="com.ryanheise.audioservice.MediaButtonReceiver"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Explanation for issues of type "Instantiatable":
Activities, services, broadcast receivers etc. registered in the manifest
file (or for custom views, in a layout file) must be "instantiatable" by
the system, which means that the class must be public, it must have an
empty public constructor, and if it's an inner class, it must be a static
inner class.
2 errors, 0 warnings
Lint found fatal errors while assembling a release target.
To proceed, either fix the issues identified by lint, or modify your build script as follows:
...
android {
lintOptions {
checkReleaseBuilds false
// Or, if you prefer, you can continue to check for errors in release builds,
// but continue the build even when errors are found:
abortOnError false
}
}
...
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':app:lintVitalRelease'.
> A failure occurred while executing com.android.build.gradle.internal.lint.AndroidLintTask$AndroidLintLauncherWorkAction
> There was a failure while executing work items
> A failure occurred while executing com.android.build.gradle.internal.lint.AndroidLintWorkAction
> Lint found fatal errors while assembling a release target.
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 26s
Running Gradle task 'assembleRelease'... 27.1s
Gradle task assembleRelease failed with exit code 1
Here is my AndroidManifest.xml:
and I've to use audio service to play audio in the background…
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.podkadeh">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<application
android:name="io.flutter.app.FlutterApplication"
android:label="podkadeh"
android:icon="#mipmap/ic_launcher">
<activity
android:name="com.ryanheise.audioservice.AudioServiceActivity"
android:exported="true"
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">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<service android:name="com.ryanheise.audioservice.AudioService"
android:exported="true"
android:required="true"
>
<intent-filter>
<action android:name="android.media.browse.MediaBrowserService" />
</intent-filter>
</service>
<receiver android:name="com.ryanheise.audioservice.MediaButtonReceiver"
android:exported="true"
android:required="true"
>
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
<!-- 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>
And here is my build.gradle
buildscript {
ext.kotlin_version = '1.5.0'
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.0.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
google()
jcenter()
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
delete rootProject.buildDir
}
The example program provided with the library com.ryanheise.audioservice that you are including in your project contains a configuration that compiles successfully : https://github.com/ryanheise/audio_service/blob/minor/audio_service/example/android/app/src/main/AndroidManifest.xml
Add xmlns:tools="http://schemas.android.com/tools" as an attribute in the root node <manifest>
Add the attribute tools:ignore="Instantiatable" in the <activity> node and
android:exported="true" tools:ignore="Instantiatable" in the <service> and <receiver> nodes.

MissingPluginException after upgrading to Android embedding v2

I need to implement a plugin in my app. For this, I needed to migrate to Android embedding v2. Through the documentation, I tried upgrading. Below is the documentation I referred:
https://github.com/flutter/flutter/wiki/Upgrading-pre-1.12-Android-projects
For upgrading, I changed my imports in MainActivity.kt
to import io.flutter.embedding.android.FlutterActivity and removed the onCreate Method as well.
In AndroidManifest.xml I added the below meta-data
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="#style/NormalTheme"
/>
<meta-data android:name="flutterEmbedding" android:value="2"/>
<meta-data
android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
android:value="true" />
After adding this I got some error so I changed the Application.java to this
public class Application extends FlutterApplication implements PluginRegistrantCallback {
#Override
public void onCreate() {
super.onCreate();
FlutterFirebaseMessagingService.setPluginRegistrant(this);
}
#Override
public void registerWith(PluginRegistry registry) {
//GeneratedPluginRegistrant.registerWith(registry);
FirebaseMessagingPlugin.registerWith(registry.registrarFor("io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin"));
}
}
The application is installing but I am getting below errors after
Unhandled Exception: MissingPluginException(No implementation found for method getApplicationDocumentsDirectory on channel plugins.flutter.io/path_provider)
MissingPluginException(No implementation found for method getApplicationDocumentsDirectory on channel plugins.flutter.io/path_provider)
I tried uninstalling and reinstalling the app. Tried flutter clean and flutter pub cache repair as well but nothing works.
If you're getting the error, MissingPluginException, bon't forget this last bit in your AndroidManifest:
</activity>
</application>
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</manifest>

flutter: android manifest doesn't read kotlin file (Application.kt)

I'm trying to imply firebase cloud messaging to my app and I have tried to add both MainActvity.kt and Application.kt to my project and i didnt have kotlin installed on my project so i downloaded kotlin plugin then restarted my IDE then added the .kt files, however when i try to add the application.kt to my android manifest the app won't build and says "app" has stopped, but without it it works fine, what am i doing wrong?
heres my application.kt code
package com.example.tamataapp
import io.flutter.app.FlutterApplication;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback;
import io.flutter.plugins.GeneratedPluginRegistrant;
import io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService;
class Application : FlutterApplication(), PluginRegistrantCallback {
override fun onCreate() {
super.onCreate()
FlutterFirebaseMessagingService.setPluginRegistrant(this)
}
override fun registerWith(registry: PluginRegistry) {
GeneratedPluginRegistrant.registerWith(registry)
}
}
and my MainActivity.kt
package com.example.tamataapp
import android.os.Bundle
import io.flutter.app.FlutterActivity
import io.flutter.plugins.GeneratedPluginRegistrant
class MainActivity: FlutterActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
GeneratedPluginRegistrant.registerWith(this)
// getWindow().addFlags(LayoutParams.FLAG_SECURE)
}
}
and here is my android manifest
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.tamataapp">
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method.
In most cases you can leave this as-is, but you if you want to provide
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. "io.flutter.app.FlutterApplication" -->
<application
android:name=".Application"
android:label="tamataapp"
android:icon="#mipmap/ic_launcher">
<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">
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="default_notification_channel_id”>Channel ID"/>
<!-- 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"/>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
<action android:name="FLUTTER_NOTIFICATION_CLICK" />
<category android:name="android.intent.category.DEFAULT" />
</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" />
<service
android:name=".java.MyFirebaseMessagingService"
android:exported="false">
</service>
</application>
</manifest>

Flutter android_alarm_manager doesn't load flutter_audio_query plugin for callback

I am working on a rather simple alarm app that uses android_alarm_manager to schedule the alarms and flutter_audio_query to gather information about the music I need to make things work. When the alarm goes off I need to have flutter_audio_query loaded to be able to access the file paths of the sound files I want to use.
The issue I am facing currently is the plugin not being loaded inside the callback, causing a MissingPluginException. This does not appear to be the issue with the PathProvider plugin for example (which I initially intended to use for the demo below).
MCVE attempt (created a new Flutter project with Kotlin Support, AndroidX under Flutter Version 1.12.13+hotfix.8; full repository here):
main.dart:
import 'package:android_alarm_manager/android_alarm_manager.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_audio_query/flutter_audio_query.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await AndroidAlarmManager.initialize();
runApp(MyApp());
Scheduler().setupAlarm();
// Runs because the FAQ plugin is loaded correctly.
final demoSongList = await FlutterAudioQuery().getSongs();
print('Main function: ${demoSongList.length}');
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Center(child: Text('Sample Text', textDirection: TextDirection.ltr,));
}
}
class Scheduler {
setupAlarm() async {
print('Setting up alarm!');
final success = await AndroidAlarmManager.oneShot(Duration(seconds: 3), 42, callback);
print(success);
}
static callback() async {
// Requires FAQ plugin to be loaded which it isn't.
final songs = await FlutterAudioQuery().getSongs();
print('Callback ${songs.length}!');
}
}
pubspec.yaml
name: stack_overflow_demo
description: A Demo Application demonstrating the issue with android_alarm_manager and plugins
version: 1.0.0+1
environment:
sdk: ">=2.1.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
android_alarm_manager: ^0.4.5+3
flutter_audio_query: ^0.3.3
dev_dependencies:
flutter_test:
sdk: flutter
flutter:
uses-material-design: true
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="io.github.geisterfurz007.stack_overflow_demo">
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method.
In most cases you can leave this as-is, but you if you want to provide
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<application
android:name="io.flutter.app.FlutterApplication"
android:label="stack_overflow_demo"
android:icon="#mipmap/ic_launcher">
<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">
<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" />
<service
android:name="io.flutter.plugins.androidalarmmanager.AlarmService"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="false"/>
<receiver
android:name="io.flutter.plugins.androidalarmmanager.AlarmBroadcastReceiver"
android:exported="false"/>
<receiver
android:name="io.flutter.plugins.androidalarmmanager.RebootBroadcastReceiver"
android:enabled="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"></action>
</intent-filter>
</receiver>
</application>
</manifest>
If more files are required, let me know; I will add them as soon as I can!
From my understanding with Android Embedding V2 (as declared in the AndroidManifest.xml), all plugins should be loaded through reflection and creating my own Application to load the plugins should not be required.
Now for the actual question of this question: What causes the FlutterAudioQuery Plugin to not be loaded in the callback and how do I change this so I can use it when the alarm runs?
For transparency: After rather low views on this question after a day, I decided to open up a Github issue in the flutter repo here.
I think the problem is that flutter_audio_query does not support the new plugin APIs yet. Check this page in the flutter documentation.
I had a quick look at the flutter_audio_query source and it doesn´t seem to implement the FlutterPlugin interface (Upgrade Step 1 in the documentation).
There is a new version of audio_query_plugin available and appears the new Flutter V2 embedding API is working with.
By CHANGELOG.md