package com.njlabs.showjava.ui; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.os.Handler; import android.text.TextUtils; import android.view.animation.Animation; import android.view.animation.LinearInterpolator; import android.view.animation.RotateAnimation; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import com.njlabs.showjava.Constants; import com.njlabs.showjava.R; import com.njlabs.showjava.processor.ProcessService; import com.njlabs.showjava.utils.Utils; import com.njlabs.showjava.utils.logging.Ln; import net.dongliu.apk.parser.ApkParser; import org.apache.commons.io.FilenameUtils; import java.io.File; import java.net.URI; public class AppProcessActivity extends BaseActivity { private TextView CurrentStatus; private TextView CurrentLine; private String packageFilePath; private BroadcastReceiver processStatusReceiver; private String decompilerToUse = "cfr"; private boolean processStarted = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); processStatusReceiver = new ProcessStatus(); setupLayoutNoActionBar(R.layout.activity_progress); CurrentStatus = (TextView) findViewById(R.id.current_status); CurrentLine = (TextView) findViewById(R.id.current_line); TextView appNameView = (TextView) findViewById(R.id.current_package_name); CurrentStatus.setText(R.string.status_starting_decompiler); if (getIntent().getDataString() == null || getIntent().getDataString().equals("")) { Bundle extras = getIntent().getExtras(); appNameView.setText(extras.getString("package_label")); packageFilePath = extras.getString("package_file_path"); if (packageFilePath != null) { try { ApkParser apkParser = new ApkParser(new File(packageFilePath)); appNameView.setText(apkParser.getApkMeta().getLabel()); } catch (Exception e) { Ln.e(e); exitWithError(); } if (extras.containsKey("decompiler")) { decompilerToUse = extras.getString("decompiler"); } } else { finish(); } } else { packageFilePath = (new File(URI.create(getIntent().getDataString()))).getAbsolutePath(); if (FilenameUtils.isExtension(packageFilePath, "apk")) { try { ApkParser apkParser = new ApkParser(new File(packageFilePath)); appNameView.setText(apkParser.getApkMeta().getLabel()); } catch (Exception e) { Ln.e(e); exitWithError(); } } } if (fromNotification() && Utils.isProcessorServiceRunning(this)) { CurrentStatus.setText(getResources().getString(R.string.status_processing)); CurrentLine.setText(""); } else { startProcessorService(); } appNameView.setSingleLine(false); appNameView.setEllipsize(TextUtils.TruncateAt.END); appNameView.setLines(1); CurrentStatus.setSingleLine(false); CurrentStatus.setEllipsize(TextUtils.TruncateAt.END); CurrentStatus.setLines(1); setupGears(); registerBroadcastReceiver(); new Handler().postDelayed(new Runnable() { @Override public void run() { if (!fromNotification()) { if (!processStarted || Utils.isProcessorServiceRunning(baseContext)) { try { unregisterReceiver(processStatusReceiver); } catch (Exception ignored) { } Utils.forceKillAllProcessorServices(baseContext); final Intent mainIntent = new Intent(baseContext, ErrorActivity.class); mainIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(mainIntent); finish(); } } } }, 5000); } private void setupGears() { final ImageView GearProgressLeft = (ImageView) findViewById(R.id.gear_progress_left); final ImageView GearProgressRight = (ImageView) findViewById(R.id.gear_progress_right); final RotateAnimation GearProgressLeftAnim = new RotateAnimation(0.0f, 360.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); GearProgressLeftAnim.setRepeatCount(Animation.INFINITE); GearProgressLeftAnim.setDuration((long) 2 * 1500); GearProgressLeftAnim.setInterpolator(new LinearInterpolator()); final RotateAnimation GearProgressRightAnim = new RotateAnimation(360.0f, 0.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); GearProgressRightAnim.setRepeatCount(Animation.INFINITE); GearProgressRightAnim.setDuration((long) 1500); GearProgressRightAnim.setInterpolator(new LinearInterpolator()); GearProgressLeft.post(new Runnable() { @Override public void run() { GearProgressLeft.setAnimation(GearProgressLeftAnim); } }); GearProgressLeft.post(new Runnable() { @Override public void run() { GearProgressRight.setAnimation(GearProgressRightAnim); } }); } private void startProcessorService() { Utils.killAllProcessorServices(this, true); Intent mServiceIntent = new Intent(getContext(), ProcessService.class); mServiceIntent.setAction(Constants.ACTION.START_PROCESS); mServiceIntent.putExtra("package_file_path", packageFilePath); mServiceIntent.putExtra("decompiler", decompilerToUse); startService(mServiceIntent); processStarted = true; } private void registerBroadcastReceiver() { IntentFilter statusIntentFilter = new IntentFilter(Constants.PROCESS_BROADCAST_ACTION); registerReceiver(processStatusReceiver, statusIntentFilter); } @SuppressWarnings("unused") protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == 1) { if (resultCode == RESULT_OK) { String result = data.getStringExtra("result"); finish(); } if (resultCode == RESULT_CANCELED) { finish(); } else { finish(); } } } private boolean fromNotification() { return getIntent().hasExtra("from_notification") && getIntent().getBooleanExtra("from_notification", false); } private void exitWithError() { Toast.makeText(baseContext, R.string.decompiler_initialise_error, Toast.LENGTH_LONG).show(); finish(); } @Override protected void onDestroy() { super.onDestroy(); try { unregisterReceiver(processStatusReceiver); } catch (Exception ignored) { } } private class ProcessStatus extends BroadcastReceiver { private ProcessStatus() { } public void onReceive(Context context, Intent intent) { String statusKey = ""; String statusData = ""; if (intent.hasExtra(Constants.PROCESS_STATUS_KEY)) { statusKey = intent.getStringExtra(Constants.PROCESS_STATUS_KEY); } if (intent.hasExtra(Constants.PROCESS_STATUS_MESSAGE)) { statusData = intent.getStringExtra(Constants.PROCESS_STATUS_MESSAGE); } switch (statusKey) { case "optimise_dex_start": processStarted = true; CurrentStatus.setText(R.string.status_optimising_dex); break; case "optimising": processStarted = true; CurrentStatus.setText(R.string.status_optimising_dex); CurrentLine.setText(""); break; case "optimise_dex_finish": CurrentStatus.setText(R.string.status_optimising_dex_finish); break; case "merging_classes": CurrentStatus.setText(R.string.status_merging_classes); CurrentLine.setText(""); break; case "start_activity": if (intent.getStringExtra(Constants.PROCESS_DIR) != null && intent.getStringExtra(Constants.PROCESS_PACKAGE_ID) != null) { Intent iOne = new Intent(getApplicationContext(), JavaExplorer.class); iOne.putExtra("java_source_dir", intent.getStringExtra(Constants.PROCESS_DIR)); iOne.putExtra("package_id", intent.getStringExtra(Constants.PROCESS_PACKAGE_ID)); startActivityForResult(iOne, 1); } break; case "start_activity_with_error": Toast.makeText(baseContext, R.string.incomplete_source, Toast.LENGTH_SHORT).show(); if (intent.getStringExtra(Constants.PROCESS_DIR) != null && intent.getStringExtra(Constants.PROCESS_PACKAGE_ID) != null) { Intent iTwo = new Intent(getApplicationContext(), JavaExplorer.class); iTwo.putExtra("java_source_dir", intent.getStringExtra(Constants.PROCESS_DIR)); iTwo.putExtra("package_id", intent.getStringExtra(Constants.PROCESS_PACKAGE_ID)); startActivityForResult(iTwo, 1); } break; case "exit_process_on_error": Toast.makeText(baseContext, R.string.error_exiting, Toast.LENGTH_SHORT).show(); finish(); break; case "finaldex": CurrentStatus.setText(R.string.status_optimising_dex_finish); CurrentLine.setText(""); break; case "dex2jar": CurrentStatus.setText(R.string.status_dex2jar); break; case "jar2java": CurrentStatus.setText(R.string.status_jar2java); break; case "res": CurrentStatus.setText(R.string.status_extracting_res); break; case "exit": finish(); break; default: CurrentLine.setText(statusData); } } } }