我在nexus 7 2013上运行我的应用程序,在logcat中我注意到一些日志运行了两次。在写了几个日志后,我得出结论,每个活动都在平板电脑上运行两次。奇怪的是,手机(LG G3或三星galaxy s4 mini)日志只打印一次。
在做了一些研究后,我尝试添加android:launchMode="singleTop"
或singleTask
或singleInstance
,但都没有效果。此外,我在旗帜活动中有一些意图:intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
和2 AsyncTasks
。
是否存在意图或异步导致问题的方法?
清单:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.marian.digimusicstream" >
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!--
To retrieve OAuth 2.0 tokens or invalidate tokens to disconnect a user. This disconnect
option is required to comply with the Google+ Sign-In developer policies
-->
<uses-permission android:name="android.permission.USE_CREDENTIALS" /> <!-- To retrieve the account name (email) as part of sign-in: -->
<uses-permission android:name="android.permission.GET_ACCOUNTS" /> <!-- To auto-complete the email text field in the login form with the user's emails -->
<uses-permission android:name="android.permission.READ_PROFILE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<permission android:name="android.permission.MEDIA_CONTENT_CONTROL" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppBaseTheme">
<activity
android:name=".LoginActivity"
android:label="@string/app_name"
android:theme="@android:style/Theme.Light.NoTitleBar"
android:windowSoftInputMode="stateHidden"
android:launchMode="singleTop">
<!-- <intent-filter> -->
<!-- <action android:name="android.intent.action.MAIN" /> -->
<!-- <category android:name="android.intent.category.LAUNCHER" /> -->
<!-- </intent-filter> -->
</activity>
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<activity
android:name=".musicPlayer"
android:label="@string/title_activity_music_player">
<!-- android:theme="@android:style/Theme.DeviceDefault.Light.DarkActionBar" -->
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".PlayerService" />
<service android:name=".audioService" />
<receiver android:name=".PlayPauseReceiver" />
<receiver android:name=".NetworkChangeReceiver" >
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
<receiver android:name=".musicPlayer$MusicNoisyReceiver" >
<intent-filter>
<action android:name="android.media.AUDIO_BECOMING_NOISY" />
</intent-filter>
</receiver>
<activity
android:name=".singleMusicScreen"
android:label="@string/title_activity_single_music_screen" >
</activity>
</application>
</manifest>
的活动:
public class musicPlayer extends DrawerActivity {
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_music_player);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
mainLayout = (RelativeLayout) findViewById(R.id.mainLayout);
pullToRefresh = (PullRefreshLayout) findViewById(R.id.pullToReresh);
musicListLayout = new RelativeLayout(getApplicationContext());
progressBar = new ProgressBar(getApplicationContext());
pref = getApplicationContext().getSharedPreferences("MyPref", MODE_PRIVATE);
editor = pref.edit();
getUser = pref.getString("sharedUser", "");
getPassword = pref.getString("sharedPass", "");
new doLogin().execute();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_music_player, menu);
return true;
}
@Override
public void onBackPressed() {
// Do Here what ever you want do on back press;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
public boolean isFirstItemCompletelyVisible() {
return mLayoutManager.findFirstCompletelyVisibleItemPosition() == 0;
}
@Override
public void onResume() {
super.onResume();
musicList.post(new Runnable() {
@Override
public void run() {
pullToRefresh.setEnabled(isFirstItemCompletelyVisible());
}
});
}
private class doLogin extends AsyncTask<Void, Void, Boolean> {
@Override
protected void onPreExecute() {
Intent myIntent = getIntent();
boolean button = myIntent.getBooleanExtra("LoginButton", false);
if (!pref.getBoolean("isCheckBoxChecked", false) && !button) {
Intent intent = new Intent(musicPlayer.this, LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplicationContext().startActivity(intent);
finish();
cancel(true);
}
if (button) {
getUser = myIntent.getStringExtra("userLogin");
getPassword = myIntent.getStringExtra("passLogin");
}
Log.i("TEST", "User: " + getUser + " pass: " + getPassword);
}
@Override
protected Boolean doInBackground(Void... params) {
try {
Log.i("TEST", "Init");
api = DefaultClientFactory.create(host, getUser, getPassword);
Log.i("TEST", "" + api.getUserInfo());
return true;
} catch (StorageApiException e) {
e.printStackTrace();
return false;
}
}
@Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
if (!result) {
Intent intent = new Intent(musicPlayer.this, LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplicationContext().startActivity(intent);
Toast.makeText(getApplicationContext(), "Invalid E-mail or Password !", Toast.LENGTH_SHORT).show();
} else {
// new backgroundTask().execute();
}
}
}
}
答案 0 :(得分:0)
活动启动模式。
机器人:launchMode =&#34; singleTop&#34;
如果活动实例存在于任务堆栈之上,则不会创建新实例,系统将通过onNewIntent()路由您的意图信息。如果它不在顶部,则将创建一个新实例。可以创建多个实例,每个实例可能属于不同的任务。(Good post on activity launch mode)
为什么要检查onPreExecute()中的共享pref然后取消它。更好的方法是在检查后执行asynctask。
取消(true)并不保证它会在调用后立即停止异步任务。如果取消,则根据需要返回结果,更好的方法是在doInBackground()中添加 isCancelled()检查。这将有助于最早完成asynctask而不执行那里写的任务。
在清单中,您可能希望添加android:conifgChanges以更好地处理方向。
android:configChanges = [&#34; mcc&#34;,&#34; mnc&#34;,&#34; locale&#34;, &#34;触摸屏&#34;,&#34;键盘&#34;,&#34; keyboardHidden&#34;, &#34;导航&#34;,&#34; screenLayout&#34;,&#34; fontScale&#34;, &#34; uiMode&#34;,&#34; orientation&#34;,&#34; screenSize&#34;, &#34; smallestScreenSize&#34]
希望这有帮助!
答案 1 :(得分:0)
这似乎很愚蠢,但是请仔细检查您是否没有两次记录日志。我以为我的MainActivity的两个实例在同一时间运行,无论我尝试了什么。然后我意识到我已经种了两棵杰克·沃顿的“木材调试”树,并且记录了两次所有内容。