我从广播接收器中启动一个活动,但为什么我的另一个活动也在启动?

4
在我的应用程序中,有一个 MainActivity 和一个 AlarmActivityMainActivity 用于设置闹钟。 AlarmActivity 用于显示闹钟。在中间,我有一个实现了 BroadcastReceiver 的类,用于接收在 MainActivity 中预定的待处理意图。我遇到的问题有两个。
1)当我只期望从下面看到的 onReceive 方法创建 AlarmActivity 时,MainActivity 却被创建了。
2)当 AlarmActivity 被创建时,它随后就被销毁了。请参见下面的日志。
请注意,这仅在我关闭屏幕时发生。如果我销毁 MainActivity 并保持屏幕开启直到闹钟响起,一切都很好。如果让 MainActivity 存活并保持屏幕开启,则会在 MainActivity 的上方显示 AlarmActivity,如预期所示。否则,如果屏幕关闭... AlarmActivity 会出现一瞬间,然后消失,我会在屏幕上看到 MainActivity。是什么原因呢?
以下是我设置闹钟的位置。请注意,callingContext 变量是来自我的 MainActivity 类的上下文。
 Intent intentAlarm = new Intent(this.callingContext, AlarmActivity.class);

        //Get the Alarm Service
        AlarmManager alarmManager = (AlarmManager) callingContext.getSystemService(Context.ALARM_SERVICE);

     //user our intent and give it a time to broadcast at
          alarmManager.set(AlarmManager.RTC_WAKEUP,alarmTime, PendingIntent.getBroadcast(this.callingContext, 1, intentAlarm, PendingIntent.FLAG_CANCEL_CURRENT));


public class AlarmReceiver extends BroadcastReceiver { 

    final String TAG=this.toString();

    @Override
    public void onReceive(Context arg0, Intent arg1) {
        Log.i(TAG,"onReceive");

        //start a new activity, an alarm has gone off

        //See that I've tried using the application context, but this did not help.
        //Context context=arg0.getApplicationContext();
        Intent intent=new Intent(arg0,AlarmActivity.class);

        //This flag is required for starting an activity outside of an activity.
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        intent.putExtra("ACTIVITY_STARTED_FROM_BROADCAST_RECEIVER",true);
        arg0.startActivity(intent);
    }
}

Alarm Activity生命周期方法。

protected void onCreate(Bundle savedInstanceState) {
        Log.i(TAG,"onCreate");
        if(savedInstanceState==null) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.layout_alarm);


        }
    }

    public static void acquireScreenCpuWakeLock(Context context) {
        if (sCpuWakeLock != null) {
            return;
        }
        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        sCpuWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK
                | PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.ON_AFTER_RELEASE, "TYLER");
        sCpuWakeLock.acquire();
    }

    public static void releaseCpuLock() {
        if (sCpuWakeLock != null) {
            sCpuWakeLock.release();
            sCpuWakeLock = null;
        }
    }
    @Override
    protected void onResume() {
        Log.i(TAG,"onResume");
        super.onResume();

    //  getFragmentManager().beginTransaction().add(R.id.alarm_frame, new AlarmFragment()).commit();
    }

    @Override
    protected void onStart() {
        Log.i(TAG,"onStart");
        super.onStart();
        final Window win = getWindow();
        win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
                WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
                WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON |
                WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON |
                WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON);
        acquireScreenCpuWakeLock(this);
        alarmFragment=new AlarmFragment();
        alarmFragment.setArguments(getIntent().getExtras());
        getFragmentManager().beginTransaction().add(R.id.alarm_frame, alarmFragment).commit();

    }

    @Override
    protected void onPause(){
        Log.i(TAG,"onPause");
        super.onPause();
        releaseCpuLock();
        getFragmentManager().beginTransaction().remove(alarmFragment);
        Log.d("pfaff","wakelock released, alarm activity paused");

    }

   @Override
    protected  void onDestroy(){
       Log.i(TAG,"onDestroy");
       super.onDestroy();
     //  wakeLock.release();
        Log.d("pfaff","alarm activity destroyed");
   }

}

闹钟碎片的生命周期方法。

  @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        return inflater.inflate(R.layout.fragment_alarm, container, false);
    }

    @Override
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
    }

    @Override
    public void onAttach(Activity activity){
        Log.i(TAG,"onAttach");
        super.onAttach(activity);
        this.activity=activity;//camera

    }
    @Override
    public void onStart() {
        Log.i(TAG, "onStart");
        super.onStart();
    }

    @Override
    public void onResume() {
       Log.i(TAG,"onResume");
        super.onResume();
        final AlarmFragment thisFragment = this;
}

