Decompile apk, problems lambda - apk

Im Decompiled apk, respectively, appeared .java files, But some files have in the name of such "AudioPlayerActivity$$Lambda$1.java", what is this "$$Lambda$1"??

"AudioPlayerActivity$$Lambda$1.java" these is basically an anonymous block of code written inside the "AudioPlayerActivity.java", now the "AudioPlayerActivity.java" can have any number of anonymous block of code, so while decompiling it, all these blocks gets converted into separate classes with a number at the end in a sequential order. Let's take an example, I have a class HelloWorld.java which contains a block
runOnUiThread(new Runnable() {
#Override
public void run() {
}
});
and another anonymous block for a clicklistener on button like this.
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
then on decompiling i would get 3 classes helloworld.smali, helloworld$1.smali (with code for runOnUithread) and helloworld$2.smali (with code for onClickListener).

Related

How to retrieve the value from the event listener from another class in java?

I have a program to get the values from a Bar code scanner(using jssc library) and it returns value as expected using event listener but I need to access that value from another class.
I tried to instantiate BarcodeScanner class to main method (ProcessTicket class) and called scannerHandler method and also called the getter method of model class to retrieve value but the getter method runs before the scan is completed. Could you please help me to achieve this?
public class BarcodeScanner {
public static Object SerialPortReader;
static SerialPort serialPort;
public void scannerHandler() {
serialPort = new SerialPort("COM4");
try{
serialPort.openPort();//Open serial port
//Set params. Also set params by this string:
serialPort.setParams(9600, 8, 1, 0);
serialPort.setParams(9600, 8, 1, 0);
serialPort.writeString(new String(new byte[]{0x02})); //triggers barcode scanner
serialPort.addEventListener(new SerialPortReader());//Add SerialPortEventListenerS
} catch (SerialPortException ex) {
System.out.println(ex);
}
}
public static class SerialPortReader implements SerialPortEventListener {
String str;
String value;
public void serialEvent(SerialPortEvent event) {
if (event.isRXCHAR() && event.getEventValue() > 0) {//If data is available
//Check bytes count in the input buffer
try {
byte[] bytesCont = serialPort.readBytes(14);
str = new String(bytesCont);
ModelClass modelClass = new ModelClass();
modelClass.setBarcodeValue(str);
} catch (SerialPortException e) {
e.printStackTrace();
}
}
}
My ProcessTicket.java Class
public class ProcessTicket {
public static void main(String[] args) throws SQLException, SerialPortException {
BarcodeScanner bSC = new BarcodeScanner();
bSC.scannerHandler();
BarcodeScanner.SerialPortReader portReader = new BarcodeScanner.SerialPortReader();
ModelClass modelClass = new ModelClass();
String value = modelClass.getBarcodeValue();
System.out.println(value);
}
}
The main problem here is that you're treating an inherently asynchronous operation (reading from an external sensor in the real world) as if it's synchronous.
I simulated that external sensor stuff to make a standalone app that tests your business logic:
HowToRetrieveTheValueFromTheEventListenerFromAnotherClassInJava.java
package com.stackoverflow;
/**
* https://stackoverflow.com/questions/57452205/how-to-retrieve-the-value-from-the-event-listener-from-another-class-in-java
*/
public class HowToRetrieveTheValueFromTheEventListenerFromAnotherClassInJava {
public static void main(String[] args) {
BarcodeScanner barcodeScanner = new BarcodeScanner((String barcode) -> {
System.out.println("Barcode scanned: " + barcode);
});
barcodeScanner.startScan();
MockUser.startScanningStuffLol();
}
}
That call to MockUser.startScanningStuffLol() is only necessary because I'm testing this just in code, without using a real barcode scanner. Please don't focus on it. I'll post its implementation if you ask, but otherwise I'm assuming that your OS/Java/hardware are working the way they were designed to work, and you can just test this with those tools instead of my MockUser software simulation.
Here are the rest of the classes that you need to implement this:
BarcodeScannedCallback.java
package com.stackoverflow;
public interface BarcodeScannedCallback {
void callback(String barcode);
}
Since we're dealing with an asynchronous operation, we can't just start it and then check for a return value, like we would with a synchronous operation. Instead, we need to pass in a function that will be called once the operation is complete, and just wait for it to finish. BarcodeScannedCallback is the signature of that function (in other words, a description of how that function needs to be structured). It takes one string parameter, and returns nothing.
The implementation of BarcodeScannedCallback is this function that I've already mentioned above, which I'm passing into the BarcodeScanner constructor:
(String barcode) -> {
System.out.println("Barcode scanned: " + barcode);
}
As you can see, this function takes one string parameter, and returns nothing. So, it's an implementation of the BarcodeScannedCallback interface.
Now for the last class: the one that bridges our main method and the serial port, using the above interface.
BarcodeScanner.java
package com.stackoverflow;
public class BarcodeScanner implements SerialPortEventListener {
private SerialPort serialPort;
private final BarcodeScannedCallback callback;
public void startScan() {
try {
serialPort = new SerialPort("COM4");
serialPort.openPort();
serialPort.addEventListener(this);
// Also you can set params by this string: serialPort.setParams(9600, 8, 1, 0);
serialPort.setParams(9600, 8, 1, 0);
// Triggers barcode scanner.
serialPort.writeString(new String(new byte[]{0x02}));
} catch (SerialPortException ex) {
System.out.println(ex);
}
}
#Override
public void serialEvent(SerialPortEvent event) {
boolean isDataAvailable = event.isRXCHAR() && event.getEventValue() > 0;
if (isDataAvailable) {
try {
byte[] bytesCont = serialPort.readBytes(14);
String barcode = new String(bytesCont);
callback.callback(barcode);
} catch (SerialPortException ex) {
System.out.println(ex);
}
}
}
public BarcodeScanner(BarcodeScannedCallback callback) {
this.callback = callback;
}
}
So here's the full lifecycle of these events:
You create a BarcodeScanner.
You tell the BarcodeScanner, via the implementation of BarcodeScannedCallback that you pass into its constructor, what code to run once it receives a barcode over the serial port.
You call startScan on the BarcodeScanner, which opens the serial port and starts waiting for the user to scan a barcode.
The user scans a barcode. This data is transmitted over the serial port. The operating system's implementation of SerialPort calls BarcodeScanner.serialEvent.
Your implementation of serialEvent does its validations, pulls the data from the serial port and converts it from bytes to a string, and calls the BarcodeScannedCallback function that was passed in at the beginning.
When I run this (with my MockUser class setting up a background thread that "scans" a barcode every 3 seconds), I get this output:
Barcode scanned: 420L0L
Barcode scanned: 007
Barcode scanned: 12345
In your case, you should be able to scan 3 barcodes with your real-world barcode scanner, and get the same results.
Note that you may need to do something to keep the main method's thread from ending prematurely, depending on the context that you're running this in.
If you're running it in an Android app or a web server, those frameworks keep their main thread running indefinitely, until you kill the app/server.
But if you're running it as a custom command-line app (which it seems like you're doing, based on the existence of a main method), you will need to do something to keep it alive until you decide to kill it. The simplest way is to put an infinite loop like while (true); on the last line of your main method.

Mockito: Verifying a method was called with a functional parameter

I have a simple scenario in which am trying to verify some behavior when a method is called (i.e. that a certain method was called with given parameter, a function pointer in this scenario). Below are my classes:
#SpringBootApplication
public class Application {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
AppBootStrapper bootStrapper = context.getBean(AppBootStrapper.class);
bootStrapper.start();
}
}
#Component
public class AppBootStrapper {
private NetworkScanner networkScanner;
private PacketConsumer packetConsumer;
public AppBootStrapper(NetworkScanner networkScanner, PacketConsumer packetConsumer) {
this.networkScanner = networkScanner;
this.packetConsumer = packetConsumer;
}
public void start() {
networkScanner.addConsumer(packetConsumer::consumePacket);
networkScanner.startScan();
}
}
#Component
public class NetworkScanner {
private List<Consumer<String>> consumers = new ArrayList<>();
public void startScan(){
Executors.newSingleThreadExecutor().submit(() -> {
while(true) {
// do some scanning and get/parse packets
consumers.forEach(consumer -> consumer.accept("Package Data"));
}
});
}
public void addConsumer(Consumer<String> consumer) {
this.consumers.add(consumer);
}
}
#Component
public class PacketConsumer {
public void consumePacket(String packet) {
System.out.println("Packet received: " + packet);
}
}
#RunWith(JUnit4.class)
public class AppBootStrapperTest {
#Test
public void start() throws Exception {
NetworkScanner networkScanner = mock(NetworkScanner.class);
PacketConsumer packetConsumer = mock(PacketConsumer.class);
AppBootStrapper appBootStrapper = new AppBootStrapper(networkScanner, packetConsumer);
appBootStrapper.start();
verify(networkScanner).addConsumer(packetConsumer::consumePacket);
verify(networkScanner, times(1)).startScan();
}
}
I want to verify that bootStrapper did in fact do proper setup by registering the packet consumer(there might be other consumers registered later on, but this one is mandatory) and then called startScan. I get the following error message when I execute the test case:
Argument(s) are different! Wanted:
networkScanner bean.addConsumer(
com.spring.starter.AppBootStrapperTest$$Lambda$8/438123546#282308c3
);
-> at com.spring.starter.AppBootStrapperTest.start(AppBootStrapperTest.java:24)
Actual invocation has different arguments:
networkScanner bean.addConsumer(
com.spring.starter.AppBootStrapper$$Lambda$7/920446957#5dda14d0
);
-> at com.spring.starter.AppBootStrapper.start(AppBootStrapper.java:12)
From the exception, clearly the function pointers aren't the same.
Am I approaching this the right way? Is there something basic I am missing? I played around and had a consumer injected into PacketConsumer just to see if it made a different and that was OK, but I know that's certainly not the right way to go.
Any help, perspectives on this would be greatly appreciated.
Java doesn't have any concept of "function pointers"; when you see:
networkScanner.addConsumer(packetConsumer::consumePacket);
What Java actually compiles is (the equivalent of):
networkScanner.addConsumer(new Consumer<String>() {
#Override void accept(String packet) {
packetConsumer.consumePacket(packet);
}
});
This anonymous inner class happens to be called AppBootStrapper$$Lambda$7. Because it doesn't (and shouldn't) define an equals method, it will never be equal to the anonymous inner class that the compiler generates in your test, which happens to be called AppBootStrapperTest$$Lambda$8. This is regardless of the fact that the method bodies are the same, and are built in the same way from the same method reference.
If you generate the Consumer explicitly in your test and save it as a static final Consumer<String> field, then you can pass that reference in the test and compare it; at that point, reference equality should hold. This should work with a lambda expression or method reference just fine.
A more apt test would probably verify(packetConsumer, atLeastOnce()).consumePacket(...), as the contents of the lambda are an implementation detail and you're really more concerned about how your component collaborates with other components. The abstraction here should be at the consumePacket level, not at the addConsumer level.
See the comments and answer on this SO question.

