This is my first time experience of decompiling an apk to java code. The following code is of a local TVApp launcher which is ofcourse android based. To my surprise, I found out that the decompilers do not do a complete conversion to the source code. Hence, it messes up a thing or two. I have tried to work around with what I had, and made functions out of labels. Although I got it to work, but I suppose I missed out on some things..
Can someone guide me how to get this to work correctly? Do I have to do a manual refactoring of the code or is there a tool available for this?
public void run()
{
EN_INPUT_SOURCE_TYPE localEN_INPUT_SOURCE_TYPE;
int i;
ITvServiceServer localITvServiceServer;
for (;;)
{
if (LauncherActivity.this.bExitThread.booleanValue()) {
return;
}
synchronized (LauncherActivity.this.bSync)
{
localEN_INPUT_SOURCE_TYPE = LauncherActivity.this.toChangeInputSource;
LauncherActivity.this.toChangeInputSource = EN_INPUT_SOURCE_TYPE.E_INPUT_SOURCE_NONE;
i = LauncherActivity.this.fullScale;
LauncherActivity.this.fullScale = 0;
if (localEN_INPUT_SOURCE_TYPE != EN_INPUT_SOURCE_TYPE.E_INPUT_SOURCE_NONE)
{
localITvServiceServer = ITvServiceServer.Stub.asInterface(ServiceManager.checkService("tv_services"));
if (localITvServiceServer == null) {
Log.w("LauncherActivity", "Unable to find ITvService interface.");
}
}
else
{
if (i != 2) {
break label345;
}
LauncherActivity.this.setPipscale();
try
{
label104:
Thread.sleep(100L);
}
catch (InterruptedException localInterruptedException)
{
localInterruptedException.printStackTrace();
}
}
}
}
for (;;)
{
for (;;)
{
ITvServiceServerCommon localITvServiceServerCommon;
try
{
localITvServiceServerCommon = localITvServiceServer.getCommonManager();
if (localEN_INPUT_SOURCE_TYPE != EN_INPUT_SOURCE_TYPE.E_INPUT_SOURCE_ATV) {
break label324;
}
if (!localITvServiceServerCommon.GetCurrentInputSource().equals(EN_INPUT_SOURCE_TYPE.E_INPUT_SOURCE_STORAGE)) {
break;
}
if (LauncherActivity.this.minidatabase != null) {
break label275;
}
j = 0;
if ((j < 0) || (j > EN_INPUT_SOURCE_TYPE.E_INPUT_SOURCE_NONE.ordinal())) {
break;
}
localITvServiceServerCommon.SetInputSource(EN_INPUT_SOURCE_TYPE.values()[j]);
if (EN_INPUT_SOURCE_TYPE.values()[j] != EN_INPUT_SOURCE_TYPE.E_INPUT_SOURCE_ATV) {
break label290;
}
k = localITvServiceServer.getChannelManager().getCurrentChannelNumber();
if ((k < 0) || (k > 255)) {
break label361;
}
localITvServiceServer.getChannelManager().programSel(k, EN_MEMBER_SERVICE_TYPE.E_SERVICETYPE_ATV);
}
catch (RemoteException localRemoteException1)
{
localRemoteException1.printStackTrace();
}
break;
label275:
int j = LauncherActivity.this.minidatabase.queryCurInputSrc();
continue;
label290:
if (EN_INPUT_SOURCE_TYPE.values()[j] != EN_INPUT_SOURCE_TYPE.E_INPUT_SOURCE_DTV) {
break;
}
localITvServiceServer.getChannelManager().changeToFirstService(EN_FIRST_SERVICE_INPUT_TYPE.E_FIRST_SERVICE_DTV, EN_FIRST_SERVICE_TYPE.E_DEFAULT);
break;
try
{
label324:
localITvServiceServerCommon.SetInputSource(localEN_INPUT_SOURCE_TYPE);
}
catch (RemoteException localRemoteException2)
{
localRemoteException2.printStackTrace();
}
}
break;
label345:
if (i != 1) {
break label104;
}
LauncherActivity.this.setFullscale();
break label104;
label361:
int k = 0;
}
}
Do I have to do a manual refactoring of the code? YES.
The only thing you can do (in Eclipse) is pressing ALT+R on a selected label and change all its occurrences.
Decompiling is not 100% complete/accurate, due to how the process works, I suggest you read: http://en.wikipedia.org/wiki/Decompiler to understand more on the process.
It is fairly accurate though on some virtual machines like Java, as its bytecode includes extensive metadata. That's why you got a 'nice' result.
You will have to do a lot of manual refactoring anyway.
And bear in mind the legality of what you are doing, check licenses and copyright.
Related
Recently, I tried to write a Java program which searches for the minimum of an array.
I tried to write it in a different way, I know there are more simple ways to do that but I want to know why my program does not work.
Here is the source code :
public int minimum(int [] t) {
int min,i,j;
i=j=t.length/2;
min=t[t.length/2];
while(j!=0 || i!=t.length-1) {
while( t[i]>=min) {
i++;
if(i==t.length) {
i=t.length-1;
continue;
}
}
while(t[j]>=min) {
j--;
if(j==-1) {
j=0;
continue;
}
}
if(t[i]<=min && t[j]<=min) {
if(t[i]<=t[j]) min=t[i];
else min=t[j];
}
}
return min;
}
Thanks.
Before you read the answer you should try debugging your code to figure this out by yourself.
I think your code loops infinitely in one of those inner while loops because the end condition
if(i==t.length) {
i=t.length-1;
continue;
}
only resets the i one step back and the continue restarts the while loop. You probably meant to have the break keyword there instead of the continue in which case your code will continue with the other inner while loop.
there is some logic errors in my code , and it get infinitely going through the two loops , i fixed the loops by changing continue with break and i modify the last condition by setting || instead of && (that was a logic mistake), and it works now .
thanks guys.
here is the new source code:
public int minimum(int [] t) {
int min,i,j;
i=j=t.length/2;
min=t[t.length/2];
while(j!=0 || i!=t.length-1) {
while( t[i]>=min) {
i++;
if(i==t.length) {
i=t.length-1;
break;
}
}
while(t[j]>=min) {
j--;
if(j==-1) {
j=0;
break;
}
}
if(t[i]<=min || t[j]<=min) {
if(t[i]<=t[j]) min=t[i];
else min=t[j];
}
}
return min;
}
I'm trying to apply retry logic to a number of methods. For example, I have method1(String) and method2(int, String) that I would like to retry up to a certain number of times.
I would ideally like:
int count = 0;
while (count < MAX_TRIES) {
try {
//run method
} catch (Exception e) {
//increment count
//throw e if count == MAX_TRIES
}
}
inside a method where I could pass in as a parameter method1 or method2. Is there any way to do this? Thanks!
Sure:
public <T> T retry(Callable<T> callable) throws Exception {
int count = 0;
while (true) {
try {
return callable.call();
} catch (Exception e) {
count++;
if (count == MAX_TRIES) {
throw(e);
}
}
}
}
And then
retry(() -> doSomething(a, b));
retry(() -> doSomethingElse(a));
This simple implementation is not very flexible, and could use better exception handling, though. You could use a library to do that (disclaimer: I'm the original author of this library), or at least see how it works and reuse some of its ideas.
I have needed to program something like this several times since programming Java:
Do something that might fail. If it fails, try it again but at most 3 (or 2 or 5) times.
This approach should work:
for (int i = 0; i < 3; i++) {
try {
doSomething();
} catch(BadException e) {
continue;
}
break;
}
But I do not think that it is very expressive. Do you have a better solution?
Something like this would be nice:
try (maxTimes = 3) {
doSomething();
} catch(BadException e) {
retry;
}
Or:
try (maxTimes = 3) {
doSomething();
if(somethingFailed()) {
retry;
}
}
But this is not possible with Java. Do you know a language with which it is possible?
Java does not let you invent your own syntax, but you can define your own method to help you express the concept with less code:
public static boolean retry(int maxTries, Runnable r) {
int tries = 0;
while (tries != maxTries) {
try {
r.run();
return true;
} catch (Exception e) {
tries++;
}
}
return false;
}
Now you can call this method like this:
boolean success = retry(5, () -> doSomething());
// Check success to see if the action succeeded
// If you do not care if the action is successful or not,
// ignore the returned value:
retry(5, () -> doSomethingElse());
Demo.
I am working on a landscape java game.
I have a sprite array like this;
Sprite stickArray[] = new Sprite[10];
and initializing it like this with visibility as false.
for (int j = 0; j < stickArray.length; j++) {
if (stickArray[j] != null) {
stickArray[j].setPosition(stickX, stickY);
stickArray[j].setVisible(false);
}
}
Later I want to position it like one after another vertically on repeating a key.pressBool is false initially.
public void keyRepeatInGame(int keyCode) {
int gameKey = getGameAction(keyCode);
Graphics g = getGraphics();
if (gameKey == FIRE || keyCode == KEY_NUM5) {
pressBool = true;
}
}
Later I have written code like this;
Initially one Sticksprite is there.above this sprite, I want to place each sticks on clalling keyrepeat()in space key.
for (int i = 0; i < stickArray.length; i++) {
if (pressBool) {
if (i == 0) {
stickArray[i].setPosition(stickSprite.getX(),
stickSprite.getY() - stickSprite.getHeight());
stickArray[i].setVisible(true);
} else {
stickArray[i].setPosition(stickArray[i-1].getX(),
stickArray[i-1].getY() - stickArray[i].getHeight());
stickArray[i].setVisible(true);
}
}
}
This code is working partially.Stick is getting added on the sprite,all at once.
How can I change the code to make the sticks repeatedly getting added on calling keyrepeat() only, and make it visible one by one properly?
I changed the code with an additional condition and break statement like this;
if (pressBool) {
if (stickSprite != null && !stickArray[i].isVisible()
&& stickArray[i] != null) {
if (i == 0) {
stickArray[i].setPosition(
stickSprite.getX(),
stickSprite.getY());
stickArray[i].setVisible(true);
break;
} else if (i > 0) {
stickArray[i].setPosition(
stickArray[i].getX(),
stickArray[i - 1].getY()
- stickArray[i].getHeight());
stickArray[i].setVisible(true);
break;
}
}
}
It worked.
I've been working with SikuliX to get some try some ATDD. The code works well when only I am the one working with it. However transferring the below code to anyone else is simply counter-productive irrespective of how well I comment the code.
int numOfTries;
while (!isFinishStage && numOfTries != 3) {
numOfTries++;
try {
temp = new Pattern("imgs/img1.png").similar(0.9f);
s.wait(temp, 1);
s.find(temp);
s.hover(temp);
isFinishStage = true;
break;
}catch (FindFailed ff1) {
try {
temp = new Pattern("imgs/img2").similar(0.5f);
s.wait(temp, 1);
s.find(temp);
s.hover(temp);
isFinishStage = true;
break;
} catch (FindFailed ff2) {
try{
temp = new Pattern("imgs/img3");
s.wait(temp, 1);
s.find(temp);
s.click(temp);
} catch (FindFailed ff3) {
continue;
}
}
}
}
A FindFailed exception is thrown once a pattern/image cannot be matched against anything on the screen (similarity simply adjusts the tolerance level). For the current GUI that it is automating, there are three possible scenarios (where this piece of code comes to play)
Screen A pops up
Screen B pops up
Neither 1 or 2, instead 'Next' pops up
Thus we check for Screen A, if not we check for Screen B, if not we check for Next, if not, repeat the cycle until we exceed the number of tries — meaning that the test has failed.
With the way Sikuli works or atleast how I've been interpreting it, you would have to perform various loops through multiple try-catch statements which seems a little off putting.
PS: The idea behind the above code is to just get it to work. If there is any ambiguity let me know so that I can clarify.
The following code is (I think) equivalent to your code:
int numOfTries;
while (!isFinishStage && numOfTries < 3) {
numOfTries++;
if (tryPattern(s, "imgs/img1.png", 0.9f) ||
tryPattern(s, "imgs/img2", 0.5f)) {
isFinishStage = true;
} else {
// Note that the third "attempt" is inconsistent with
// the others because you don't set isFinishedStage.
tryPattern(s, "imgs/img3", 1.0f)
}
}
private boolean tryPattern(SomeClass s, String path, float similarity) {
try {
Pattern temp = new Pattern(path);
if (similarity != 1.0f) {
temp = temp.similar(similarity);
}
s.wait(temp, 1);
s.find(temp);
s.hover(temp);
return true;
} catch (FindFailed ff) {
return false;
}
}
I would like you to read software principles and make your code clean after lecture:
10 Object Oriented Design Principles
After this you should know basics like DRY and KISS principles that should emplace pretty well in your posted code.
Here's how:
String [] patterns = {
"imgs/img1",
"imgs/img2",
"imgs/img3"
};
float [] similarities = {
0.9f,
0.5f,
0.1f
};
for(int i=0; i<patterns.length; i++) {
String str = patterns[i];
try {
float sim = 0.1; // default
try {
sim = similarities[i];
} catch (IndexOutofBoundsException e) {;}
temp = new Pattern(str).similar(sim);
s.wait(temp, 1);
s.find(temp);
s.hover(temp);
if(i != patterns.length - 1){ // Different last case
isFinishStage = true;
break;
}
} catch (FindFailed ff) {
continue;
}
}