Android PDF Viewers In Depth

Helpful? Then DOWNLOAD and RATE my app!

Helpful? Then DOWNLOAD and RATE my app!

Google really dropped the ball when it decided not to provide a native PDF Viewer for Android.  After reading a lot on the subject, I understand that Google believed developers would be fine allowing their apps to open another application to view PDFs using the Intent structure. But, while some developers are OK with this approach many others don’t want to redirect their users to an uncontrolled experience that will close their own app.

Google finally realized this and included a native PDF viewer in KitKat (https://developer.android.com/about/versions/android-4.4.html). But, since the vast majority of users don’t have KitKat this doesn’t solve the problem – unless Google develops a compatibility library.

To frustrate the situation, a query on StackOverflow produces so many responses but no definitive answer to the question “what basic PDF Viewer can be added to my app?”. That is, until now.

Below I discuss every solution I ran across and how to use it – well, when I could get it to work. You can dig through each method if you want or you can trust my conclusion:

MuPDF is the best solution if 1)you have the patience and time to install it and 2)your code can be open source. If this is the case, follow my incredibly thorough instructions below and you will be satisfied.

PlugPDF is the best solution if 1)you want a plug-and-play solution and don’t have the time or patience to for MuPDF or 2)your code must remain closed source and 2)you can pay for it. Honestly, $699 for the code is fair since it’s a one time cost, you don’t have to hire a developer, and their competitors charge more than venture capitalists (not exaggerating).

iText


iText is NOT a PDF viewer! Instead, iText is a library that provides methods for creating a pdf, converting HTML to PDF, converting PDF to Bitmap, and other such PDF creation methods. You could use iText to convert a PDF to a Bitmap which is then displayed in a view, but then you’d be doing all the work to make a PDF Viewer when better solutions exist.

 Intents: Google Docs Reader


Launch a chooser that allows the user to select which web browser to use and then open Google Docs Viewer website to display the PDF.

Cost:

  • Free

Pros:

  • Really easy to implement
  • It’s free
  • PDFs are always loaded correctly
  • Zoom in/out with button

Cons:

  • Online PDF is displayed outside your app, in web browser instead of natively in app, and only with internet
  • Pinch zoom is not available

Features:

  • Display online PDF using a web browser

Usage:

MainActivity.java

import java.net.URLEncoder;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        String myPDFURL = "http://www.metafuture.org/pdf/futureofindonesia.pdf";

        String link;
        try{
            link="http://docs.google.com/viewer?url="
            +URLEncoder.encode(myPDFURL,"UTF-8")
            +"&embedded=true";            

            Uri uri = Uri.parse(link);
            Intent intent = new Intent(Intent.ACTION_VIEW, uri);
            startActivity(intent);
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

 Intents: PDF Viewer Chooser


Launch a chooser that allows the user to select which PDF viewer to use for opening the file.

Cost:

  • Free

Pros:

  • Really easy to implement
  • It’s free
  • Rich features without having to code or maintain them

Cons:

  • User is directed away from your app

Features:

  • Depends on the viewer that is selected

Usage:

AndroidManifest.xml




    

    
    
    
        
            
                

                
            
        
    

MainActivity.java
package com.pdfviewer_intentspdfchooser;

import java.io.File;
import java.util.List;

import android.app.Activity;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.widget.Toast;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        File file = new File(Environment.getExternalStorageDirectory().toString()
                + "/hospcombrprt.pdf");
        String mimeType = "pdf";
        
        openFile(file,mimeType);
    }
    
    private void openFile(File file, String mimeType){
        Intent viewIntent = new Intent();
        viewIntent.setAction(Intent.ACTION_VIEW);
        viewIntent.setDataAndType(Uri.fromFile(file), mimeType);
        
        // using the packagemanager to query is faster than trying startActivity
        // and catching the activity not found exception, which causes a stack unwind.
        List resolved = getPackageManager().queryIntentActivities(viewIntent, 0);
        
        if(resolved != null && resolved.size() > 0){
            startActivity(viewIntent);
        }else{
            // notify the user they can't open it.
            Toast.makeText(this, "Cannot open file", Toast.LENGTH_LONG).show();
        }
    }
}

Intents: Intents Adobe Reader


Open the file by forcing Adobe Reader to be launched. This will fail to open the document if the app is not already installed.

Cost:

  • Free

Pros:

  • Really easy to implement
  • It’s free
  • Rich features without having to code or maintain them

