4
\$\begingroup\$

How can I reduce the amount of repetitive code in my Android app? A lot of the code seems to be doing the same thing twice. I think that there is a more compact way to do this.

What are some ways that I can reduce lines of code in this program?
Is there a better way that I could write this program? I think that I am taking more steps than necessary.

The code is for this app.

package com.kerseykyle.easyhash;
import java.security.MessageDigest;
import android.os.Build;
import android.os.Bundle;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Intent;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends Activity {
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 Share();
 Intent intent = getIntent();
 String action = intent.getAction();
 String type = intent.getType();
 if (Intent.ACTION_SEND.equals(action) && type != null) {
 if ("text/plain".equals(type)) {
 handleSendText(intent); // Handle text being sent
 } 
 } 
 EditText myTextBox = (EditText) findViewById(R.id.input);
 myTextBox.setSingleLine(true);
 myTextBox.addTextChangedListener(new TextWatcher() {
 public void afterTextChanged(Editable s) {
 }
 public void beforeTextChanged(CharSequence s, int start, int count,
 int after) {
 }
 @TargetApi(Build.VERSION_CODES.HONEYCOMB)
 public void onTextChanged(CharSequence s, int start, int before,
 int count) {
 String md5hash = CreateHash(s.toString(), "MD5");
 TextView md5 = (TextView) findViewById(R.id.md5);
 md5.setText(md5hash);
 md5.setTextIsSelectable(true);
 String sha1hash = CreateHash(s.toString(), "SHA-1");
 TextView sha1 = (TextView) findViewById(R.id.sha1);
 sha1.setText(sha1hash);
 sha1.setTextIsSelectable(true);
 String sha256hash = CreateHash(s.toString(), "SHA-256");
 TextView sha256 = (TextView) findViewById(R.id.sha256);
 sha256.setText(sha256hash);
 sha256.setTextIsSelectable(true);
 String sha512hash = CreateHash(s.toString(), "SHA-512");
 TextView sha512 = (TextView) findViewById(R.id.sha512);
 sha512.setText(sha512hash);
 sha512.setTextIsSelectable(true);
 }
 });
 }
 public static String CreateHash(String data, String function) {
 try {
 MessageDigest digest = MessageDigest.getInstance(function);
 byte[] hash = digest.digest(((String) data).getBytes("UTF-8"));
 StringBuffer hexString = new StringBuffer();
 for (int i = 0; i < hash.length; i++) {
 String hex = Integer.toHexString(0xff & hash[i]);
 if (hex.length() == 1)
 hexString.append('0');
 hexString.append(hex);
 }
 return hexString.toString();
 } catch (Exception ex) {
 throw new RuntimeException(ex);
 }
 }
 public void Share() {
 TextView md5 = (TextView) findViewById(R.id.md5);
 md5.setOnClickListener(new OnClickListener() {
 @Override
 public void onClick(View v) {
 // TODO Auto-generated method stub
 EditText myTextBox = (EditText) findViewById(R.id.input);
 String md5hash = CreateHash(myTextBox.getText().toString(),
 "MD5");
 Intent sendIntent = new Intent();
 sendIntent.setAction(Intent.ACTION_SEND);
 sendIntent.putExtra(Intent.EXTRA_TEXT, md5hash);
 sendIntent.setType("text/plain");
 startActivity(sendIntent);
 }
 });
 TextView sha1 = (TextView) findViewById(R.id.sha1);
 sha1.setOnClickListener(new OnClickListener() {
 @Override
 public void onClick(View v) {
 // TODO Auto-generated method stub
 EditText myTextBox = (EditText) findViewById(R.id.input);
 String sha1hash = CreateHash(myTextBox.getText().toString(),
 "SHA-1");
 Intent sendIntent = new Intent();
 sendIntent.setAction(Intent.ACTION_SEND);
 sendIntent.putExtra(Intent.EXTRA_TEXT, sha1hash);
 sendIntent.setType("text/plain");
 startActivity(sendIntent);
 }
 });
 TextView sha256 = (TextView) findViewById(R.id.sha256);
 sha256.setOnClickListener(new OnClickListener() {
 @Override
 public void onClick(View v) {
 // TODO Auto-generated method stub
 EditText myTextBox = (EditText) findViewById(R.id.input);
 String sha256hash = CreateHash(myTextBox.getText().toString(),
 "SHA-256");
 Intent sendIntent = new Intent();
 sendIntent.setAction(Intent.ACTION_SEND);
 sendIntent.putExtra(Intent.EXTRA_TEXT, sha256hash);
 sendIntent.setType("text/plain");
 startActivity(sendIntent);
 }
 });
 TextView sha512 = (TextView) findViewById(R.id.sha512);
 sha512.setOnClickListener(new OnClickListener() {
 @Override
 public void onClick(View v) {
 // TODO Auto-generated method stub
 EditText myTextBox = (EditText) findViewById(R.id.input);
 String sha512hash = CreateHash(myTextBox.getText().toString(),
 "SHA-512");
 Intent sendIntent = new Intent();
 sendIntent.setAction(Intent.ACTION_SEND);
 sendIntent.putExtra(Intent.EXTRA_TEXT, sha512hash);
 sendIntent.setType("text/plain");
 startActivity(sendIntent);
 }
 });
 {
 }
 }
 @TargetApi(Build.VERSION_CODES.HONEYCOMB)
 void handleSendText(Intent intent) {
 String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
 if (sharedText != null) {
 EditText input = (EditText) findViewById(R.id.input);
 input.setText(sharedText);
 String md5hash = CreateHash(sharedText, "MD5");
 TextView md5 = (TextView) findViewById(R.id.md5);
 md5.setText(md5hash);
 md5.setTextIsSelectable(true);
 String sha1hash = CreateHash(sharedText, "SHA-1");
 TextView sha1 = (TextView) findViewById(R.id.sha1);
 sha1.setText(sha1hash);
 sha1.setTextIsSelectable(true);
 String sha256hash = CreateHash(sharedText, "SHA-256");
 TextView sha256 = (TextView) findViewById(R.id.sha256);
 sha256.setText(sha256hash);
 sha256.setTextIsSelectable(true);
 String sha512hash = CreateHash(sharedText, "SHA-512");
 TextView sha512 = (TextView) findViewById(R.id.sha512);
 sha512.setText(sha512hash);
 sha512.setTextIsSelectable(true);
 }
 } 
}
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Dec 26, 2013 at 19:55
\$\endgroup\$
1
  • 1
    \$\begingroup\$ You should remove // TODO Auto-generated method stub as soon as you put any code in the method. It's just there to help you to find the method. \$\endgroup\$ Commented Dec 27, 2013 at 7:51

