跟着教程《Android Service(二) Service使用》开发了Android Service,但由于开发中存在两个特殊性:
1. 测试机使用的是安卓版本5.1的酷派大神Note3
2. 上述教程的Intent类是在MainActivity类的方法以外定义的
导致按照上述教程以及一系列指导如何在安卓5.0版本以上使用Intent类的教程的做法修改代码后总报错。仅仅按照上述教程呢只有一个核心错误:Service Intent must be explicit。在手机上表现为点击启动按钮以后服务应用闪退,服务不能成功启动。按照该错误检索出的教程说Intent类在安卓5.0以上版本必须显式声明,但是修改下来呢错误更多,就不一一列举了,主要是Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference。直接一启动应用就闪退,连应用界面都不能待了。
改来改去宝宝心里苦啊,为什么大家都说使用setAction(),setAction()这些方法,但我的语法提示没有这些方法(仅有4个无关语法,即FilterComparison、ShortcutIconResource、ClassLoaderCreator、Creator,这些都什么鬼?),而且写出来还给这些方法红字。
绝望的我最后无意发现在类方法中引用这些方法,喜出望外地发现语法提示居然弹出了Intent类本该有的丰富方法:
为什么别人都行我不行的原因终于找到了。接下来需要采取这些教程中比较好的代码修改方案,我最终采用了《Android用Intent启动Activity的方法》这篇教程中的第1种方法,即setClass方法+startService,非常简便,亲测有效。修改后的MainActivity.java代码如下
...
public class MainActivity extends AppCompatActivity {
Intent intent = new Intent();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//在这里调用Intent类的setClass()方法并开启Service
intent.setClass(this, MyService.class);
startService(intent);
findViewById(R.id.btn_start).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startService(intent);
}
});
findViewById(R.id.btn_stop).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
stopService(intent);
}
});
}
}
...
开发中还有一些坑需要记录一下:
1. 根据第一篇教程的代码,正确import所有的依赖包后,仍会发现R.id.btn_start和R.id.btn_stop处提示错误,那是因为我们没有在activity_main.xml中加入ID为这两者的按钮,到activity_main.xml那里拖两个按钮,改一下ID就好。
2. “所见不一定所得”。按钮不能仅仅拖动到预览界面就行,否则虽然在预览界面上看按钮在不同的位置,但启动APP以后会发现两个按钮都堆叠到了左上角,其中一个盖住了另外一个。我们至少应该在Component Tree中点居中(Center)一下,Android Studio会帮我们自动调整按钮在预览界面中的位置,估计必须要通过点Center在xml中添加一些代码,才能达到所见即所得的效果。
3. 老项目是扶不起的阿斗。刚开始开发的时候,想起以前有一个项目一直没动,打算拿旧项目开涮,结果Gradle构建项目构建来构建去,发现Java编译器遇到了很多已经弃用(obsolete)的方法,编译出了问题,不能生成APP,最后重新建了个新项目。这里也要感谢强大的Android Studio,提示我下载了所有最新的开发所需工具,让我在这方面没有走弯路。
总之,Java类还能因为在代码中的位置不同而有能否使用类方法的差异,这一点要引以为戒。
事后想想也是,在OOP中是在方法以外只能定义变量,不能调用任何方法,否则即使写了,因为没在程序的入口,所以不能执行。看来是我急于修补,忘记了OOP代码的执行原理 Orz