Cons:

  • User is directed away from your app

Features:

  • Depends on Adobe’s mood

Usage:

AndroidManifest.xml




    
    
    

    
        
            
                

                
            
        
    

MainActivity.java

package com.pdfviewer_intentadobereader;

import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        String filePath = Environment.getExternalStorageDirectory().toString()
                + "/hospcombrprt.pdf";
        
        try {
            loadDocInReader(filePath);
        } catch (ActivityNotFoundException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    private void loadDocInReader(String filePath)
        throws ActivityNotFoundException, Exception {

        try {
            Intent intent = new Intent();
    
            intent.setPackage("com.adobe.reader");
            intent.setDataAndType(Uri.parse(filePath), "application/pdf");
    
            startActivity(intent);

        } catch (ActivityNotFoundException activityNotFoundException) {
            activityNotFoundException.printStackTrace();

            throw activityNotFoundException;
        } catch (Exception otherException) {
            otherException.printStackTrace();

            throw otherException;
        }
    }
}

PDF Viewer v1.1 (aka EbookDroid)


PDF Viewer v1.1 is the same as EbookDroid. This used to be an open source project but has become closed source. They may do licenses but I have no clue. If it ever becomes open source again or if they provide an API for use in other applications, it would be great since this viewer is blazing fast, reliable, very popular on the market, and could be embedded into your app.

Since it’s closed, I’m not going to discuss it more.

GitHub: https://github.com/mortenpi/ebookdroid

Quoppa Android PDF Toolkit


I do not know much about the functionality, useability, extensiveness, or much else about this product because I abandoned all notion of using this API after receiving the following response to my inquiry about pricing:

When the app produces revenue, then we use a royalty based license, the license is set at 8% of any revenue that is produced by the app, with a minimum of $3000 per year.  Royalties include free upgrades as well as technical support, there is no other fees.

I think this is nonsense, no matter their product, when considering the fact that a venture capitalist has to invest $15,000 for that percentage of a start-up. For this reason, and given the other great options on the list (MuPDF and PlugPDF) I hope nobody buys into this product!

VuDroid


VuDroid loads a PDF pages in rectangular sections and rather slowly. It was too slow for my taste, especially given the other viewers, and so I have no more info on it.

GitHub Repo: https://github.com/xiedantibu/vudroid

Android-pdfview


I found this while looking for VuDroid and It seems to be based on VuDroid. According to its website, it’s a “fast pdf reader component for Android” with animations, gestures, and zoom. I tried importing into Eclipse but ran into many problems. First of all, it requires actionbarSherlock for the example. Secondly, it requires the VuDroid library. Finally, it was built using Maven which has some commands that aren’t recognized in my Eclipse since I don’t have Maven plugins installed. Finally, there was no .apk for me to download just to review the speed and functionality. For these reasons, I stopped trying and have no further information.

Site: http://joanzapata.com/android-pdfview/

GitHub Repo: https://github.com/JoanZapata/android-pdfview

WebView: Google Docs Reader


This is almost the same approach used in “Intent: Google Docs Reader,” except that it doesn’t redirect the user away from your application to a web browser. Instead, your application is creates a webView and acts like a web browser in order to display the Google Docs Viewer webpage inside your app.

Cost:

  • Free

Pros:

  • Really easy to implement
  • It’s free
  • Online PDF can be viewed inside your app
  • Pinch zoom automatic and works well
  • PDFs are always loaded correctly

Cons:

  • PDF cannot be loaded from device
  • Google Docs Viewer theme will likely conflict with your app’s custom theme
  • Panning the document is jerky
  • No control over viewer’s buttons
  • Must have internet to view PDF

Features:

  • Display online PDF using a web browser while connected to internet
  • Next/Previous page
  • Zoom in/out using button or pinch

Usage:


AndroidManifest.xml




    
    
    

    
        
            
                

                
            
        
    



MainActivity.java

package com.pdf_webview_googdocspreviewer;
import android.app.Activity;
import android.os.Bundle;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.webkit.WebSettings.PluginState;

public class MainActivity extends Activity {
   
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        WebView mWebView=new WebView(MainActivity.this);
        
        //Tell app to load webpage in app
        mWebView.setWebViewClient(new WebViewClient());
        
        //Use webview's built-in pinch and zoom
        mWebView.getSettings().setBuiltInZoomControls(true);
        
