当你说不行时,你应该说些什么:以Android播放midi为例
中国好几年前都对能对美国说"不",软件工程师也经常要对用户和同事说"不"。
但是别人经常还要在你说不以后继续喋喋不休,为什么呢?
据说男生说不的时候,就是不的意思;据说女生说不的时候,是请再继续表现的
意思。这坑害了很多易做图男。因为,只有她希望你继续表现的时候,那时"不"的
意思才是请继续表现,否则,"不"的意思就是"不"。一些女生假设对方能够理解
这一显然的事实:即,你是否是被欢迎继续表现的。
而这个世界上没有显然的事情。继续表现的,多是易做图男,被希望继续表现的,
通常很快就引退了。
关于如何说是,咱们今天不讨论;今天单讨论一下如何明确地说不。
会发生上述误会,盖因东方民族隐晦含蓄的表达方式传统。看过一个日本片子。
某个提了个什么主意,女主角坐在那里,低头着头,很坚毅地说:"虽说很好。"
你不要以为还有下文,她说到这里就戛然而止了。日本人就是这样说话的。她发
出的声音是"虽说很好",但实际想传达的是后面所有没说的内容。
在工程中,用户和同事也经常会误解。那么如何准确地传达"不"的信息呢?
1. 对用户
这个简单。
除了告诉他不以外,还要告诉他 技术上完全可以,但是...然后开始罗列代价:
时间(工期)、经费等等。
然后他就自动引退了。这在女生说不的场景中,类似于,女生说完不以后,再补
充,"其实呢,也不是不行,但是需要加些条件。我想要的很简单:一座大大的
露台,上面有个秋千……"
明确的回绝,就是 不行+ 你不具备"行"的理由。
2. 对同事
明确告诉同事,尤其是分配给你任务的那个人,"你的想法很猪头" 的方法是,
告诉他,他的想法不可行的原因。
并且,为了交流简洁起见,把他所有可能的提问,所有可能修正的主意都罗列出
来,然后一一否定。写文档或报告的时候,不要期待交互,不要期待他问你答,
用答案堵住他所有可能下嘴的地方。
不恃敌所不攻也,恃吾有以待也。
以下是一个实例故事。这也我们为什么要训练写实验报告的原因,它记录了过程
和数据,以此支持你的看法。没有人会像科幻电影里的总统啥的那样,因为你琼
瑶般喊"你们相信我吧,地球真的要毁灭啦"就相信你。
我们应该做的是:告诉小伙不行,然后对他淡定地笑笑,然后准确清晰完整地说
出他不行的原因。
背景:
我请牛同学做Android下的一个程序原理,播放音乐合弦,比如大三度。意思是,同
时把do,re,mi的声音发出来。
技术方案之一是用PCM混音,之二是在MIDI中同时播放这几个音。牛同学分别试
了。
牛同学试了一段时间以后,说终于找到一个生成midi文件的方法。
我提出新的要求,不要把midi文件写到文件系统(internal storage)中,而是
用java的stream,在内存(RAM)中直接发给MediaPlayer播放。
牛同学说:不行。
故事开始了。
你说不行,我当然不能因为是你说的,然后就信了。要有事实。
所以牛同学发来他的代码,我学习了一段,发现真的不行。然后写了下面这封信。
略有修改。
----信的正文由此开始----
下面提到的"应该"是指 建议给你的 报告的写法.有了这些你"应该"提供的资料,我才能了解你研究了哪些必要的方法.
这是用以证明你研究的路线是正确的方法.
或者换种说法,如果以下报告中的"应该"部分你已经告诉我,我就不必看你的代码了.
1. 你应该提供我MidiFile的出处,以便我参考,因为MidiFile不是你写的,且不是java/android的一部分;
2. 你是否参考了此邮件后面网址的实现?[http://kevinboone.net/javamidi.html]
3. 我提到的不必向文件系统中写出midi文件,
原计划的路线是这样的:
通过重写writeToFile 实现,把这个方法中的写到文件系统中转为对Stream赋值,也可以把midi的内容放在vector<byte>中;
4. 然后设置MediaPlayer.SetDataSource()的参数为这个vector或者Stream.
下面是我寻找解决方案的路线。
4.1 MediaPlayer需要FileDescriptor
[http://developer.android.com/reference/android/media/MediaPlayer.html#pubmethods]
MediaPlayer.setDataSource(FileDescriptor fd)
Sets the data source (FileDescriptor) to use.
4.2 FileDescriptor可以由FileInputStream/FileOutputStream建立
[http://developer.android.com/reference/java/io/FileDescriptor.html]
It's possible to get the file descriptor used by some classes (such as
FileInputStream, FileOutputStream, and RandomAccessFile), and then
create new streams that point to the same file descriptor.
[http://developer.android.com/reference/java/io/FileOutputStream.html]
FileInputStream.getFD()
public final FileDescriptor getFD ()
Returns the underlying file descriptor.
4.4 到这里,我的思路走不下去了。因为FileInputStream的构造函数要求存储在FLASH中的文件。
你应该列出以下方法,并说明MediaPlayer没有其他的方法setDataSource.
void setDataSource(String path)
Sets the data source (file-path or http/rtsp URL) to use.
void setDataSource(FileDescriptor fd, long offset, long length)
Sets the data source (FileDescriptor) to use.
void setDataSource(FileDescriptor fd)
Sets the data source (FileDescriptor) to use.
void setDataSource(Context context, Uri uri, Map<String, String> headers)
Sets the data source as a content Uri.
void setDataSource(Context context, Uri uri)
Sets the data source as a content Uri.
4.5 然后我开始查是否有其他的办法。因为利用stream而不通过文件系统,这实
在应该是个非常通用的方案,android sdk没有理由不支持啊。
[http://developer.android.com/reference/android/content/Context.html#getCacheDir()]讨论了这一问题,
播放内存中,而不是flash(internal storage)中的midi文件。
4.6 下面这个方法我同意[http://code.google.com/p/android/issues/detail?id=739]
: Comment 7 by steveold...@gmail.com, Aug 19, 2008
: From the ReadMe included with 0.9 SDK. www.zzzyk.com
:
: Unfortunately, the ability to play audio streams from memory (such as via an
: InputStream or Reader) will not be possible in Android 1.0. As a workaround, we
: recommend that developers save media content to SD card and use MediaPlayer to play
: from a file URI, or embed a small HTTP server and play from a URI on localhost (such
: as http://127.0.0.1:4242/something
杨注:但是第二天一早,我又意识到这是不行的。因为读http必然要求那个midi
文件已经存在了。这与我原计划不希望写入文件系统相违背。
同一贴子有人提到
补充:移动开发 , Android ,