Blog

- Showing all posts in category: Android

When showing a DialogFragment the title is not visible when opening it on a small resolution or on a smartphone. This is the default behavior/styling of Android to preserve space for the content. In some cases you don' t want to hide the title because the user could miss the context of the dialog. 

For example you have a dialog with a EditText and a submit button. It would be shown like this:

Well how the heck do I know what to fill in here?

Let' s show that title

Open styles.xml and add this style:

<style name="DialogWithTitle" parent="@style/Theme.AppCompat.Light.Dialog">
	<item name="android:windowNoTitle">false</item>
</style>

The naming of the android:windowNoTitle property is obscure. So if I would like to show the title, you to set it to false

In your DialogFragment class you have to set the style:

	public static AlertTextDialogFragment newInstance() {
		AlertTextDialogFragment fragment = new AlertTextDialogFragment();
		fragment.setStyle(STYLE_NORMAL, R.style.DialogWithTitle);
		Bundle args = new Bundle();
		fragment.setArguments(args);
		return fragment;
	}

Tadaa, the title is always visible now.


Protip

If you have to create some kind of setting or boolean name, try to give it the positive name. In this case it could be clear if the name would be android:showWindowTitle. 

Try to prevent these kind of names:

boolean disableChecks
boolean notShowing
boolean dontSave

 

Today I was trying to run a unit test in Android but for some reason it didn't work. It was a Doh! moment again

This was the message I got:

Process finished with exit code 1
Class not found: "xx.xx.xx"Empty test suite.

In Android there are two kinds of unit tests:

  • Local unit tests which will run on your computer inside JVM
  • Instrumented unit tests that only will run on an Android device

These tests have their own package with the same name as your identifier.

You would see this inside your java folder:

nl.orhun.myapp < -- source files
nl.orhun.myapp (androidTest) <-- instrumented test files
nl.orhun.myapp (test) < -- local unit test files

The advantage of local unit testing is that you don't have the overhead to need to run a virtual device. It just simply can run on your computers JVM. Unfortunately you can't make use of Android framework features. So this will only be handy to test your own code which is not Android framework dependent.

Initially I created a local unit test and ran it. After that I moved the class to the androidTest to make it a instrumented test

Because I ran it before, it remembered my last run configuration. The next time I ran the LoginTest, it tried to run is as a LocalTest while the test is inside androidTest package which gave this error.

So, when you move a unit test from a local test to androidTest, check your Run/Debug settings. In my case I could remove the configuration so the next time a new one is generated again.

 

All your androidTest configurations are under AndroidTests. The local unit tests are under JUnit.

Today I wanted to create a AttachmentMenuDialog which will be reusable in an Activity or Fragment. Like the name says, it's a DialogFragment which will be used to add file attachments to your Activity/Fragment.

In the image below you see that I have two Activities who are opening the AttachmentMenuDialog. The only difference is that ActivityOne is opening the fragment directly and ActivityTwo is opening from another fragment.

I struggled with the problem that it worked in one of the both Activities. So when I fix it for ActivityOne, it broke at ActivityTwo and vice versa.

 

Inside AttachmentMenuDialog I have three buttons:

  • Add a file from the storage (File intent)
  • Take a picture with the camera (Camera intent)
  • Create a PDF document inside PDFActivity

Adding a file from storage and taking a picture was no problems at all, but getting the PDF document as a result from the PDFActivity was not so easy as it should be.

On the PDF button I had this onClickListener:

AttachmentMenuDialog.java:

pdfButton.setOnClickListener(new View.OnClickListener() {
	@Override
	public void onClick(View view) {
		Intent intent = new Intent(getContext(), PDFActivity.class);
                //REQUEST_CODE_PDF = 1234
		startActivityForResult(intent, REQUEST_CODE_PDF);
	}
});

This should work like expected you think? Well it's not. Not on this way at least. The PDFActivity is opened, and when I create a PDF, I would like to have the result back inside my Activity. Like the scheme above I would like to have the PDF document inside ActivityOne or ActivityTwo.

The problem is that when you open the activity by using the fragments startActivityForResult, you will lose the requestCode. Your activity regenerates a new one and you will never ever, ever get your result back. After running the debugger  I found out that the requestCode is always changed to the number 65660. Don't ask me why.

Solution:

You have to start the Activity from your parent activity like this:

getActivity().startActivityForResult(intent, REQUEST_CODE_PDF);

When the PDFActivity is finished, it will execute onActivityResult() from the parent Activity. You will have to delegate it to your fragment if you need it there.

ActivityOne.java

@Override
public void onActivityResult(int requestCode, int resultCode, final Intent data) {
	if (attachmentMenuDialog != null) {
		attachmentMenuDialog.onActivityResult(requestCode, resultCode, data);
	}
}

 