        //Makes webview more viewable...i.e. without this it seems
        //like android loads the webpage at too large a scaling
        mWebView.getSettings().setLoadWithOverviewMode(true);
        mWebView.getSettings().setUseWideViewPort(true);
        
        //Google docs viewere requires this
        mWebView.getSettings().setJavaScriptEnabled(true);
        mWebView.getSettings().setPluginState(PluginState.ON);
        
        //Load the page into the webview
        mWebView.loadUrl("http://www.metafuture.org/pdf/futureofindonesia.pdf");
        
        //Set the app's main view to the webView that displays the pdf
        setContentView(mWebView);
    }
}

Android-Pdf-Viewer-Library


I tried on two devices 4.0 and 4.3 and is not good. Load takes forever and usually doesn’t work. When it works the next/previous page works inconsistently. Functionality when a page does load the responsiveness is poor.

Site: http://andpdf.sourceforge.net/

GitHub: https://github.com/jblough/Android-Pdf-Viewer-Library

Cost:

  • Free

Pros:

  • Really easy to implement
  • It’s free

Cons:

  • It just doesn’t work for me
  • Your activity must extend PdfViewActivity rather than using a PdfView – sure, some re-coding may provide that capability but it’s not worth it based on the speed

Features:

  • Displays PDF(supposedly)
  • Next/Previous page

Usage:

  1. Clone the repo from GitHub
  2. Import the cloned repo library into Eclipse
  3. Create a new project in Eclipse and add the library to the new project
  4. Copy and paste the MainActivity.java code from below into your MainActivity.java file in the new project.
  5. Create PdfViewerActivity.java in the same package as MainActivity.java and copy the following code into it.
PdfViewerActivity.java

package com.pdfviewer_usingactivity;

public class PdfViewerActivity extends net.sf.andpdf.pdfviewer.PdfViewerActivity {
     public int getPreviousPageImageResource() { return R.drawable.left_arrow; }
     public int getNextPageImageResource() { return R.drawable.right_arrow; }
     public int getZoomInImageResource() { return R.drawable.zoom_in; }
     public int getZoomOutImageResource() { return R.drawable.zoom_out; }
     public int getPdfPasswordLayoutResource() { return R.layout.pdf_file_password; }
     public int getPdfPageNumberResource() { return R.layout.dialog_pagenumber; }
     public int getPdfPasswordEditField() { return R.id.etPassword; }
     public int getPdfPasswordOkButton() { return R.id.btOK; }
     public int getPdfPasswordExitButton() { return R.id.btExit; }
     public int getPdfPageNumberEditField() { return R.id.pagenum_edit; }

}
MainActivity.java

package com.pdfviewer_usingactivity;

import java.io.File;
import java.io.FilenameFilter;

