我正在编写一个具有两个主要组件的 Android 应用程序:一个在启动时启动的服务,以及一个我只想在通过其图标手动启动它时启动的 GUI,而不是在设备启动时启动。我知道如何在启动时启动服务,但它也会在启动时启动 GUI,这是我不想要的。
我认为这与我的清单中的设置有关,但是尽管尝试了很多事情,但我还没有弄清楚如何防止 GUI 在启动时也启动。
我应该补充一点,我不会在启动时以编程方式启动 GUI。我确实在 GUI 的活动类中引用了静态公共变量,但我没有进行任何方法调用或向 GUI 的活动发送任何意图。
这是我的清单。我究竟做错了什么?非常感谢。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="my.package.name"
android:versionCode="0"
android:versionName="0.1.0">
<uses-sdk
android:minSdkVersion="11"
android:targetSdkVersion="17"/>
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.WRITE_SMS"/>
<uses-permission android:name="android.permission.SEND_SMS"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application android:icon="@drawable/icon"
android:label="@string/app_name"
android:allowBackup="true" >
<!-- XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
I want MainActivity to only start when I
select its icon, NOT at boot time. However,
it always starts up at boot.
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-->
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
MyBootReceiver properly starts up at boot time,
and it properly invokes MyBootService. At
the appropriate time, MyBootService invokes
RegisterActivity.
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-->
<activity android:name=".RegisterActivity"
android:label="@string/app_name">
</activity>
<receiver
android:name=".MyBootReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="my.package.name" />
</intent-filter>
</receiver>
<service android:name=".MyBootService" />
</application>
</manifest>
添加广播接收器类:
package my.package.name;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class MyBootReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Intent bootIntent = new Intent(context, MyBootService.class);
bootIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startService(bootIntent);
}
}
添加服务类...
package my.package.name;
import java.util.ArrayList;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AccountManagerCallback;
import android.accounts.AccountManagerFuture;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.telephony.TelephonyManager;
public class MyBootService extends Service {
private static final String GOOGLE_ACCOUNT_TYPE = "com.google";
private static final String GOOGLE_ACCOUNT_FEATURE = "service_ah";
private Context context = null;
@Override
public IBinder onBind(Intent intent) {
this.display("onBind");
return (null);
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
AccountManager am = AccountManager.get(this);
am.getAccountsByTypeAndFeatures(GOOGLE_ACCOUNT_TYPE, new String[]{GOOGLE_ACCOUNT_FEATURE},
new AccountManagerCallback<Account[]>() {
@Override
public void run(AccountManagerFuture<Account[]> acclist) {
MyBootService parent = MyBootService.this;
Intent regIntent = new Intent(parent.getApplicationContext(), RegisterActivity.class);
try {
ArrayList<String> accountNameList = new ArrayList<String>();
for (Account a: acclist.getResult()) {
accountNameList.add(a.name);
}
regIntent.putStringArrayListExtra("accountNames", accountNameList);
try {
TelephonyManager tmgr = (TelephonyManager) parent.getApplicationContext().getSystemService(Context.TELEPHONY_SERVICE);
String phoneNo = tmgr.getLine1Number();
regIntent.putExtra("phoneNumber", phoneNo);
}
catch (Throwable t) {
}
}
catch (Throwable t) {
// put error message here
}
regIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
parent.startActivity(regIntent);
}
}, null);
return (START_STICKY);
}
@Override
public void onDestroy() {
this.display("onDestroy");
super.onDestroy();
}
}
更多信息
我弄清楚了发生了什么。首先,我说我的 MainActivity 正在启动是错误的。经过更详细的调试,我发现它的onCreate()和onResume()方法没有被调用。但是,应用程序的视图出现了:显示应用程序名称和默认图标的黑屏。我最初把它误认为是全面启动的迹象。
当然,这引发了一个问题,即为什么该视图首先出现在启动时。我有一些关于此的信息,尽管我仍然对发生的事情感到困惑。我剥离了MyBootService 调用的 RegisterActivity 类的onCreate()方法。调用this.getIntent()时,应用程序的视图会在启动时显示。当this.getIntent()被注释掉时,应用程序的视图不会在启动时显示。
请注意,这是RegisterActivity 类的onCreate() ,而不是MainActivity。
你们有谁知道在调用this.getIntent()时可能导致应用程序视图出现的原因是什么?
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// If the following line is commented out, the
// application's view does not show up on boot;
// if the following line is not commented out,
// the application's view shows up.
Intent intent = this.getIntent();
}