Action composition using #With annotation in Play framework (Java)

How can I use two action compositions in Play Framework 2.4 (in Java)?
Suppose that, to avoid code duplication, I've got two actions to use :Auth and LogData.
How can I use both in an action composition?
This won't compile, causing a duplicate annotation error:
# play.PlayExceptions$CompilationException: Compilation error[error:
duplicate annotation]
#play.db.jpa.Transactional()
#With(Auth.class)
#With(LogData.class)
public static Result callForumTeacher(String random, Long gameId){
//Action code
return ok(Json.toJson("data"));
}
This is a skeleton on how Auth and LogData are implemented:
public class CheckPausedGame extends Action.Simple {
#Override
public F.Promise<Result> call(Http.Context context) throws Throwable {
if (checkCondition(context)) {
return delegate.call(context);
} else {
F.Promise<Result> promise = F.Promise.promise(new F.Function0<Result>() {
#Override
public Result apply() throws Throwable {
return redirect("/paused");
}
});
return promise;
}
}
}
This only a skeleton omitting some methods not useful for this question.
While the documentation doesn't seem to clearly state this (at least I haven't found it anywhere), the intended way to use #With in cases like this is to pass all Actions at once (With takes an array)
Your code becomes
#play.db.jpa.Transactional()
#With(value = {Auth.class, LogData.class})
public static Result callForumTeacher(String random, Long gameId){
//Action code
return ok(Json.toJson("data"));
}
See the api doc