1 Answer 1

4
\$\begingroup\$

This type of problem is conveniently solved with a Strategy Pattern. But, first things first:

  • you should search for efficient ways to convert bytes to hexadecimal-string values. This is a great solution I like....
  • Unless you have no choice (you are using Patterns/Matchers) you should always use StringBuilder instead of StringBuffer
  • The method CreateHash should not have a capital-letter to start with, it should rather be createHash

As for the Strategy Pattern.... In this case, you can create a class that listens for the text change, and updates the signature in the linked TextView. The same class listens for on-click on the TextView too. The class could have the signature

public abstract class HashDigestDisplay implements TextWatcher, OnClickListener {
 private final TextView view;
 private final MessageDigest digest;
 public HashDigestDisplay (TextView target, String digestName) throws NoSuchAlgorithmException {
 this.view = target;
 this.digest = MessageDigest.getInstance(digestName);
 this.view.setOnClickListener(this);
 }
 public void afterTextChanged(Editable s) {
 }
 public void beforeTextChanged(CharSequence s, int start, int count,
 int after) {
 }
 private String myDigest(String input) {
 digest.reset(); 
 byte[] hash = digest.digest(input.getBytes("UTF-8"));
 return bytesToHex(hash);
 }
 @TargetApi(Build.VERSION_CODES.HONEYCOMB)
 public void onTextChanged(CharSequence s, int start, int before, int count) {
 view.setText(myDigest(s.toString()));
 view.setTextIsSelectable(true);
 }
 @Override
 public void onClick(View v) {
 // TODO Auto-generated method stub
 EditText myTextBox = (EditText) findViewById(R.id.input);
 String hash = myDigest(myTextBox.getText().toString());
 Intent sendIntent = new Intent();
 sendIntent.setAction(Intent.ACTION_SEND);
 sendIntent.putExtra(Intent.EXTRA_TEXT, hash);
 sendIntent.setType("text/plain");
 startActivity(sendIntent);
 }
}

You can see the pattern that is emerging above. Obviously there are issues in the onClick method, but this is from copy/pasting your code.

Now, what you do in your onCreate() setup method is simply:

myTextBox.addTextChangedListener(
 new HashDigestDisplay((TextView) findViewById(R.id.md5), "MD5"));
myTextBox.addTextChangedListener(
 new HashDigestDisplay((TextView) findViewById(R.id.sha1), "SHA-1"));
....

After that, the system should be self-managing.

You only have one copy of the code, and the only things different about it are the name of the Digest and the target of the TextView.

answered Dec 26, 2013 at 20:50
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.