@Override
    public void onPause() {
        Log.i(this.toString(),"onPause");
        super.onPause();
        getActivity().onBackPressed();

    }


    @Override
    public void onDestroy() {
        // TODO Auto-generated method stub
        Log.i(this.toString(),"onDestroy");

        super.onDestroy();
       // tearDownMedia();
        scanMyMedia();
        releaseCameraAndPreview();
        if(timeReceiverIsRegistered) {
            getActivity().unregisterReceiver(_broadcastReceiver);
        }
    }


以下是日志记录(logcat):

   11-27 21:56:46.036  29370-29370/com.example.videoalarmt I/com.example.videoalarmt.AlarmReceiver@41eb2158﹕ onReceive
    11-27 21:56:46.066  29370-29370/com.example.videoalarmt I/com.example.videoalarmt.MainActivity@41eaaf08﹕ onCreate
    11-27 21:56:46.066  29370-29370/com.example.videoalarmt I/timePickerFragment{41ea1e58}﹕ onCreateView
    11-27 21:56:46.096  29370-29370/com.example.videoalarmt E/TextView﹕ Saved cursor position 2/2 out of range for (restored) text
    11-27 21:56:46.096  29370-29370/com.example.videoalarmt E/TextView﹕ Saved cursor position 2/2 out of range for (restored) text
    11-27 21:56:46.136  29370-29370/com.example.videoalarmt I/com.example.videoalarmt.AlarmActivity@41ed7bf8﹕ onCreate
    11-27 21:56:46.136  29370-29370/com.example.videoalarmt I/com.example.videoalarmt.AlarmActivity@41ed7bf8﹕ onStart
    11-27 21:56:46.136  29370-29370/com.example.videoalarmt I/com.example.videoalarmt.AlarmActivity@41ed7bf8﹕ onResume
    11-27 21:56:46.136  29370-29370/com.example.videoalarmt I/AlarmFragment{41edaa40}﹕ onAttach
    11-27 21:56:46.136  29370-29370/com.example.videoalarmt I/AlarmFragment{41edaa40}﹕ onViewCreated
    11-27 21:56:46.136  29370-29370/com.example.videoalarmt I/AlarmFragment{41edaa40}﹕ onStart
    11-27 21:56:46.136  29370-29370/com.example.videoalarmt I/AlarmFragment{41edaa40}﹕ onResume
    11-27 21:56:46.136  29370-29370/com.example.videoalarmt I/AlarmFragment{41edaa40}﹕ was started from broadcast receiver
    11-27 21:56:46.206  29370-29370/com.example.videoalarmt I/AlarmFragment{41edaa40 #0 id=0x7f0a0024}﹕ onPause
    11-27 21:56:46.206  29370-29370/com.example.videoalarmt I/com.example.videoalarmt.AlarmActivity@41ed7bf8﹕ onPause
    11-27 21:56:46.787  29370-29370/com.example.videoalarmt I/AlarmFragment{41edaa40 #0 id=0x7f0a0024}﹕ Putting media recorder in PREPARED state from DATASOURCECONFIGURED state
    11-27 21:56:46.787  29370-29370/com.example.videoalarmt I/MediaRecorderJNI﹕ prepare: surface=0x76608e58
    11-27 21:56:47.137  29370-29370/com.example.videoalarmt E/MediaPlayer﹕ Should have subtitle controller already set
    11-27 21:56:47.137  29370-29370/com.example.videoalarmt I/Choreographer﹕ Skipped 53 frames!  The application may be doing too much work on its main thread.
    11-27 21:56:47.237  29370-29370/com.example.videoalarmt I/com.example.videoalarmt.AlarmActivity@41ed7bf8﹕ onStop
    11-27 21:56:47.598  29370-29370/com.example.videoalarmt I/AlarmFragment{41edaa40 #0 id=0x7f0a0024}﹕ onDestroy
    11-27 21:56:47.598  29370-29370/com.example.videoalarmt I/com.example.videoalarmt.AlarmActivity@41ed7bf8﹕ onDestroy
    11-27 21:56:47.658  29370-29370/com.example.videoalarmt W/IInputConnectionWrapper﹕ showStatusIcon on inactive InputConnection
    11-27 21:57:02.243  29370-29370/com.example.videoalarmt I/com.example.videoalarmt.MainActivity@41eaaf08﹕ onDestroy


这是我的清单

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.videoalarmt"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="15"
        android:targetSdkVersion="21" />
    <uses-permission android:name="com.android.alarm.permission.SET_ALARM"/>
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

<uses-feature android:name="android.hardware.camera" android:required="true" />
<uses-feature android:name="android.hardware.camera.front" android:required="true" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@android:style/Theme.Holo.Light.NoActionBar"
        >

        <meta-data android:name="com.google.android.gms.version"
           android:value="@integer/google_play_services_version" />

           <receiver android:name="com.example.videoalarmt.AlarmReceiver"/>
        <activity
            android:name="com.example.videoalarmt.MainActivity"
            android:label="@string/app_name" 
            android:screenOrientation="portrait"
            >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

        </activity>
          <activity
            android:name="com.example.videoalarmt.AlarmActivity"
            android:label="@string/app_name" 
            android:screenOrientation="portrait"
            >
        </activity>

            <activity android:name="com.google.android.gms.ads.AdActivity"
             android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"/>

    </application>



</manifest>

arg0.startActivity()中的arg0是一个Context而不是Intent。 - Shvet
1
startActivity是在Context对象上调用的方法,而不是Intent对象。对吗?http://developer.android.com/reference/android/content/Context.html#startActivity(android.content.Intent) - Tyler Pfaff
1
Intent intent = new Intent(sourceActivity.this, DestinationActivity.class); startActivity(intent); - Shvet
1
这不是这样工作的,我的朋友。startActivity() 是从一个 Context 中调用的,并传入了一个 Intent。 - Tyler Pfaff
@TylerPfaff 请看下面的回答。你不应该在Fragment的onPause中调用getActivity().onBackPressed() - Jared Rummler
显示剩余13条评论
6个回答

2

没有理由创建MainActivity。我在您的代码中发现的唯一问题是以下行中:

Intent intentAlarm = new Intent(this.callingContext, AlarmActivity.class);

您正在使用Activity类创建一个意图,但在待定意图中使用了getBroadCast()方法。应该是:

Intent intentAlarm = new Intent(this.callingContext, AlarmReceiver.class);

我没有尝试过你的代码,但这可能是你问题的原因。请进行以下更改并检查是否仍在创建Mainactivity?


1
从查看您的代码和日志,我认为您的问题是在片段中调用了 onBackPressed
11-27 21:56:46.206  29370-29370/com.example.videoalarmt I/AlarmFragment{41edaa40 #0 id=0x7f0a0024}﹕ onPause

您的AlarmFragment.onPause不应该调用getActivity().onBackPressed()。这很可能是导致您的活动关闭的原因。只需在AlarmFragment.onPause中删除该行代码,我认为您的问题将得到解决。

0
在BroadcastReceiver的onReceive()方法中,您不能执行超过10秒的操作。请参阅官方文档
当屏幕锁定时,CPU停止工作请参阅此处
因此,当屏幕锁定且CPU停止工作并且时间超过10秒时,您会收到此错误。
为了避免这个错误,您应该使用唤醒锁。使用此功能,您的应用程序可以在屏幕锁定时继续运行。
还要查看链接1链接2
我希望我的信息对您解决问题有所帮助。

0
intent intent = new Intent(context, WordService.class);  
context.startService(intent);

2
为了帮助他人,同时也包括简要说明代码如何解决问题会很有帮助。 - Leigh
WordService.class只是一个示例,您可以在此处放置自己想要通过广播接收器调用的类。 - wadali

0

根据您的描述,我理解您遇到了以下问题:当您打开主活动并设置闹钟后,在闹钟接收器接收到闹钟之前关闭屏幕。然后,当您再次打开屏幕时,您会看到闹钟活动闪烁并消失。

基于此,以下是解释:

由于它在后台运行,因此在屏幕关闭时接收器会接收到闹钟。正在发生的是接收器启动闹钟活动,由于屏幕关闭,闹钟活动被暂停并且闹钟片段将其关闭。但是,所有这些事件都会堆积,直到您解锁屏幕并看到它们全部发生。

您可以在屏幕打开后延迟启动闹钟活动。当闹钟接收器接收到信息时,请检查屏幕是否关闭,并将闹钟设置保存在SharedPreferances中。您可以设置广播接收器来检查屏幕的开关事件。在屏幕打开时,请检查您的共享首选项以获取延迟的闹钟,并在清除共享首选项后启动闹钟活动。

另一个解决方案是添加

<uses-permission android:name="android.permission.WAKE_LOCK" />

在您的清单中添加权限,并在接收器接收到信息时打开屏幕。在您的屏幕接收器中开始闹钟活动。

您还应该使用 getActivity().finish() 而不是 getActivity().onBackPressed() 关闭一个活动。


-1
无论何时按下锁定按钮,应用程序都会进入暂停模式。如果您希望您的应用程序执行某些操作(或继续执行某些操作),则需要在主活动的onPause()方法中处理此操作。

这不适用于我的情况。 - Tyler Pfaff

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接