How can I add a datasource to a UIMap method instead of a Test Method (VS 2010 Coded UI Test)

I have a 2010 Coded UI Test that performs some actions against a website. I am able to add a datasource to a "Test Method" which loops the entire method once per record.
But, what I really want to do is loop only a portion of the test which is just a single recorded method in the UIMap.
Let's say the test method looks something like this:
//[DataSource("Microsoft.VisualStudio.TestTools.DataSource.XML", "|DataDirectory|\\TestCommunities.xml", "Community", DataAccessMethod.Sequential), DeploymentItem("Tests\\WebTests\\DataSources\\TestCommunities.xml"), TestMethod]
public void LoginCreateCommunities()
{
this.UIMap.LoginAdmin();
//this.UIMap.CreateCommunityParams.UIItem0EditText = TestContext.DataRow["CommunityName"].ToString();
this.UIMap.CreateCommunity();
this.UIMap.LogoffClose();
}
It's only UIMap.CreateCommunity() that I want to loop the datasource. I do not want all 3 methods to execute per record in the datasource, which is what happens when I attach the datasource to the test method (the portion commented out above).
Is there a way to achieve what I'm trying to do here?
Thanks.
You have to use the ClassInitialize and ClassCleanup methods. You place it in the #region Additional test attributes area at the bottom. So for you it'd look something like:
#region Additional test attributes
[ClassInitialize]
static public void ClassInit(TestContext context)
{
Playback.Initialize();
try
{
sharedTest.LoginAdmin();
}
finally
{
Playback.Cleanup();
}
}
[ClassCleanup]
static public void ClassCleanup()
{
Playback.Initialize();
try
{
sharedTest.LogoffClose();
}
finally
{
Playback.Cleanup();
}
}
#endregion
first you have to define a new UIMap in your codedUI class
[CodedUITest]
public class CodedUITest1
{
static private UIMap sharedTest = new UIMap();
....
[ClassInitialize()]
static public void ClassInit(TestContext context)
{
Playback.Initialize();
try
{
sharedTest.RecordedStartApp();
}
finally
{
Playback.Cleanup();
}
}
[ClassCleanup()]
static public void ClassCleanup()
{
Playback.Initialize();
try
{
sharedTest.RecordedCloseApp();
}
finally
{
Playback.Cleanup();
}
}
}