import android.app.ListActivity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class MainActivity extends ListActivity {

    String[] pdflist;
    File[] imagelist;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //setContentView(R.layout.main);

        File images = Environment.getExternalStorageDirectory();
        imagelist = images.listFiles(new FilenameFilter() {
            public boolean accept(File dir, String name) {
                return ((name.endsWith(".pdf")));
            }
        });
        pdflist = new String[imagelist.length];
        for (int i = 0; i < imagelist.length; i++) {
            pdflist[i] = imagelist[i].getName();
        }
        this.setListAdapter(new ArrayAdapter(this,
                android.R.layout.simple_list_item_1, pdflist));
    }

    protected void onListItemClick(ListView l, View v, int position, long id) {
        super.onListItemClick(l, v, position, id);
        String path = imagelist[(int) id].getAbsolutePath();
        openPdfIntent(path);
    }

    private void openPdfIntent(String path) {
        try {
            final Intent intent = new Intent(this, PdfViewerActivity.class);
            intent.putExtra(PdfViewerActivity.EXTRA_PDFFILENAME, path);
            startActivity(intent);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

PlugPDF


Simply put, if you have the money and don’t have the time or patience for MuPDF, buy this! It’s fast and has great functionality. The demos can be downloaded from the link below and are truly simple to install.

My main quarrel is that the out-of-the box API requires that your app extend PlugPdf’s activity. It would be preferable to have a view that displays the pdf since we are trying to incorporate the functionality inside our own app. I asked if it were possible to use a view rather than Activity and hear was the response is below. In short, it’s possible but you’ll have to do a little more work.

Plug-and-play solutions requires your Activity to extend You can refer SimpleDocumentReader source code. SimpleDocumentReader is a basic viewer class for user convenience. Actually it accesses to a PDF file through a ReaderView instance. As the source code of simpleDocumentReader is open to you, you can freely modify and use it to add ReaderView function to your own View. For controls UI, please refer SimpleDocumentReader.java::onLoadFinish.

My second quarrel is that they claim it’s free for independent developers and personal use. This is not true. They allow you to download the example app for free and play around. But, there is a key that you must buy in order to use the library in your own app. This key is mapped to the package name of a single app.

This leads me to my final quarrel…purchase agreement is a little much. There are several API levels to buy starting at $699. You must buy this library for each app that you want to use it in, for each developer, and you must buy library updates after a year.

Ok, it may seem like I hate this product, but I don’t. I highly recommend it for groups that have the money and don’t have the time, or don’t want to hire a specialized pdf developer just for a short time. It’s worth the time and is a quality product and is certainly cheaper than hiring somebody or buying from one of their competitors.

Site: http://plugpdf.com/download/

Cost:

  • Starts at $699

Pros:

  • Really easy to implement
  • A business that supports the product when things don’t work
  • One time cost that beats its competitors and is less than hiring your own specialized developer

Cons:

  • Too expensive for single developers who are making their first app
  • Your activity must extend PdfViewActivity rather than using a PdfView

Features:

The simple demo:

  • Loads PDF from Http (assumed based on demo name)
  • Loads PDF really slowly (maybe it’s because the pdf is very heavy in images and being downloaded from online?)
  • PDF updates well after downloaded
  • PDF scrolls from left to right, fits page to screen width, and snaps page to screen center
  • No other features shown-if this is all that’s provided in the lowest cost then it’s not much

The Premium Demo:

  • Loads pdf quickly
  • Draw with grey pen and save
  • Draw rectangles,ovals, line and save
  • Add note symbol->hit edit->add header and text
  • Long-click to select text-works pretty well but it would be nice to see different handles. Drag two circular handles to make selection. When selected prompt allows copy to clipboard, highlight texts, underline, strikeout, squiggly(like a mispelled word)
  • Pinch zoom in/out works pretty well though a little jerky (not terrible)
  • Pan/fling when zoomend in
  • Thumbnail scrollview at bottom that lets you select a page and go to it
  • Search for text works well
  • Available Memory is also displayed (nice for development)

Usage:

  1. Download library from website
  2. Import library into Eclipse
  3. Import PDFHttpDemo(simple demo) into Eclipse and link to the library
  4. Import PDFReaderDemo(premium demo) into Eclipse and link to the library
  5. Create a new project in Eclipse and add the library to the new project
  6. Run both projects and poke around

MuPdf


This is the best solution for developers who 1)have no money – or don’t want to pay 2)can open source their code 3)have the time and patience to follow the instructions below. It is the best solution out there, period. It is very fast, always displays PDFs correctly, is feature rich, and is free if you can open source your code. It provides a PDF view that can be placed in any layout rather than having to extend an Activity – which is my biggest turnoff from any API. The only downside is that it does take half a day to install all the pre-reqs just to get the example app running – which is actually the same MuPDF Reader that is on the Android Market.

If you have Windows then follow the procedure below and you will get this running in the end. I know because I had not installed anything on my brand new computer and ran into pretty much every possible bug and resolved it – hopefully.

Site: www.mupdf.com/docs/how-to-build-mupdf-for-android

GitHub: https://github.com/muennich/mupdf

Cost:

  • Free

Pros:

  • Display pdf in your app using a view
  • Blazing fast
  • Always loads PDF correctly
  • Feature rich

Cons:

  • Takes a lot of time to install all the required components
  • The license means your project must be open source or pay for a license-no clue how much it would be

Features:

  • Text Selection: Works really well with single column but not with multiple columns. If multiple columns then text of all columns is selected if those columns have text at same vertical position on screen (maybe a bug?)
  • Navigate to a specified page
  • Search for text
  • Pinch zoom works well

Installation Instructions :