Well the first problem is solved. My PDF document from PDFActivity is passed to my Activity where I expect it, but like I'm not frustrated enough, I faced a new problem. Why the heck is my Activity(ActivityOne) closing  when I create my PDF inside PDFActivity?

In ActivityOne and in ActivityTwo the PDFActivity returned the PDF document inside the onActivityResult method. For some reason ActivityTwo finished/closed automatically when PDFActivity was finished.

Let's take a look at the PDFActivity where I finish the activity

public static final int RESULT_PDF_OK = 5;

public void onTaskComplete(File pdfFile) {
	Intent intent = new Intent();
	intent.putExtra(INTENT_PDF_FILE, pdfFile);
	setResult(RESULT_OK, intent);
	finish();
}

The problem is that I was putting RESULT_OK as status code which is an reserved status for internal usage. Android uses resultcodes untill 1 for internal usage. Like RESULT_OK = -1.  For your own purposes you can safely use custom resultCodes which are bigger than 1.

I think that because I opened the whole Fragment/Activity chain by using getActivity().startActivityForResult() that I passed the context of my Activity to the PDFActivity which unintentionally finishes the Activity because the result is RESULT_OK.

It took me 8 hours to solve this problem. I was creating a custom view that extends LinearLayout and having a RecyclerView as child. The problem was that RecyclerView didn't measured correctly so the width and height stayed on 0dp. The RecyclerView was never visible.

While trying some tricks and hacks to measure the RecyclerView, I've found out that this was just an Android bug that's fixed on februari 25, 2016. RecyclerView was ignoring the layout params such as WRAP_CONTENT and MATCH_PARENT.

Upgrade the RecyclerView dependency at least to this version:

compile 'com.android.support:recyclerview-v7:23.2.0'

Also take a look at this article about Android Support Library 23.2.

Happy programming all!

When you are creating your awesome Android app, you'll make use of the awesome Android libraries like listed on this page.
Sometimes you will face the problem that you want to add some behaviour to some component like a View.

I had the following problem: I was using Android material chips library, but I needed to do something when the user lost focus of the EditText. I have managed to get the EditText view instance by using View.findViewById(), but the library already had implemented OnFocusChangeListener. If I set my own OnFocusChangeListener implementation, then I will break the functionality of the library. So I had to find an alternative way to detect the focus/blur event.

You can do it with the following code:

ViewTreeObserver viewTreeObserver = getViewTreeObserver();
viewTreeObserver.addOnGlobalFocusChangeListener(new ViewTreeObserver.OnGlobalFocusChangeListener() {
    @Override
    public void onGlobalFocusChanged(View oldFocus, View newFocus) {
        //oldFocus could be null
        if (oldFocus == null || !oldFocus.equals(myEditText)) {
            return;
        }
        doYourThing();
    }
});

 

Just don't forget to check if the oldFocus is null or not, or else you will get a NPE.

Focus on a EditText and move the cursor end of the last character.

EditText editText = (EditText) findViewById(R.id.myEditText);
editText.requestFocus();
editText.setSelection(editText.getText().length());

 

 

Let Android open a file in an app that can handle the file, like opening a PDF in Adobe Reader. Or opening an image in your photo viewer.

Determine the mimetype by file extension:

public static String getMimeType(String filename) {
    String type = null;
    String extension = MimeTypeMap.getFileExtensionFromUrl(filename);

    if (extension != null) {
        type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
    }
    return type;
}

 

Let Android open the file by finding the right app for it. It throws an unchecked ActivityNotFoundException if there could not be found an app that can handle this file.

public static void openIntent(Context context, File file, String mimeType) {
	String mimetype = mimeType;
	Intent myIntent = new Intent(android.content.Intent.ACTION_VIEW);
	myIntent.setDataAndType(Uri.fromFile(file), mimetype);
	try {
		context.startActivity(myIntent);
	} catch(ActivityNotFoundException e) {
		Toast.makeText(context, "No app found for this file type.",
				Toast.LENGTH_SHORT).show();
	}
}

 

Use it like this:

//The file you want to open
File file = new File("/somedir/somefile.png");

//Get the mimetype of the file
String mimeType = getMimeType(file.getName());

//Open the file in a new Activity
openIntent(getContext(), file, mimeType);

 

# Android vibrate programmatically
Published on 15-02-2016

To vibrate your Android device programatically use the code below. The 1000 stands for a duration of 1000 milliseconds.

((Vibrator)getSystemService(VIBRATOR_SERVICE)).vibrate(1000);

 

Don't forget to add the required permission to your AndroidManifest.xml file:

<uses-permission android:name="android.permission.VIBRATE" />