Plug-in Development: Creating Problem Marker for a Given Resource

I seem to be having a problem with associating a problem marker with a resource; in my case, I'm trying to create a problem marker for the editor.
To achieve this, I've tried to do the following:
public class MyEditor extends TextEditor{
private ColorManager colorManager;
public MyEditor() {
super();
...
IResource resource = (IResource) getEditorInput().getAdapter(IResource.class);
try
{
marker = resource.createMarker(IMarker.PROBLEM);
}
catch (CoreException e)
{
e.printStackTrace();
}
}
However, the problem is getEditorInput() keeps returning null. I assume I am not calling it at the right location. I thought it would be ideal to create the marker once I'm setting up the editor, but this proves otherwise.
Does anyone have any advice to obtaining the proper resource I want so that I may create the problem marker? I would like to show errors and such within the editor.
I've looked at samples online for creating the marker, but most just show methods that pass the ITextEditor object without showing where the method call is. (for example: Creating Error Marker for Compiler -- see reportError method)
Thank you.
Paul
Edit:
I have also viewed the following link regarding problem markers, but again, it calls createMarker from a resource(res, in this case), but does not show the setup for it.
See Show Syntax Errors in An Eclipse Editor Plugin
EditorInput is initialize in init method
You can override init or
public class MyEditor extends TextEditor{
private ColorManager colorManager;
public MyEditor() {
super();
...
}
public void init(IEditorSite site, IEditorInput input)
throws PartInitException {
super.init(site, input);
IResource resource = (IResource) getEditorInput().getAdapter(IResource.class);
try
{
marker = resource.createMarker(IMarker.PROBLEM);
}
catch (CoreException e)
{
e.printStackTrace();
}
}
I create a marker (including a call to getEditorInput()) from the run() method of an Action object.
public class MyAction extends Action {
...
public void run() {
...
int line = ...;
IEditorInput ei = editor.getEditorInput()
if (ei != null)
createMarkerAt(line, ei);
}
}
Addition (Following Paul's comment) How to get an Editor?
Well, In my app I am subclassing AbstractRulerActionDelegate, by overriding the createAction(ITextEditor e, IVerticalRulerInfo ri) method (which, BTW, Is a must - this method is abstract) my app can get the relevant ITextEditor object.

Resources