Correct, one application can not inject key events into another
application.  There should be no way around this.

For instrumentation test cases that cross application boundaries, I strongly
recommend you set up an ActivityMonitor to block the launching of that other
application's activity, returning a mocked result instead.

On Fri, Nov 21, 2008 at 3:34 PM, dreamerBoy <[EMAIL PROTECTED]> wrote:

>
> Hi Hackbod -
>
> I tried this using Instrumentation -
>
> The goal of this little program is to make an outgoing call and then
> generate a keypress on the ENDCALL button.
>
> 1. It appears that I am incapable of unlocking the keyguard:
>
> 11-21 14:40:58.445: INFO/InstTest(209): after
> inKeyguardRestrictedInputMode() ? true
>
> 2. Then, Android tells me I don't have permission to send a key event:
>
> 11-21 14:41:00.173: WARN/WindowManager(53): Permission denied:
> injecting key event from pid 209 uid 10019 to window Window{43506808
> com.android.phone/com.android.phone.InCallScreen} owned by uid 1001
>
> EmptyActivity is just as it sounds - no additional code other than
> what Eclipse generates.
>
>
> If anyone can see something that is not being done correctly, I would
> very much appreciate their thoughts -
>
> Thanks -
>
> Paul
>
> ~~~~~~~~~~
>
> package test.instTest;
>
> import android.app.Activity;
> import android.content.Context;
> import android.content.Intent;
> import android.net.Uri;
> import android.telephony.PhoneStateListener;
> import android.telephony.TelephonyManager;
> import android.test.ActivityInstrumentationTestCase;
> import android.util.Log;
> import android.view.KeyEvent;
> import android.app.Instrumentation;
> import android.view.View;
> import android.content.IntentFilter;
> import android.app.Instrumentation.ActivityResult;
> import android.app.KeyguardManager;
>
> public class InstTest extends
> ActivityInstrumentationTestCase<EmptyActivity>
> {
>   private static final String LOG_TAG    = "InstTest";
>   private TelephonyManager    telMgr;
>   private Instrumentation     instrumentation;
>   private Context             context;
>   private KeyguardManager     keyguardMgr;
>
>   public InstTest()
>   {
>      super("test.instTest", EmptyActivity.class);
>   }
>
>   public void testPreconditions()
>   {
>      instrumentation = getInstrumentation();
>      assertTrue("Instrumentation must be non-null", instrumentation !
> = null);
>      context = instrumentation.getContext();
>      assertTrue("Context must be non-null", context != null);
>      telMgr = (TelephonyManager) context.getSystemService
> (Context.TELEPHONY_SERVICE);
>      assertTrue("TelephonyManager must be non-null", telMgr != null);
>      keyguardMgr = (KeyguardManager) context.getSystemService
> (Context.KEYGUARD_SERVICE);
>      assertTrue("KeyguardManager must be non-null", keyguardMgr !=
> null);
>   }
>
>   public void testCall()
>   {
>      testPreconditions();
>
>      Log.i(LOG_TAG, "before inKeyguardRestrictedInputMode() ? " +
> keyguardMgr.inKeyguardRestrictedInputMode());
>
>      KeyguardManager.KeyguardLock keyguardLock =
> keyguardMgr.newKeyguardLock(LOG_TAG);
>      keyguardLock.disableKeyguard();
>
>      Log.i(LOG_TAG, "after inKeyguardRestrictedInputMode() ? " +
> keyguardMgr.inKeyguardRestrictedInputMode());
>
>      IntentFilter intentFilter = new IntentFilter
> (Intent.ACTION_CALL);
>
>      Uri parsedPhoneNumber = Uri.parse("tel:1234567");
>
>      Intent myIntent = new Intent(Intent.ACTION_CALL,
> parsedPhoneNumber);
>      Intent resultData = new Intent(Intent.ACTION_CALL,
> parsedPhoneNumber);
>      // myIntent = new Intent(Intent.ACTION_DIAL, parsedPhoneNumber);
>
>      myIntent.setFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION |
> Intent.FLAG_FROM_BACKGROUND
>            | Intent.FLAG_ACTIVITY_SINGLE_TOP |
> Intent.FLAG_ACTIVITY_NEW_TASK);
>      resultData.setFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION |
> Intent.FLAG_FROM_BACKGROUND
>            | Intent.FLAG_ACTIVITY_SINGLE_TOP |
> Intent.FLAG_ACTIVITY_NEW_TASK);
>
>      Instrumentation.ActivityResult actResult = new
> Instrumentation.ActivityResult(Activity.RESULT_OK, resultData);
>
>      Instrumentation.ActivityMonitor actMonitor = new
> Instrumentation.ActivityMonitor(intentFilter, actResult, false);
>
>      Log.i(LOG_TAG, "starting call.");
>
>      instrumentation.waitForIdleSync();
>
>      context.startActivity(myIntent);
>
>      instrumentation.waitForIdleSync();
>
>      Log.i(LOG_TAG, "number of hits from ActivityMonitor: " +
> actMonitor.getHits());
>      Activity phoneActivity = actMonitor.getLastActivity();
>      if (phoneActivity != null)
>         Log.i(LOG_TAG, "phoneActivity is NOT NULL!!");
>      else
>         Log.i(LOG_TAG, "phoneActivity is NULL");
>
>      Log.i(LOG_TAG, "before phone state is " + phoneStateToString());
>
>      Activity activity = getActivity();
>      Log.i(LOG_TAG, "activity class is " + activity.getClass());
>
>      View view = getActivity().getCurrentFocus();
>      if (view == null)
>         Log.i(LOG_TAG, "Focus view is NULL");
>      else
>         Log.i(LOG_TAG, "Focus view is NOT NULL");
>
>      Log.i(LOG_TAG, "Sending ENDCALL");
>      sendKeys(KeyEvent.KEYCODE_ENDCALL);
>
>      instrumentation.waitForIdleSync();
>      Log.i(LOG_TAG, "Sent ENDCALL, sleeping");
>
>      sleep(1000);
>
>      Log.i(LOG_TAG, "after phone state is " + phoneStateToString());
>   }
> }
>
> <?xml version="1.0" encoding="utf-8"?>
> <manifest xmlns:android="http://schemas.android.com/apk/res/android";
>        package="test.instTest" android:versionCode="1"
> android:versionName="1.0.0">
>        <application android:icon="@drawable/icon" android:label="@string/
> app_name">
>                <uses-library android:name="android.test.runner" />
>                <activity android:name=".EmptyActivity"
> android:label="@string/
> app_name">
>                        <intent-filter>
>                                <action
> android:name="android.intent.action.MAIN" />
>                                <category
> android:name="android.intent.category.LAUNCHER" />
>                        </intent-filter>
>                </activity>
>        </application>
>        <instrumentation
> android:name="android.test.InstrumentationTestRunner"
>                android:targetPackage="test.instTest" android:label="first
> phone key
> test" />
>        <uses-permission
> android:name="android.permission.CALL_PHONE"></uses-
> permission>
>        <uses-permission
> android:name="android.permission.READ_PHONE_STATE"></
> uses-permission>
>        <uses-permission
> android:name="android.permission.DISABLE_KEYGUARD"></
> uses-permission>
> </manifest>
>
>
> >adb shell am instrument -w -e class test.instTest.InstTest#testCall
> test.instTest/android.test.InstrumentationTestRunner
>
> test.instTest.InstTest:.
> Test results for InstTest=.
> Time: 3.368
>
> OK (1 test)
>
>
>
> On Nov 13, 4:37 pm, hackbod <[EMAIL PROTECTED]> wrote:
> > Fwiw, there has never been a public API to inject a key event, except
> > for the official API is on the Instrumentation class (which still
> > exists).  As far as I know we don't right now have an API to get an
> > Instrumentation object when not running an instrumentation test,
> > though.
> >
> > I am a little confused about what you are asking -- you say that you
> > want to send an ENDCALL to end a call, but that this is inside of the
> > same application?  I believe that if your app currently has focus, the
> > system will process that end call, though this is really not by
> > design, but is probably not a big deal (we decide whether it is okay
> > based on which window has focus so will be receiving the event...  but
> > end call is special since it is intercepted by the system and never
> > delivered to the focused window).  But if the user is in the in-call
> > screen, then that has focus, and you can't inject a key event since
> > you don't have focus.
> >
> > On Nov 13, 4:13 pm,dreamerBoy<[EMAIL PROTECTED]> wrote:
> >
> > > I'm building a test application and I have to be able to hang up a
> > > call in an automated fashion.
> >
> > > It occurred to me that I might be able to inject a key event:
> >
> > >       KeyEvent keyEvent = new KeyEvent(KeyEvent.ACTION_DOWN,
> > > KeyEvent.KEYCODE_ENDCALL );
> >
> > > into the event queue somehow.
> >
> > > Apparently the last incarnation of the  API had an injectKeyEvent()
> > > method in WindowManager but that's been stripped out.
> >
> > > Anyone know how to do it in 1.0?
> >
> > > Thanks much.
> >
> > > dreamer
> >
> >
> >
>


-- 
Dianne Hackborn
Android framework engineer
[EMAIL PROTECTED]

Note: please don't send private questions to me, as I don't have time to
provide private support.  All such questions should be posted on public
forums, where I and others can see and answer them.

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to