Accessing external apps with parameters

JDS

Active Member
Licensed User
Longtime User
I already found the following:

B4X:
Dim In As Intent
Dim pm As PackageManager
Dim uri as String
uri= "geo:" & latitude & "," & longitude '& "?q=" & latitude & "," & longitude
In.Initialize(In.ACTION_VIEW,uri)
If In.IsInitialized Then StartActivity(In)
StartActivity(In)

Google maps is started with the correct points.
But we don't want to use Google maps but an other program called PTV (or NavFree). With the following we can start the program PTV:

B4X:
Dim In As Intent
Dim pm As PackageManager
Dim uri as String
In = pm.GetApplicationIntent("com.ptvag.navigation.app")
If In.IsInitialized Then StartActivity(In)
StartActivity(In)

With Google Maps the trigger for the correct location is the code
B4X:
 In.Initialize(In.ACTION_VIEW,uri)

And then especially the string "uri". The intent-codes can be found on the website of google (Intents List: Invoking Google Applications on Android Devices | Android Developers)
Is there a way to retreive the intents from external apps?
 

JDS

Active Member
Licensed User
Longtime User
I've contacted the builder of the external app. They say that there must be used of a messenger service.
(a) Implement an Android ServiceConnection and the appropriate interfaces of
this connection and create a messenger based on the IBinder.
This messenger will be used to send messages to the navigator.
(b) Bind to the navigator service with bindService().
(c) Disconnection is done with unbind().
(d) Create a Messenger object and a Handler to receive messages from the navigator.

I can't find any information about the "Android ServiceConnection" or "IBinder" on the forum. Can anyone point me in the right direction?
 
Upvote 0

JDS

Active Member
Licensed User
Longtime User
Hi Erel,

I've created the following.

B4X:
package jds.ptv.ptvlibrary;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import anywheresoftware.b4a.BA.ShortName;

@ShortName("PTV2")

public class ptvlibrary extends Activity {
   
/**Code van Constants */
   
   static final int MSG_RI_ADD_STATION = 100;
   static final int MSG_RI_DELETE_ALL_STATIONS = 101;
   static final int MSG_RI_START_NAVIGATION = 300;
   
/**Code van BaseActivity */
   
   // The navigator service messenger, used to send data to the navigator
   private Messenger foreignService = null;
   
   // Flag indicating whether we have called bind on the service
   private boolean bound;

   private Messenger ourMessenger;

   @Override
   public void onCreate(Bundle savedInstanceState)
   {
      super.onCreate(savedInstanceState);
      setIncomingHandler(new IncomingHandler());
   }
   
   /** Create a Messenger to let the navigation application send us messages,
    *  will take the above created message handler for incoming messages. */
   //final Messenger ourMessenger = new Messenger(new IncomingHandler());
   
   public void setIncomingHandler(Handler handler) 
   {
      ourMessenger = new Messenger(handler);
   }
   
   /** Class for interacting with the main interface of the service. */
   protected ServiceConnection serviceConnection = new ServiceConnection()
   {
      public void onServiceConnected(ComponentName className, IBinder service)
      {
         // This is called when the connection with the service has been
         // established, giving us the object we can use to
         // interact with the service. We are communicating with the
         // service using a Messenger, so here we get a client-side
         // representation of that from the raw IBinder object.
         foreignService = new Messenger(service);
         bound = true;
      }

      public void onServiceDisconnected(ComponentName className)
      {
         // This is called when the connection with the service has been
         // unexpectedly disconnected -- that is, its process crashed.
         foreignService = null;
         bound = false;
      }
   };
   
   @Override
   protected void onStart() 
   {
      super.onStart();
      // bind to the navigator RI service. To do so, we have to create 
      // a new Intent with the class name set to the package name of the RI service
      Intent serviceIntent = new Intent();
      serviceIntent.setClassName("com.ptvag.navigation.app", "com.ptvag.navigation.ri.RIService");

      // and then bind to the service 
      boolean rc = getApplicationContext().bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE);
   }

   @Override
   protected void onStop() 
   {
      super.onStop();
      // unbind from the service
      if (bound) 
      {
         getApplicationContext().unbindService(serviceConnection);
         bound = false;
      }
   }
   
   public Messenger getForeignService() {
      return foreignService;
   }

   public boolean isBound() {
      return bound;
   }

   public Messenger getOurMessenger() {
      return ourMessenger;
   }
   
/**Code van StationsActivity */
   
   /** Message handler for incoming messages from the navigation application */
   class IncomingHandler extends Handler
   {
      @Override
      public void handleMessage(Message msg)
      {
         
      }
   }
   
   /** Called when the activity is first created. */
   /**@Override
   public void onCreate(Bundle savedInstanceState)
   {
      super.onCreate(savedInstanceState);
      /**setContentView(R.layout.stations);
         
      setIncomingHandler(new IncomingHandler());
      
   }*/
   
   public void addStation(String Name, double x, double y)
   {
      deleteAllStations();
      if (!isBound()) 
         return;

      // get a message from the message pool
      Message msg = Message.obtain(null, MSG_RI_ADD_STATION, 0, 0);
      // set the replyTo field to our messenger object, so the navigator can 
      // send us messages back
        msg.replyTo = getOurMessenger();
        // create a bundle and put the relevant values from the edit fields in it
        Bundle bundle = new Bundle();
        bundle.putString("Name", Name.toString());
        /**bundle.putString("Name", "TEST");*/   
      bundle.putDouble("GeoDezPosX", x);          
      bundle.putDouble("GeoDezPosY", y);
      // add the bundle to the message
        msg.setData(bundle);
        startNavigation();
   }
   
   /** Send a message to start a navigation */
   protected void startNavigation()
   {
      if (!isBound()) 
         return;
      
      Message msg = Message.obtain(null, MSG_RI_START_NAVIGATION, 0, 0);
      msg.replyTo = getOurMessenger();
      try 
      {
         getForeignService().send(msg);
      } catch (RemoteException e) 
      {
         e.printStackTrace();
      }      
   }
   
   /** Send a message to delete all stations */
   protected void deleteAllStations()
   {
      if (!isBound()) 
         return;
      
      Message msg = Message.obtain(null, MSG_RI_DELETE_ALL_STATIONS, 0, 0);
      msg.replyTo = getOurMessenger();
      try 
      {
         getForeignService().send(msg);
      } catch (RemoteException e) 
      {
         e.printStackTrace();
      }            
   }   
}

But I can't find the problem. From B4A I call the public void "AddStation" which purpose is to lauch the external application with a new point to navigate.
B4X:
latitude=52.139890
longitude=5.055460
f.addStation("Testlocatie",latitude,longitude)
The B4A-program doesn't generate faillures but it isn't starting the external app.
Am I missing something? Is there a way to debug a library? Just like debugging B4A with the command "Log()"?
 
Upvote 0
Top