2013-05-06 46 views
5

Tôi đang viết một ứng dụng Android có hai thành phần chính: dịch vụ khởi động vào lúc khởi động và GUI mà tôi chỉ muốn khởi chạy khi khởi chạy thủ công thông qua biểu tượng của nó, không phải khi thiết bị khởi động. Tôi biết cách khởi động dịch vụ tại thời điểm khởi động, nhưng nó cũng khởi chạy GUI lúc khởi động mà tôi không muốn.Android: Khởi động dịch vụ lúc khởi động, nhưng không khởi chạy GUI

Tôi đoán rằng điều này có liên quan đến các cài đặt trong tệp kê khai của tôi, nhưng mặc dù đã thử một số thứ, tôi chưa tìm ra cách ngăn GUI cũng bắt đầu lúc khởi động.

Tôi nên thêm rằng tôi không khởi chạy GUI theo chương trình lúc khởi động. Tôi tham chiếu các biến công cộng tĩnh trong lớp hoạt động của GUI, nhưng tôi không thực hiện bất kỳ cuộc gọi phương thức nào hoặc gửi bất kỳ ý định nào đến hoạt động của GUI.

Đây là tệp kê khai của tôi. Tôi đang làm gì sai? Cảm ơn nhiều.

<?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> 

Thêm lớp broadcast receiver:

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); 
    } 
} 

Thêm lớp dịch vụ ... INFO

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(); 
    } 
} 

THÊM

tôi đã tìm ra một số những gì đang xảy ra. Trước hết, tôi đã nhầm lẫn khi nói rằng MainActivity của tôi đã bắt đầu. Khi gỡ lỗi chi tiết hơn, tôi thấy rằng các phương thức onCreate()onResume() không được gọi. Tuy nhiên, chế độ xem của ứng dụng đã hiển thị: màn hình màu đen có tên ứng dụng và biểu tượng mặc định. Ban đầu tôi nhầm tưởng rằng với một dấu hiệu của một khởi động đầy đủ.

Điều này, tất nhiên, đặt ra câu hỏi tại sao chế độ xem đó xuất hiện khi khởi động, ngay từ đầu. Tôi có một số thông tin về điều này, mặc dù tôi vẫn còn bối rối như những gì đang xảy ra. Tôi đã loại bỏ phương thức onCreate() của lớp RegisterActivity được gọi bởi MyBootService. Khi this.getIntent() được gọi, chế độ xem của ứng dụng sẽ hiển thị khi khởi động. Khi this.getIntent() được nhận xét, giao diện của ứng dụng không hiển thị khi khởi động.

Lưu ý rằng đây là onCreate() của lớp RegisterActivity, KHÔNG của MainActivity.

Bạn có biết điều gì có thể khiến cho lượt xem của ứng dụng hiển thị khi this.getIntent() được gọi không?

@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(); 
} 
+0

đăng mã nhận truyền phát của bạn. Bạn có chắc là bạn không tạo ý định cho hoạt động đó bên trong mã nhận của mình không? –

+0

'MyBootReceiver.onReceive()' làm gì? –

+0

Đã thêm lớp người nhận phát sóng. – NYCHippo

Trả lời

3

Tôi nghĩ rằng những gì bạn đang nhìn thấy là preview sử dụng hệ điều hành Android để làm cho khởi động ứng dụng dường như nhanh hơn. Bản xem trước này được tạo dựa trên chủ đề hoạt động của bạn.

Thử đặt chủ đề tùy chỉnh cho số RegisterActivity của bạn trông gần giống với kết quả cuối cùng hơn.Ví dụ, nếu hoạt động của bạn là một hộp thoại, tạo ra một chủ đề mở rộng Theme.Dialog hoặc Theme.Light.Dialog

Bạn có thể nhận được thêm thông tin về bài đăng blog từ Cyril Mottier: Android App Launching Made Gorgeous


EDIT: Thay đổi để thực sự câu trả lời câu hỏi

+0

Có, nhưng RegistrationActivity không phải là vấn đề. Đó là hoạt động khác, được gọi là MainActivity. Một số biến tĩnh công khai trong MainActivity được tham chiếu trong RegistrationActivity, nhưng không có phương thức MainActivity nào được gọi, cũng không gửi bất kỳ Intents nào đến MainActivity. – NYCHippo

+0

"MyBootReceiver khởi động đúng lúc khởi động, và nó đúng cách gọi MyBootService. Vào thời điểm thích hợp, MyBootService gọi RegisterActivity." Vấn đề của anh ta là ** MainActivity ** bắt đầu. –

+0

Cảm ơn bạn và câu trả lời của bạn đã cung cấp khóa. Xem "Câu trả lời thực tế" của tôi để giải thích cách tôi giải quyết vấn đề này. – NYCHippo

0

THE REAL, ĐÁP THỰC TẾ

Vì sự giúp đỡ và phản hồi tôi nhận được ở đây, cuối cùng tôi đã tìm ra được vấn đề của mình và giải quyết vấn đề:

Tôi đã sai khi sử dụng Hoạt động ngay từ đầu (lớp RegisterActivity) vì tôi không muốn chức năng mà ban đầu tôi đưa vào RegisterActivity để được kết hợp với GUI. Do thiếu kinh nghiệm với mô hình Android và thiếu tài liệu đọc đầy đủ, tôi đã không nhận ra Hoạt động luôn có chế độ xem được liên kết với nó.

Bây giờ tôi biết điều này, tôi đã tái cấu trúc ứng dụng của mình để tất cả chức năng trước đây trong RegisterActivity đã được chuyển sang MyBootService. Bây giờ, không có chế độ xem nào bật lên khi khởi động và ứng dụng của tôi thực hiện những gì tôi muốn.

Cảm ơn tất cả vì sự giúp đỡ và kiên nhẫn của bạn.

Các vấn đề liên quan