Am also facing the same problem, can tell me wheather you got the
solution for the problem or not?
On Nov 22 2008, 5:23 am, "Dianne Hackborn" <hack...@android.com>
wrote:
> 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 <paul.hube...@gmail.com> 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 <hack...@gmail.com> 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<paul.hube...@gmail.com> 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
> hack...@android.com
>
> 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.
Service lifecycle--服务组件的生命周期
A service can be used in two ways--翻译:服务组件有两种使用方式:
* It can be started and allowed to run until someone stops it or it stops itself. In this mode, it's started by calling Context.startService() and stopped by calling Context.stopService(). It can stop itself by calling Service.stopSelf() or Service.stopSelfResult(). Only one stopService() call is needed to stop the service, no matter how many times startService() was called.
翻译:第一种方式:服务被启动后一直将运行到被终止或是服务自行终止。这时候服务是被Context.startService()方法启动的,服务的终止是被Context.stopService()方法的执行被终止的,服务自行终止是通过执行Service.stopSelf() 或 Service.stopSelfResult()方法的。无论服务组件实例的startService()方法被执行了几次,只需执行 stopService()方法一次,服务就被终止。
* It can be operated programmatically using an interface that it defines and exports. Clients establish a connection to the Service object and use that connection to call into the service. The connection is established by calling Context.bindService(), and is closed by calling Context.unbindService(). Multiple clients can bind to the same service. If the service has not already been launched, bindService() can optionally launch it.
翻译:另一种方式是:借助接口。客户端代码创建一个针对服务对象的连接,然后使用该连接来调用服务。创建连接的方法是:Context.bindService()方法;终止服务可以调用的方法是Context.unbindService()。多个客户程序可以绑定到同一个服务上,如果被绑定的服务还没有启动,可以使用bindService()方法来启动服务。
The two modes are not entirely separate. You can bind to a service that was started with startService(). For example, a background music service could be started by calling startService() with an Intent object that identifies the music to play. Only later, possibly when the user wants to exercise some control over the player or get information about the current song, would an activity establish a connection to the service by calling bindService(). In cases like this, stopService() will not actually stop the service until the last binding is closed.
翻译:这两种方式不是说完全独立的,我们可以绑定已经用startService()方法启动的服务,例如:可以执行startService()方法启动后台音乐服务,在该方法的参数intent中指定了要播放的音乐。稍后,用户可能在播放器上做些操作或是想看到正在播放的音乐的一些相关信息,那么可以有一个activity来创建与后台音乐服务的连接(执行bindService()方法),这个场合下,调用stopService()方法实际上是不能终止该服务的,除非最后一个绑定被解除。
Like an activity, a service has lifecycle methods that you can implement to monitor changes in its state. But they are fewer than the activity methods — only three — and they are public, not protected:
翻译:和 activity 组件类似, service组件实例也有生命周期方法,可以被实现,但是只有三个方法,这三个方法都是public,不是protected方法:
void onCreate() void onStart(Intent intent) void onDestroy()
By implementing these methods, you can monitor two nested loops of the service's lifecycle:--翻译:实现这三个方法可以监听服务组件实例生命周期中的两个状态切换循环过程:
* The entire lifetime of a service happens between the time onCreate() is called and the time onDestroy() returns. Like an activity, a service does its initial setup in onCreate(), and releases all remaining resources in onDestroy(). For example, a music playback service could create the thread where the music will be played in onCreate(), and then stop the thread in onDestroy().
翻译:整个生命期起于onCreate() 方法被调用,结束于 onDestroy()方法被执行完成。这两个方法作用和activity的同名方法类似,一个执行初始化操作,一个执行资源释放操作。例如:音乐回放服务可以在 onCreate()方法中创建一个线程来执行音乐播放操作,之后, onDestroy()方法中终止该线程。
* The active lifetime of a service begins with a call to onStart(). This method is handed the Intent object that was passed to startService(). The music service would open the Intent to discover which music to play, and begin the playback.
翻译: 激活期起于onStart()方法被执行,该方法根据startService()方法的参数intent,做onStart相关的操作(音乐服务根据intent参数来查找要播放的音乐),然后执行回放。
There's no equivalent callback for when the service stops — no onStop() method.
翻译:要注意的是,服务终止的时候并没有对应的onStop()回调方法。
The onCreate() and onDestroy() methods are called for all services, whether they're started by Context.startService() or Context.bindService(). However, onStart() is called only for services started by startService().
翻译:无论服务组件实例是通过 Context.startService() 方法还是通过 Context.bindService()方法被启动的,系统都会调用到服务实例的 onCreate() 和 onDestroy() 方法。但是onStart()方法的调用只能针对由startService()启动的服务。
If a service permits others to bind to it, there are additional callback methods for it to implement:---翻译:如果某个服务允许被绑定,那么这个服务组件还有其他回调方法可以被实现:
IBinder onBind(Intent intent) boolean onUnbind(Intent intent) void onRebind(Intent intent)
The onBind() callback is passed the Intent object that was passed to bindService and onUnbind() is handed the intent that was passed to unbindService(). If the service permits the binding, onBind() returns the communications channel that clients use to interact with the service. The onUnbind() method can ask for onRebind() to be called if a new client connects to the service.
翻译:onBind() 回调方法的参数是一个intent对象,该对象实际上是通过 Context.bindService 方法传入的, onUnbind()方法的参数是Context.unbindService()方法传入的,如果服务允许绑定,那么,onBind() 返回的是客户端需要与该服务实例交互的通讯通道对象;当有新的客户需要和该服务连接的时候,可以通过 onUnbind() 方法来执行 onRebind() 方法,以完成重新绑定的操作。
The following diagram illustrates the callback methods for a service. Although, it separates services that are created via startService from those created by bindService(), keep in mind that any service, no matter how it's started, can potentially allow clients to bind to it, so any service may receive onBind() and onUnbind() calls.
翻译:下面用两个图说明了服务的回调方法,虽然这里我们是分别基于两种启动服务的方式(Context.startService()、Context.bindService())来做说明的,但是要时刻记住:服务组件往往都是允许被绑定,所以即使一个服务组件实例是被Context.startService方法启动的,这个服务组件实例实际上是有onBind() 、 onUnbind()回调方法。
引自http://www.chinasvg.com/svg/about-svg/svg-chinese-garbled-steps-and-methods.html
好多SVG编
辑器都有不能正常支持中文,后来自己手工创建SVG文件,却也不能在浏览器插件里正常显示。还以为是插件问题(如adobe svg
viewer和corel svg
viewer等),象我用inkscape,就能很好的处理中文,但却不能在浏览器里正常显示!不知为什么,还真以为插件问题。查看svg
viewer的技术规范,都说是支持utf-8的,那是什么问题呢?难道是文字编码问题,后来几经测试,用各种编码及encoding头,还是不对劲。
后来我好不容易总算琢磨出问题所在,原来你必须给中文加上中文字体。看来adbobe svg viewer和corel svg
viewer缺省都没有带支持某种中文字体的,不象inkscape,能正常显示中文。因此,在这种情况下,给中文加上某种字体的样式,就可以正常显示而
不是一些框框了,包括从W3C来的一些SVG中文幻灯片,给它加上中文某中字体的样式才行!
以上两段引用了eureka 的blog文章,他说得没错,造成SVG的中文乱码问题,主要是由于在SVG中对中文字体的定义有误造成的。那怎样才能彻底解决SVG中文乱码问题呢?下面是解决SVG中文乱码的步骤及方法:
1 首先要将SVG文件保存成UTF-8的编码格式。
操作:UltraEdit file->convisions->ASCII to UTF-8
2 要在svgviewer中显示中文字体,需要将中文字体名称进行“国际化”,
即将汉字字体名称改为英文名称,如将“宋体”改为“Simsun",“黑体”改为"Simhei"等,下面是部分字体对照列表:
English NameLocalized Name SimSun 宋体 SimHei 黑体 FangSong_GB2312 仿宋_GB2312 KaiTi_GB2312 楷体_GB2312 YouYuan
幼圆 STSong 华文宋体 STZhongsong 华文中宋 STKaiti 华文楷体 STFangsong 华文仿宋 STXihei 华文细黑 STLiti 华文隶书 STXingkai 华文行楷 STXinwei 华文新魏 STHupo 华文琥珀 STCaiyun 华文彩云 FZYaoTi 方正姚体简体 FZShuTi 方正舒体简体 LiSu 隶书
3 SVG文件应该像下面这种格式编写:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg width="400" height="400"
xmlns="http://www.w3.org/2000/svg">
<desc>sdfasdf</desc>
<rect x="1" y="1" width="350" height="350"
fill="none" stroke="blue" />
<text font-size="30" font-family="SimSun" x="100" y="100" width="200" height="30">
显示的是中文
</text>
</svg>
4 你还应该特别注意上面示例中的第一行代码
<?xml version="1.0" encoding="UTF-8"?>
这行代码是说这个SVG文件是UTF-8编码来定义的。
如果是Illustrator中制作的SVG怎样解决编码问题?那可以参见"怎样对Illustrator制作的SVG进行优化" ,文章介绍了Illustrator保存SVG时,我们对保存的选项进行调节,来控制SVG的编码、字体类型、字体子集、是否压缩格式以及生成适用于不同设备(如手机)的SVG文件。
(THE END)