public class PeripheralManager - returning all stubs - android

I have imported
implementation 'com.google.android.things:androidthings:1.0'
And when I execute code, it throws a runtime error because inside of the PeripheralManager class the methods are all stubs:
public List<String> getUartDeviceList() {
throw new RuntimeException("Stub!");
}
This was working several months ago, I've tried changing implementation to compile

There are several conditions you should verify in your project:
Your device must be either the i.MX7D or Raspberry Pi 3B with the Android Things OS on it, as noted in the hardware guide.
Your app/build.gradle must use compileOnly 'com.google.android.things:androidthings:1.0'
Your app/src/main/AndroidManifest.xml must include the following as a child of the application element:
<uses-library android:name="com.google.android.things"/>
You may also want to check properties like the targetSdkVersion being 27. If you continue to run into trouble, check out Android Things sample projects.

Which device are you running it into? This API is only available on Android Things boards, not on phones.

Related

Android + coreLibraryDesugaring: which Java 11 APIs can I expect to work?

I'm trying to migrate some Java library from 'normal' JVM to android and stuck with some Java11 APIs used in the code.
The first thing I already got - Java11 language features seems to work only with Canary build of Android Studio, see answer here
Now I need to get understanding about which APIs can be really used. Here are two use-cases which do not work for me and I can't get if I'm doing something wrong or it never should work:
List.copyOf() - introduced in Java11, method copyOf is not available on android. Methods 'List.of()', introduced with Java 9, work OK.
class java.lang.invoke.LambdaMetafactory - introduced with Java 1.8 - to be used for programmatic creation of lambdas for usage instead for reflection, is not visible on Android.
I see both of them in sources of desugar_jdk_libs here:
https://github.com/google/desugar_jdk_libs/blob/master/jdk11/src/java.base/share/classes/java/lang/invoke/LambdaMetafactory.java
https://github.com/google/desugar_jdk_libs/blob/master/src/share/classes/java/util/List.java
So - the question is: how can I identify if some Java API is supposed to be available in 'desugared' android build or no? What really can be expected from 'desugaring'?
Steps to reproduce:
Using Android Studio Canary generate a dummy "Basic Activity" project
Make sure following is provided in build.gradle
android {
compileOptions {
coreLibraryDesugaringEnabled true
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
}
dependencies {
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
}
Add following lines somewhere in code
List<Integer> ints1 = List.of(1, 2, 3);
Supplier<List<Object>> listSupplier = () -> new ArrayList<>();
List<Object> alist = listSupplier.get();
List<Integer> ints2 = List.copyOf(ints1);
LambdaMetafactory.metafactory(null,null,null,null,null,null);
Last 2 lines fail to compile for me.
PS: final application is supposed to work on Android 10+.
Contrary to the other answer, desugaring is totally possible.
The dependency to add is
dependencies {
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
}
You can find more information at the official Android Java 8 desugaring documentation.
Desugaring lib is considered unofficial. We can't expect an exact answer. We get the feature when it is ready. Now List.copyOf() method now working with the latest Gradle version.
About the LambdaMetafactory class, It is not included in Android Javadoc. This means we assume we don't have LambdaMetafactory at all. Google stripped down some java API for being lightweight.
In general, We should check android Javadoc first. If android Javadoc has no mention about some API. We can be sure we won't get that feature anytime soon.

How to run an Apache-Mina SSHD-Server (2.2.0) on Android Pie?

I'm trying to run an Apache MINA SSHD Server (v. 2.2.0) on an Android Pie (API 28.0) device. I found various post about it running on Android 4 devices, but none of them seems to work on my Android 9 device. So I tried to implement it myself but got stuck at the initialization of the Server with a ReflectionException/NoClassDefFoundError.
When I try to set up the server with SshServer.setUpDefaultServer(); I get this exception:
java.lang.NoClassDefFoundError: Failed resolution of: Ljavax/management/ReflectionException;
at org.apache.sshd.common.util.GenericUtils.peelException(GenericUtils.java:730)
at org.apache.sshd.common.util.GenericUtils.peelException(GenericUtils.java:728)
at org.apache.sshd.common.util.security.SecurityEntityFactory$2.getInstance(SecurityEntityFactory.java:134)
at org.apache.sshd.common.util.security.SecurityUtils.getMessageDigest(SecurityUtils.java:726)
at org.apache.sshd.common.digest.DigestUtils.checkSupported(DigestUtils.java:53)
at org.apache.sshd.common.digest.BuiltinDigests.<init>(BuiltinDigests.java:61)
at org.apache.sshd.common.digest.BuiltinDigests.<clinit>(BuiltinDigests.java:36)
at org.apache.sshd.common.cipher.ECCurves.<clinit>(ECCurves.java:61)
at org.apache.sshd.common.keyprovider.KeyPairProvider.<clinit>(KeyPairProvider.java:63)
at org.apache.sshd.common.signature.BuiltinSignatures.<clinit>(BuiltinSignatures.java:62)
at org.apache.sshd.common.BaseBuilder.<clinit>(BaseBuilder.java:133)
at org.apache.sshd.server.ServerBuilder.builder(ServerBuilder.java:165)
at org.apache.sshd.server.SshServer.setUpDefaultServer(SshServer.java:429)
at ch.zhaw.init.sshshell.SshShellService.<init>(SshShellService.java:20)
From some older posts for Android 4 it seems that this is was a known problem and the solution there was to add $useLibrary 'org.apache.http.legacy' to gradle and add to the manifest.xml. I did that but the exception still occurs.
build.gradle file:
android {
compileSdkVersion 28
useLibrary 'org.apache.http.legacy'
...
}
dependencies {
...
implementation 'org.apache.sshd:sshd-core:2.2.0'
implementation 'org.slf4j:slf4j-simple:1.6.2'
implementation 'org.apache.mina:mina-core:2.1.2'
implementation "org.bouncycastle:bcprov-jdk16:1.46"
}
manifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="ch.zhaw.init.sshshell">
<application
android:networkSecurityConfig="#xml/network_security_config">
<uses-library android:name="org.apache.http.legacy"
android:required="false" />
<service android:name=".SshShellService">
<intent-filter>
<action android:name="StartSshServer"/>
</intent-filter>
</service>
</application>
</manifest>
My Java-Code:
import org.apache.sshd.server.SshServer;
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
private static final int PORT = 8022;
private final SshServer sshd = SshServer.setUpDefaultServer(); // Here I get the error
private final SimplePasswordAuthenticator passwordAuth = new SimplePasswordAuthenticator();
private final SimplePublicKeyAuthenticator publicKeyAuth = new SimplePublicKeyAuthenticator();
private final SimpleForwardingFilter forwardingFilter = new SimpleForwardingFilter();
It seems that older versions worked, but I search for days and did not find any working example for the newest version. Does anyone has a working example which runs the latest version of Apache Mina SSHD (2.2.0) on Android 9 (without rooting the device)?
or if not is there an alternative SSH-Server (not client - there are many of them) for Android Pie?
Thank you for any help.
For this specific failure, it suffices to create a dummy ReflectionException class (example). Given that the class doesn't even exist, nothing outside of your own code would ever instantiate it, so SSHD's instanceof ReflectionException check would never match, and you don't need to program any of its members.
You'll also want to create a dummy MBeanException (example).
the error because of BouncyCastle lib has been deprecated as android9(api level 28).
you can get detail tips from aosp: http://androidxref.com/9.0.0_r3/xref/libcore/ojluni/src/main/java/sun/security/jca/Providers.java#548
https://android-developers.googleblog.com/2018/03/cryptography-changes-in-android-p.html
to solve this problem ,you can follow steps:
uninstall BouncyCastleProvider from system default
Security.removeProvider("BC");
install new "BC" custom provider
Security.addProvider(new BouncyCastleProvider());
init your mina sshd Service
SshServer sshd = SshServer.setUpDefaultServer();
sshd.setPort(ssdServerPort);
....
aosp just compare object to decide if bc provider object is system default provider,so just replace with new bc provider object
:http://androidxref.com/9.0.0_r3/xref/libcore/ojluni/src/main/java/sun/security/jca/Providers.java#341
notes: you must uninstall provider with :Security.removeProvider("BC"),before install provider

Android library with dependency not resolving properly

So I have an Android library project, SimpleWidget. I publish it to jcenter.
I can make a new project and add implementation 'my.project:simplewidget:1.2.3' and everything works as expected, I can use SimpleWidget instances and their public APIs.
Now I make another Android library project, ComplexWidget. ComplexWidget is a subclass of SimpleWidget. I add implementation 'my.project:simplewidget:1.2.3' to the build.gradle and everything resolves, and in fact I can even get away without lint yelling for something super basic like ComplexWidget complexWidget = new ComplexWidget().
However, the project will not compile. Any ComplexWidget method that has a return or parameter type of SimpleWidget (e.g., many of the inherited methods, or an interface that accepts SimpleWidget arguments, or a Factory that returns SimpleWidget instances) will not compile and Android Studio complains that "Cannot access my.project.SimpleWidget".
Not sure if I should even mention it for fear of muddying the waters, but if I command click SimpleWidget in, for example, public class ComplexWidget extends SimpleWidget, I get a warning at the top of the file that "Library source does not match the byetcode for the class SimpleWidget".
Any ideas?
TYIA
use api 'my.project:SimpleWidget:1.2.3' instead

How to resolve "Obsolete custom lint check" for my custom IssueRegistry written in Kotlin and make it work (Android)

I am trying to implement custom lint checks (using Kotlin). I have set up a module for my custom checks and added classes to test my first lew lint check, mostly following these two tutorials here and here.
So I now have a module, I have a custom IssueRegistry, I've created an issue and a Detector class for it. So far it seems complete. I've added a test to check if my lint check works and it looks alright.
I have added my module to the project by referencing it in settings.gradle like this: include ':app', ':somemodule', ':mylintmodule'
Now if I run the linter using ./gradlew lint I get a lint result file telling me this:
Lint found an issue registry (com.myproject.mylintmodule) which requires a newer API level. That means that the custom lint checks are intended for a newer lint version; please upgrade
Lint can be extended with "custom checks": additional checks implemented by developers and libraries to for example enforce specific API usages required by a library or a company coding style guideline.
The Lint APIs are not yet stable, so these checks may either cause a performance degradation, or stop working, or provide wrong results.
This warning flags custom lint checks that are found to be using obsolete APIs and will need to be updated to run in the current lint environment.
It may also flag issues found to be using a newer version of the API, meaning that you need to use a newer version of lint (or Android Studio or Gradle plugin etc) to work with these checks.
To suppress this error, use the issue id "ObsoleteLintCustomCheck" as explained in the Suppressing Warnings and Errors section.
So it tells me that I am using a newer API verion in my custom lint check, right? This is my custom IssueRegistry (minus some parts not relevant for this problem):
class MyCustomIssueRegistry : IssueRegistry() {
override val issues: List<Issue>
get() = listOf(ISSUE_NAMING_PATTERN)
override val api: Int = com.android.tools.lint.detector.api.CURRENT_API
override val minApi: Int = 1
}
From googling this problem and finding this issue I figured I have to override and set the right API version (and maybe the min API?) by overriding these properties like I did above (this version is my last attempt, directly taken from that issue).
So this property can be set to values between -1 and 5, meaning this (taken right out of the lint.detector.api class):
/** Describes the given API level */
fun describeApi(api: Int): String {
return when (api) {
5 -> "3.5+" // 3.5.0-alpha07
4 -> "3.4" // 3.4.0-alpha03
3 -> "3.3" // 3.3.0-alpha12
2 -> "3.2" // 3.2.0-alpha07
1 -> "3.1" // Initial; 3.1.0-alpha4
0 -> "3.0 and older"
-1 -> "Not specified"
else -> "Future: $api"
}
I have tried all of them, plus the one above adding a minApi override too, and I keep getting the exact same result for each of them.
Also I am unable to locate what other API version this is compared with. Is there a place where this is set for the regular linter in an Android project?
It's also unclear to me what I have to do to make sure my changes got applied - is it enough to change some code, then run lint, or do I have to compile the project first, or build & clean?
Following the tutorials, I added my custom lint check by adding this to the app's build.gradle: lintChecks project(":mylintmodule")
Is that even right? The API issue on my registry class shows up no matter if my lint check is referenced (and hopefully used) like that or not. I have also tried the other method described in the first tutorial, adding this task to the linter module build.gradle:
defaultTasks 'assemble'
task copyLintJar(type: Copy) {
description = 'Copies the lint jar file into the {user.home}/.android/lint folder.'
from('build/libs/')
into(System.getProperty("user.home") + '/.android/lint')
include("*.jar")
}
// Runs the copyLintJar task after build has completed.
build.finalizedBy(copyLintJar)
But since I can't figure out how to see if my custom checks are actually run, I don't know if that works as intended either.
So how do I get this warning resolved (since I interpret the text as "As long as the versions don't match I will not try to run your lint check"), and how can I make sure my lint check is actually run by the linter?

Method setUp in android.test.AndroidTestCase not mocked

I'm trying to come to terms with the new unit test feature of Android Studio.
I've followed the instructions on http://tools.android.com/tech-docs/unit-testing-support. The description there explicitly mentions the 'Method ... not mocked' error and suggests to put the following into the build.gradle:
android {
// ...
testOptions {
unitTests.returnDefaultValues = true
}
}
This works in so far as the tests run when started from the command line with
gradlew test --continue
but not when I run the test class from Android Studio with rightclick -> run. This way, I get the same error again:
java.lang.RuntimeException: Method setUp in android.test.AndroidTestCase not mocked. See https://sites.google.com/a/android.com/tools/tech-docs/unit-testing-support for details.
at android.test.AndroidTestCase.setUp(AndroidTestCase.java)
at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:86)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:74)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:211)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:67)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
Any ideas on how to solve this?
EDIT: The content of the test class doesn't really matter because the setUp of the test fails, I tried with the most simple class:
public class ContactFormToolTest extends AndroidTestCase {
public void testSOmething(){
assertEquals(false, true);
}
}
Also tried overriding setUp, makes no difference.
From: https://sites.google.com/a/android.com/tools/tech-docs/unit-testing-support#TOC-Method-...-not-mocked.-
The android.jar file that is used to run unit tests does not contain
any actual code - that is provided by the Android system image on real
devices. Instead, all methods throw exceptions (by default). This is
to make sure your unit tests only test your code and do not depend on
any particular behaviour of the Android platform (that you have not
explicitly mocked e.g. using Mockito). If that proves problematic, you
can add the snippet below to your build.gradle to change this
behavior:
android {
// ...
testOptions {
unitTests.returnDefaultValues = true
}
}
The new Unit Tests feature in Android Studio fakes the entire Android SDK so that you can run fast, Java-only tests, without needing to install your application on an Android device (this is similar to Robolectric). The general idea is that you mock all the responses from the Android SDK calls.
AndroidTestCase is used to run a test with the real Android SDK.
So, your issue is that you are trying to run an AndroidTestCase that depends on the Android SDK, but your test runner is launching the Unit Tests environment, which uses a fake Android SDK instead of a real one.
You need to choose one approach. If you want a pure unit test, then you probably should use a JUnit 4 test class instead of an AndroidTestCase. More instructions here:
https://developer.android.com/training/testing/unit-testing/local-unit-tests.html#build
As of SDK version 24, AndroidTestCase is deprecated
This class was deprecated in API level 24.
Use InstrumentationRegistry instead. New tests should be written using
the Android Testing Support Library.
You are supposed to use the Espresso framework for UI testing. There is a tutorial.

Categories

Resources