Set-up an Android Build Environment

  1. Downlaod and install the Android SDK
  2. Run the Android tool to install the platform tools
  3. Add the tools and platform-tools directories inside the SDK directory to your PATH
  4. Download and install the Android NDK (THIS IS DIFFERENT than SDK)
  5. Install a Java JDK (THIS IS DIFFERENT than JRE)
  6. Install ANT
  7. Install GIT (http://msysgit.github.io/) then Tortoise GIT(https://code.google.com/p/tortoisegit/wiki/Download)
  8. Install CYGWIN (https://www.cygwin.com/install.html) with everything marked for Development, Debug, and X11. This will take hours, but I don’t know which individual packages are used and this is the best way to guarantee all commands will be available that are needed.

Prepare the source

1. Open C:\

2. Right-click -> Git Bash (if you don’t see the option, GIT and/or TortoiseGit aren’t installed). In the Git Bash window, clone the main project by typing the following:

$ git clone git://git.ghostscript.com/mupdf.git

3. Update the third party submodules by typing the following:

$ cd C:\mupdf\

$ git submodule update –init

4. Populate the generated directory with the necessary files by opening a CYGWIN terminal and running the following commands:

$ cd “/cygdrive/c/mupdf/”

$ make generate

NOTES:

  • Error: make command does not exist or is not recognized. Potential causes: was typed into windows terminal or GIT Bash terminal instead of CYGWIN terminal. If it was typed into CYGWIN terminal then the make package was not installed so open the CYGWIN installed and install every package in Dev,Debug,X11 and try again
  • cygdrive is the “virtual Linux drive” for cygwin and /cygdrive/c/ represents C:/
  • Use parentheses around the entire filepath just in case there are spaces in the folder or file name

Build and Debug

1.Create a copy of the properties file by running the following commands in the CYGWIN prompt:

$ cd “/cygdrive/c/mupdf/platform/android”

$ cp local.properties.sample local.properties

2. Open local.properties from C:/mupdf/platform/android in a text editor of your choice (I use Notepad++)

3. Remove the # in the following line and save:

#sdk.dir=C:\\Program Files (x86)\\Android\\android-sdk

NOTE: This assumes your Android SDK is located at C:\Program Files (x86)\Android\android-sdk If it is located at a different path then use that path but replace \ by \\

 4. Build the native code libraries by running the following command in the CYGWIN prompt (still in c/mupdf/platform/android):

$ cd “/cygdrive/c/program files (x86)/ndk/”

$ cd ndk-build

NOTE: ndk command not found

  •  This assumes your NDK is located at the stated filepath
  • Likely this is because you have installed the SDK, the package you’ve been using to code in Android. So, install the NDK

5. Build the java application by calling the following commands in CYGWIN prompt:

$ cd “/cygdrive/c/mupdf/platform/android”

$ ant debug

Install on Device

  1. Add at least one pdf to the downloads folder on the sdCard
  2. Import MuPDF into Eclipse.
  3. Run the Android Application on your device
Helpful? Then DOWNLOAD and RATE my app!

Helpful? Then DOWNLOAD and RATE my app!

Advertisements

Android “R cannot be resolved to a variable”

Helpful? Then DOWNLOAD and RATE my app!

Helpful? Then DOWNLOAD and RATE my app!

Seeing “R cannot be resolved to a variable,” is one of the most annoying and recurring  problems when developing in Android. Below are the problems I’ve run into and their solutions.

No problems; everything in working order:


 

Image

Let’s start with a working project (picture above). Notice the following:

  • src/package name is com.example.project
  • gen/package name is EXACTLY the same
  • MainActivity is in src/com.example.project
  • While src and gen are different folders, they have the same packages and any files within the same package can see any other file in that package without having to import the class. Consequently, MainActivity can automatically see R.java and can therefor call R.id.container without errors.

 

Problem 1: Bad path single package


 

Image

The image above shows the result of a bad path from MainActivity to R.java. Notice the following:

  • red x on Project Folder, src folder, com.app.project package, and MainActivity.java in the package explorer on the left
  • no red x on any folders or files in the gen folder.
  • Clearly this means the root of the problem is in MainActivity and not with R.java
  • Looking at MainActivity on right side, the R. is underlined in red for any reference to R.java (e.g. R.layout.activity_main and R.id.container)
  • MainActivity is in com.app.project package while R.java is in com.example package, so it cannot automatically see R.java. Since it cannot automatically see R.java it must provide the path to R.java but hasn’t done so using import.

Solution 1:

The first solution is to rename one of the packages to that of the other. When I run into this problem it’s because I renamed my main package and forgot to rename the package in /gen. So, rename /gen/com.example.project by opening the manifest file as shown below. This should automatically rename the package in the package explorer. If it doesn’t, just delete the entire /gen folder and let android recreate it.

Image

Solution 2:

When you don’t want to rename the package in /gen (Problem 2 is a good example), then it’s required that MainActivity has the following line: import com.example.project.R;

Image

 

Problem 2: Bad path multi-package


 

Image

The image above shows the result of a bad path from SecondaryActivity to R.java even though MainActivity isn’t experiencing the same problem. Notice the following:

  • red x on Project Folder, src folder, com.app.project.secondaryActivity package, and SecondaryActivity.java in the package explorer on the left
  • no red x on any folders or files in the gen folder.
  • Clearly this means the root of the problem is in SecondaryActivity and not with R.java
  • Looking at SecondaryActivity on right side, the R. is underlined in red for any reference to R.java (e.g. R.layout.activity_main and R.id.container)
  • SecondaryActivity is in com.app.project.secondaryActivity package while MainActivity and R.java are in com.app.project package, so it cannot automatically see R.java. Since it cannot automatically see R.java it must provide the path to R.java but hasn’t done so using import.

Solution:

Use Solution 2 from Problem 1.

 

Problem 3: Wrong path specified… android.R


 

Broke Project 3

The image above shows the result of android.R being imported rather than com.app.project.R Notice the following:

  • red x on Project Folder, src folder, com.app.project package, and  in the package explorer on the left
  • no red x on any folders or files in the gen folder.
  • Clearly this means the root of the problem is in MainActivity and not with R.java
  • Looking at MainActivity on right side, the R. is NOT underlined while activity_main and container are
  • MainActivity is in com.app.project package and so is R.java, so no need to import anything since MainActivity can already see R.java
  • Problem is that the code thinks R.layout.activity_main and R.id.container should be in android.R and not com.app.R because of import android.R

Solution:

Delete import android.R

Note:

When using auto-complete (e.g. hitting spacebar during R.layout.cont to get R.layout.container),  unexpected suggestions appear. This is a result of importing android.R so delete it and the correct suggestions should appear again.

Problem 4: No R.java doesn’t exist after cleaning


 

First ensure that the problem isn’t a path issue as described above. If all paths are correct then try to select Project Tab->Clean ->Name of project.

If /Gen/com.app.project/R.java does not immediately reappear then an xml file or manifest file have an error – even if Eclipse doesn’t show it! So, go through recently changed files and make sure everything stacks up.  Here are some common problems:

  • Didn’t close a view. Every view needs to start and close. For example or
  • Missing quotes. Very common the second quote gets deleted and results in something like
  • Bad drawable names or xml file names. Both MUST be lowercase, number, and no symbols except underscore

 

Problem 5: R.java shows after cleaning but won’t update


Again, ensure there isn’t a path problem. Then, if a clean regenerates R.java but won’t update it.  Very likely the name of a value or enum is not allowed and must be fixed.  Look at the R.java file and see what fields have errors and look for un-allowed characters. For example, maybe there is a dash instead of an underscore.

 

Well, that’s the end of my experience with this problem. Hopefully one of these solutions helped. Let me know if you’ve seen another case and have a solution.

 

Helpful? Then DOWNLOAD and RATE my app!

Helpful? Then DOWNLOAD and RATE my app!

Handlers and threads

Helpful? Then DOWNLOAD and RATE my app!

Helpful? Then DOWNLOAD and RATE my app!

I keep having to relearn the handler and thread concept.  Here are some notes for a future blog:

  • Create a Handler on the main thread; call it, for example, messageHandler
  • Subclass the Thread class and pass a Handler into the constructor; save the handle (e.g. messageHandler) in the thread.
  • When the thread needs to pass information to the main thread it simply passes a message to the main thread using  the handle to the Handler (e.g. messageHandler.post(…something here…));
  • A thread is still an object and a handle to it can be stored.  This is useful because the thread may need to be stopped at times when the configuration changes – since android does not handle the java threads.
  • Since handles of threads can be stored individually, so can List.
  • While List is allowed, it’s not the same as accessing a List of objects from threads.  List is not thread safe!!!
  • Again, List is not thread safe!!! So, don’t try to change data in one List from multiple threads.
  • Supposedly, Collections.synchronizedList() allows multiple threads to touch a list in a safe way but i’ve not investigated
  • synchronized before a method makes it thread safe…i.e. only one thread can access it at a time
Helpful? Then DOWNLOAD and RATE my app!

Helpful? Then DOWNLOAD and RATE my app!

Debugging Android Project DDMS Heap Dump in Eclipse

Helpful? Then DOWNLOAD and RATE my app!

Helpful? Then DOWNLOAD and RATE my app!

First off, what is a heap dump? A heap dump is essentially a snapshot of an application’s data at a given point in time.  It maps a specific process, view, etc. to the memory being used.  Sort of like ctl-alt-delete on windows in order to determine what’s using up your app’s memory.

To get a heap dump in Eclipse for an application running on your device:

  1. Open Eclipse
  2. Run the target application on the target device by pushing the application to the device over USB (then keep USB connected).
  3. Select Window->Open Perspective->DDMS
  4. The target device should be shown on the left side in the devices window.
  5. The target application should be shown under the device
  6. Select the target application and then the Dump HPROF file icon(half-full glass with green fluid and red arrow). This will prompt you to save the file; do so.

Convert Android HPROF to readable HPROF

  1. The previous file cannot yet be read by the Eclipse MAT tool (see below) and so must be converted first.
  2. On your computer go to C:\…\android-sdks\tools (where … is wherever you installed eclipse) and copy the hprof-conv.exe file
  3. Navigate to the folder where you saved the heap dump and paste the hprof-conv.exe file (you can probably keep it in its original location and navigate to files, but I’m lazy).
  4. Open a command prompt and navigate to the folder where your file and the hprof-conv.exe file are located (can do using cd:\folderName).
  5. Type the following line into the command prompt and hit enter:

hprof-conv dump.hprof converted-dump.hprof

Your newly converted file will be created in the same folder as the original file and will be called converted-dump.hprof.

Opening HPROF in Eclipse after conversion:

  1. Go to Window->Open Perspective->Other->Memory Analysis
  2. This may take a while to open
  3. When it opens, it will show up amoung the coding windows-at least mine did-and so find it using the window icon that looks like a disk structure
  4. From here, you will be at the home screen of MAT with your app’s dump file.  Use any of the following links as reference on how to analyze things:

NOTE: READ THIS…I was trying to open the converted file in Eclipse since I had the MAT plug-in installed and everything went well.  But, that was only because I recorded the HPROF before installing the MAT plug-in for Eclipse.  After I installed that plug-in, DDMS stopped asking me where to store my file and what to name it.  This became very frustrating since I couldn’t get dump files, but I noticed that randomly numbered tabs were showing up in the java perspective and had the MAT disk icons.  Well…blam! Those were the dumps and already converted for me.  Also, if I hit the phone icon in DDMS it will do a screen capture dump showing me layout views and images on screen! Awesome!!!!

Helpful? Then DOWNLOAD and RATE my app!

Helpful? Then DOWNLOAD and RATE my app!

Creating a new Android project in Eclipse (hello world)

Helpful? Then DOWNLOAD and RATE my app!

Helpful? Then DOWNLOAD and RATE my app!

Before starting this tutorial, you should have read, understood, and successfully completed the tutorials listed below.  These tutorials are the building blocks for this tutorial and are listed in order from basic building blocks to compound ideas.

  1. Installing Eclipse-TODO
  2. Updating Eclipse-TODO
  3. Importing Libraries into Eclipse-TODO
  4. Linking libraries to projects in eclipse-TODO

Having completed these tutorials, you can now move on to creating a new Android project that will simply display “hello world!” on the device screen.

To do this, follow the procedure below:

1. Open Eclipse and let it load workspace.

2. Click File->New->Android Application Project

NewAndroidProject

3. Enter the application, project, and package name as shown in the image below.

NewAndroidProject2

4. Configure the project as shown below.

NewAndroidProject3

5. Configure the attributes of the icons as shown below.

NewAndroidProject4

6. Create a blank activity as shown below.

NewAndroidProject5

7. Create the main layout for the activity as shown below and select “Finish”.

NewAndroidProject6

8. The application will be created and the main xml layout file will automatically be displayed as shown in the image below.

NewAndroidProject7

9. To run this application on your device right-click on the Example_helloWorld folder in the Package Explorer window on the left hand of the screen.  Then select Run As->Android Application Project as shown below.

NewAndroidProject8

10. If your device is connected, it will be shown in the Android Device Chooser window.  Select your device and select “OK”.  Eclipse will compile the code into an Android Package file (.apk) and transfer it to your device.

NewAndroidProject9

11. Your device’s screen should be white and say “Hello world!”.

That’s it! Your first Android application is completed.

Helpful? Then DOWNLOAD and RATE my app!

Helpful? Then DOWNLOAD and RATE my app!