0

There is a BookView.class that has a private method defined as below

  public class BookView{
    private boolean importBook(String epubBookPath){
    //The function that adds books to database.
    }
  }

I am trying to call this function from a different package. My code is

    protected void onPostExecute(String file_url) {
        // dismiss the dialog after the file was downloaded
        dismissDialog(progress_bar_type);

        /*Now we add the book information to the sqlite file.*/
        TextView textView=(TextView)findViewById(R.id.textView1);
        String filename = textView.getText().toString();
        String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath();
        String epubBookPath = baseDir+filename;
        Log.i("epubBookPath:",epubBookPath); //No errors till here!

        try {
            Method m=BookView.class.getDeclaredMethod("importBook");
            m.setAccessible(true);//Abracadabra 
            //I need help from here! How do i pass the epubBookPath to the private importBook method.
        } catch (NoSuchMethodException e) {

            e.printStackTrace();
        }
        Intent in = new Intent(getApplicationContext(),
                CallEPubUIActivity.class);        
        startActivity(in);
    }

EDIT:

I found another public method in the jar file which is doing the above work.

  public void jsImportBook(String epubBookPath) {
     if (!BookView.this.importBook(epubBookPath))
     return;
   BookView.this.createBookshelf();
  }
Bhavyanshu
  • 536
  • 7
  • 25
  • Private methods are private for a reason, so no one outside of the class calls them. You're not going to be able to do this unless you maybe try using reflection and even then I'm not sure it will work. – cmbaxter May 21 '13 at 13:53
  • 1
    Reflection is the way to go, but nobody actually recommends it: http://stackoverflow.com/questions/880365/any-way-to-invoke-a-private-method – andreih May 21 '13 at 13:54
  • Read the [Invoking Methods](http://docs.oracle.com/javase/tutorial/reflect/member/methodInvocation.html) secion of the [Oracle Reflection Trail](http://docs.oracle.com/javase/tutorial/reflect/index.html). – Anthony Accioly May 21 '13 at 14:01
  • @cmbaxter I would make it public but it is a class of a jar file. I have got it using the java decompiler. I cannot edit it. – Bhavyanshu May 21 '13 at 14:03

4 Answers4

11

If you want to do that you should make it public or make a public wrapper method it.

If thats not possible, you can work your way around it, but thats ugly and bad and you should have really good reasons to do so.

public boolean importBook(String epubBookPath){
    //The function that adds books to database.
}

or

public boolean importBookPublic(String epubBookPath){
    return importBook(epubBookPath);
}
private boolean importBook(String epubBookPath){
    //The function that adds books to database.
}

Also note that if you CAN'T access the method directly in a third-party library than it is most likely INTENDED that way. Take a look at the call hierarchy of the private method and see if you find a public method that does the call to the private one and that also does what you need.

Libraries are often designed in a way that a public method does some checking (all Parameters given, authenticated etc.) and then pass the call to the private method to do the actual work. You almost never want to work around that process.

Community
  • 1
  • 1
Angelo Fuchs
  • 9,825
  • 1
  • 35
  • 72
  • dont you think you need to specify return for importBook(epubBookPath) inside of public method. – Alpesh Gediya May 21 '13 at 13:58
  • @AngeloNeuschitzer I would make it public but it is a class of a jar file. I have got to it using the java decompiler. I cannot edit it. Is there a way i can edit it? Thanks for the quick response. – Bhavyanshu May 21 '13 at 14:07
  • @Bhavyanshu Most likely there is a intended way to achieve that result and the method is `private` by design. As long as you don't know why its private, you should not work your way around this. Have a look at the call hierarchy and have a look from where that method gets called, then decide if one of the `public` methods that do call that private one are capable of performing your task for you. Then use them. If that fails, have a look at where the jar comes from and if the original code is somewhere (or you can contact the original creator). Them let them fix it. Reflection is last resort. – Angelo Fuchs May 21 '13 at 14:13
  • 1
    @AngeloNeuschitzer Okay as you just said, there is a public function being called from a javascript file. Check the edit in the question. – Bhavyanshu May 21 '13 at 14:22
9

With reflection, you'll need an instance of BookView to invoke the method with (unless it's a static method).

BookView yourInstance = new BookView();
Method m = BookView.class.getDeclaredMethod("importBook");
m.setAccessible(true);//Abracadabra 
Boolean result = (Boolean) m.invoke(yourInstance, "A Path"); // pass your epubBookPath parameter (in this example it is "A Path"

The method you are looking for is Method#invoke(Object, Object...)

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
2

Use reflection to get you method and set Accessible as true, then invoke the method using BookView Object instance and required parameters(path string) using statement as below:

     Boolean result = (Boolean)method.invoke(bookObject, epubBookPath);

Sample code as below:

Method method = BookView.getDeclaredMethod("importBook");
method.setAccessible(true);
Boolean result = (Boolean)method.invoke(bookObject, epubBookPath);
Yogendra Singh
  • 33,927
  • 6
  • 63
  • 73
0

Private methods cannot be accessed outside the class it is defined. Make it Public.