upload android base code part7

This commit is contained in:
August 2018-08-08 18:09:17 +08:00
parent 4e516ec6ed
commit 841ae54672
25229 changed files with 1709508 additions and 0 deletions

View file

@ -0,0 +1,86 @@
<?xml version="1.0" encoding="utf-8"?><!--
Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<manifest package="com.android.multiwindowplayground"
xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/MultiWindowSampleTheme">
<!-- The launcher Activity that is started when the application is first started.
Note that we are setting the task affinity to "" to ensure each activity is launched
into a separate task stack. -->
<activity
android:name="com.android.multiwindowplayground.MainActivity"
android:taskAffinity="">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- This Activity cannot be resized and is always displayed full screen. -->
<activity
android:name="com.android.multiwindowplayground.activities.UnresizableActivity"
android:resizeableActivity="false"
android:taskAffinity="" />
<!-- This Activity has a default size (750x500dp) with a minimum size
(500dp at its shortest side). It is launched in the top/end (top/right) corner by default.
These attributes are defined in the 'layout' tag within an Activity definition. -->
<activity
android:name="com.android.multiwindowplayground.activities.MinimumSizeActivity"
android:launchMode="singleInstance"
android:taskAffinity="">
<layout
android:defaultHeight="500dp"
android:defaultWidth="750dp"
android:gravity="top|end"
android:minWidth="500dp"
android:minHeight="500dp" />
</activity>
<!-- In split-screen mode, this Activity is launched adjacent to another Activity. This is
controlled via a flag set in the intent that launches this Activity. -->
<activity
android:name="com.android.multiwindowplayground.activities.AdjacentActivity"
android:taskAffinity="" />
<!-- This Activity is launched within an area defined in its launch intent. -->
<activity
android:name="com.android.multiwindowplayground.activities.LaunchBoundsActivity"
android:taskAffinity="" />
<!-- This activity handles all configuration changes itself.
Callbacks for configuration changes are received in 'onConfigurationChanged'. -->
<activity
android:name="com.android.multiwindowplayground.activities.CustomConfigurationChangeActivity"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
android:launchMode="singleInstance"
android:taskAffinity="" />
<!-- This Activity is launched in a new task without any special flags or settings. -->
<activity
android:name="com.android.multiwindowplayground.activities.BasicActivity"
android:launchMode="singleInstance"
android:taskAffinity="" />
</application>
</manifest>

View file

@ -0,0 +1,14 @@
page.tags="MultiWindowPlayground"
sample.group=Android N Preview
@jd:body
<p>
This sample demonstrates the use of the multi-window API available
in Android N. It shows the use of new Intent flags and
AndroidManifest properties to define the multi-window behavior.
Switch the sample app into multi-window mode to see how it affects
the lifecycle and behavior of the app.
</p>

View file

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?><!--
Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- This layout contains a TextView and a LogFragment that logs some text to the screen. -->
<LinearLayout android:id="@+id/layout"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:orientation="vertical">
<ScrollView
android:id="@+id/scrollview"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_gravity="top"
android:layout_weight="0.75">
<TextView
android:id="@+id/description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:textColor="@color/white" />
</ScrollView>
<include
layout="@layout/logging"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_gravity="bottom"
android:layout_weight="0.25" />
</LinearLayout>

View file

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="vertical"
android:background="@color/lightgray">
<ScrollView xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.75"
android:background="@color/white"
android:layout_gravity="top"
android:id="@+id/scrollview"
tools:context="com.android.multiwindowplayground.MainActivity">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/introduction_title"
android:textSize="30sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/warning_multiwindow_disabled"
android:visibility="gone"
tools:visibility="visible"
style="@style/TextWarning"
android:paddingTop="@dimen/content_vertical_dividing_padding"
android:paddingBottom="@dimen/content_vertical_dividing_padding"
android:text="Enable multi-window mode to see this sample in action!" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/description"
android:text="@string/sample_introduction" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/button_start_basic"
android:onClick="onStartBasicActivity"
android:text="@string/start_default" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/start_unresizable"
android:onClick="onStartUnresizableClick"
android:text="@string/start_unresizable" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/start_adjacent"
android:onClick="onStartAdjacentActivity"
android:text="@string/start_adjacent" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/start_customconfiguration"
android:onClick="onStartCustomConfigurationActivity"
android:text="@string/start_custom_activity" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="@dimen/content_vertical_dividing_padding"
android:text="@string/sample_freeform_introduction" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/start_minimumsize"
android:onClick="onStartMinimumSizeActivity"
android:text="@string/start_minimum" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/start_launchbounds"
android:onClick="onStartLaunchBoundsActivity"
android:text="@string/start_bounds" />
</LinearLayout>
</ScrollView>
<include
layout="@layout/logging"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_gravity="bottom"
android:layout_weight="0.25" />
</LinearLayout>

View file

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/log_fragment"
android:name="com.example.android.common.logger.LogFragment" />

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

View file

@ -0,0 +1,19 @@
<!--
Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<dimen name="activity_horizontal_margin">64dp</dimen>
</resources>

View file

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?><!--
Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<color name="colorPrimary">#3F51B5</color>
<color name="colorPrimaryDark">#303F9F</color>
<color name="colorAccent">#FF4081</color>
<color name="purple">#512DA8</color>
<color name="pink">#C2185B</color>
<color name="teal">#00695C</color>
<color name="lime">#9E9D24</color>
<color name="gray">#424242</color>
<color name="lightgray">#F5F5F5</color>
<color name="cyan">#00838F</color>
<color name="white">#FFFFFF</color>
</resources>

View file

@ -0,0 +1,22 @@
<!--
Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="content_vertical_dividing_padding">16dp</dimen>
</resources>

View file

@ -0,0 +1,66 @@
<!--
Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<string name="app_name">MultiWindow Playground</string>
<string name="introduction_title">Multiwindow Playground</string>
<string name="sample_introduction">This sample demonstrates the use of the multi-window API
available in Android N.\nFirst, switch this app into
<b>split-screen mode</b>
(for example by long-pressing the recents button). Each button below starts a new activity
with special flags.\n<b>See the files MainActivity.java and AndroidManifest.xml for
implementation details.</b>
</string>
<string name="sample_freeform_introduction">The buttons below demonstrate features only
available in <b>free-form multi-window mode</b>.</string>
<string name="start_default">Start basic, default Activity</string>
<string name="start_unresizable">Start unresizable Activity</string>
<string name="start_adjacent">Start Activity adjacent</string>
<string name="start_minimum">Start Activity with minimum size</string>
<string name="start_bounds">Start Activity with launch bounds</string>
<string name="start_custom_activity">Start activity that handles configuration changes.</string>
<string name="activity_description_basic">This Activity was launched in a new task without any
additional flags or options.
</string>
<string name="activity_description_unresizable">This activity is set as unresizable in the
AndroidManifest. This is done by setting the <i>resizeableActivity</i> property to
<i>false</i> for this activity.
</string>
<string name="activity_adjacent_description">This activity was launched with the flag
<b>Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT</b>.\n\nIf possible, it has been launched into the
adjacent area from the activity that started it.\nThis is only a hint to the system. For
example - if the application is not in split-screen mode, it will be launched full-screen.
If it is launched in the same task as the initial Activity, it will retain its activity
properties and its location.
</string>
<string name="activity_custom_description">This activity handles configuration changes
itself.\n\nIn the AndroidManifest, this activity has been configured to receive callbacks
for <b>screenSize|smallestScreenSize|screenLayout|orientation</b>
changes.\nTry resizing this activity to different sizes to see which configuration
properties change.
</string>
<string name="activity_bounds_description">This activity has been launched with a launch bounds
set in its intent. The bounds define the area into which the activity should be launched.
\n\nNote that this flag only applies in free-form mode.
</string>
<string name="activity_minimum_description">This activity has a minimum size.\nIt was launched
into the top/end corner with a a default size of 750dp by 500dp, with a minimum size of 750dp
as defined in its <b>layout attribute in the AndroidManifest definition</b>.
\n\nNote that this Activity was launched in a different task, otherwise the properties from
the Activity that launched this one would have been applied.
</string>
</resources>

View file

@ -0,0 +1,36 @@
<!--
Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<!-- Base application theme. -->
<style name="MultiWindowSampleTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<!-- Drawable to use in the background while the window is resizing on Android N. -->
<item name="android:windowBackgroundFallback">@color/colorAccent</item>
<item name="android:windowBackground">@color/colorAccent</item>
</style>
<style name="TextWarning" parent="TextAppearance.AppCompat.Medium">
</style>
</resources>

View file

@ -0,0 +1,117 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.multiwindowplayground;
import com.android.multiwindowplayground.activities.AdjacentActivity;
import com.android.multiwindowplayground.activities.BasicActivity;
import com.android.multiwindowplayground.activities.CustomConfigurationChangeActivity;
import com.android.multiwindowplayground.activities.LaunchBoundsActivity;
import com.android.multiwindowplayground.activities.LoggingActivity;
import com.android.multiwindowplayground.activities.MinimumSizeActivity;
import com.android.multiwindowplayground.activities.UnresizableActivity;
import android.app.ActivityOptions;
import android.content.Intent;
import android.graphics.Rect;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
public class MainActivity extends LoggingActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
View multiDisabledMessage = findViewById(R.id.warning_multiwindow_disabled);
// Display an additional message if the app is not in multiwindow mode.
if (!isInMultiWindowMode()) {
multiDisabledMessage.setVisibility(View.VISIBLE);
} else {
multiDisabledMessage.setVisibility(View.GONE);
}
}
public void onStartUnresizableClick(View view) {
Log.d(mLogTag, "** starting UnresizableActivity");
/*
* This activity is marked as 'unresizable' in the AndroidManifest. We need to specify the
* FLAG_ACTIVITY_NEW_TASK flag here to launch it into a new task stack, otherwise the
* properties from the root activity would have been inherited (which was here marked as
* resizable by default).
*/
Intent intent = new Intent(this, UnresizableActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
public void onStartMinimumSizeActivity(View view) {
Log.d(mLogTag, "** starting MinimumSizeActivity");
startActivity(new Intent(this, MinimumSizeActivity.class));
}
public void onStartAdjacentActivity(View view) {
Log.d(mLogTag, "** starting AdjacentActivity");
/*
* Start this activity adjacent to the focused activity (ie. this activity) if possible.
* Note that this flag is just a hint to the system and may be ignored. For example,
* if the activity is launched within the same task, it will be launched on top of the
* previous activity that started the Intent. That's why the Intent.FLAG_ACTIVITY_NEW_TASK
* flag is specified here in the intent - this will start the activity in a new task.
*/
Intent intent = new Intent(this, AdjacentActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
public void onStartLaunchBoundsActivity(View view) {
Log.d(mLogTag, "** starting LaunchBoundsActivity");
// Define the bounds in which the Activity will be launched into.
Rect bounds = new Rect(500, 300, 100, 0);
// Set the bounds as an activity option.
ActivityOptions options = ActivityOptions.makeBasic();
options.setLaunchBounds(bounds);
// Start the LaunchBoundsActivity with the specified options
Intent intent = new Intent(this, LaunchBoundsActivity.class);
startActivity(intent, options.toBundle());
}
public void onStartBasicActivity(View view) {
Log.d(mLogTag, "** starting BasicActivity");
// Start an Activity with the default options in the 'singleTask' launch mode as defined in
// the AndroidManifest.xml.
startActivity(new Intent(this, BasicActivity.class));
}
public void onStartCustomConfigurationActivity(View view) {
Log.d(mLogTag, "** starting CustomConfigurationChangeActivity");
// Start an Activity that handles all configuration changes itself.
startActivity(new Intent(this, CustomConfigurationChangeActivity.class));
}
}

View file

@ -0,0 +1,41 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.multiwindowplayground.activities;
import com.android.multiwindowplayground.R;
import android.os.Bundle;
import android.view.View;
/**
* This Activity is to be launched adjacent to another Activity using the {@link
* android.content.Intent#FLAG_ACTIVITY_LAUNCH_ADJACENT}.
*
* @see com.android.multiwindowplayground.MainActivity#onStartAdjacentActivity(View)
*/
public class AdjacentActivity extends LoggingActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_logging);
setBackgroundColor(R.color.teal);
setDescription(R.string.activity_adjacent_description);
}
}

View file

@ -0,0 +1,43 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.multiwindowplayground.activities;
import com.android.multiwindowplayground.R;
import android.os.Bundle;
import android.view.View;
/**
* This activity is the most basic, simeple use case and is to be launched without any special
* flags
* or settings.
*
* @see com.android.multiwindowplayground.MainActivity#onStartBasicActivity(View)
*/
public class BasicActivity extends LoggingActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_logging);
// Set the color and description
setDescription(R.string.activity_description_basic);
setBackgroundColor(R.color.gray);
}
}

View file

@ -0,0 +1,54 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.multiwindowplayground.activities;
import com.android.multiwindowplayground.R;
import android.content.res.Configuration;
import android.os.Bundle;
import android.view.View;
/**
* This activity handles configuration changes itself. The list of configuration changes that are
* supported is defined in its AndroidManifest definition. Each configuration change triggers a
* call to {@link #onConfigurationChanged(Configuration)}, which is logged in the {@link
* LoggingActivity}.
*
* @see com.android.multiwindowplayground.MainActivity#onStartCustomConfigurationActivity(View)
*/
public class CustomConfigurationChangeActivity extends LoggingActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_logging);
setBackgroundColor(R.color.cyan);
setDescription(R.string.activity_custom_description);
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
/*
Note: The implementation in LoggingActivity logs the output o the new configuration.
This callback is received whenever the configuration is updated, for example when the
size of this Activity is changed.
*/
}
}

View file

@ -0,0 +1,41 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.multiwindowplayground.activities;
import com.android.multiwindowplayground.R;
import android.os.Bundle;
import android.view.View;
/**
* In free-form mode, this activity is to be launched within a defined bounds on screen.
* This property is set as part of the Intent that starts this activity.
*
* @see com.android.multiwindowplayground.MainActivity#onStartLaunchBoundsActivity(View)
*/
public class LaunchBoundsActivity extends LoggingActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_logging);
setBackgroundColor(R.color.lime);
setDescription(R.string.activity_bounds_description);
}
}

View file

@ -0,0 +1,156 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.multiwindowplayground.activities;
import com.android.multiwindowplayground.R;
import com.example.android.common.logger.Log;
import com.example.android.common.logger.LogFragment;
import com.example.android.common.logger.LogWrapper;
import com.example.android.common.logger.MessageOnlyLogFilter;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.support.annotation.ColorRes;
import android.support.annotation.StringRes;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;
/**
* Activity that logs all key lifecycle callbacks to {@link Log}.
* Output is also logged to the UI into a {@link LogFragment} through {@link #initializeLogging()}
* and {@link #stopLogging()}.
*/
public abstract class LoggingActivity extends AppCompatActivity {
protected String mLogTag = getClass().getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(mLogTag, "onCreate");
}
@Override
public void onPostCreate(Bundle savedInstanceState, PersistableBundle persistentState) {
super.onPostCreate(savedInstanceState, persistentState);
Log.d(mLogTag, "onPostCreate");
}
@Override
protected void onPause() {
super.onPause();
Log.d(mLogTag, "onPause");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(mLogTag, "onDestroy");
}
@Override
protected void onResume() {
super.onResume();
Log.d(mLogTag, "onResume");
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Log.d(mLogTag, "onConfigurationChanged: " + newConfig.toString());
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
Log.d(mLogTag, "onPostCreate");
}
@Override
protected void onStart() {
super.onStart();
// Start logging to UI.
initializeLogging();
Log.d(mLogTag, "onStart");
}
@Override
protected void onStop() {
super.onStop();
// Stop logging to UI when this activity is stopped.
stopLogging();
Log.d(mLogTag, "onStop");
}
@Override
public void onMultiWindowModeChanged(boolean isInMultiWindowMode) {
super.onMultiWindowModeChanged(isInMultiWindowMode);
Log.d(mLogTag, "onMultiWindowModeChanged: " + isInMultiWindowMode);
}
// Logging and UI methods below.
/** Set up targets to receive log data */
public void initializeLogging() {
// Using Log, front-end to the logging chain, emulates android.util.log method signatures.
// Wraps Android's native log framework
LogWrapper logWrapper = new LogWrapper();
Log.setLogNode(logWrapper);
// Filter strips out everything except the message text.
MessageOnlyLogFilter msgFilter = new MessageOnlyLogFilter();
logWrapper.setNext(msgFilter);
// On screen logging via a fragment with a TextView.
LogFragment logFragment = (LogFragment) getSupportFragmentManager()
.findFragmentById(R.id.log_fragment);
msgFilter.setNext(logFragment.getLogView());
}
public void stopLogging() {
Log.setLogNode(null);
}
/**
* Set the description text if a TextView with the id <code>description</code> is available.
*/
protected void setDescription(@StringRes int textId) {
// Set the text and background color
TextView description = (TextView) findViewById(R.id.description);
if (description != null) {
description.setText(textId);
}
}
/**
* Set the background color for the description text.
*/
protected void setBackgroundColor(@ColorRes int colorId) {
View scrollView = findViewById(R.id.scrollview);
if (scrollView != null) {
scrollView.setBackgroundResource(colorId);
}
}
}

View file

@ -0,0 +1,40 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.multiwindowplayground.activities;
import com.android.multiwindowplayground.R;
import android.os.Bundle;
import android.view.View;
/**
* This Activity has a minimum size defined in the AndroidManifeset.
*
* @see com.android.multiwindowplayground.MainActivity#onStartMinimumSizeActivity(View)
*/
public class MinimumSizeActivity extends LoggingActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_logging);
setBackgroundColor(R.color.pink);
setDescription(R.string.activity_minimum_description);
}
}

View file

@ -0,0 +1,42 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.multiwindowplayground.activities;
import com.android.multiwindowplayground.R;
import android.os.Bundle;
import android.view.View;
/**
* This Activity is defined as unresizable in the AndroidManifest.
* This means that this activity is always launched full screen and will not be resized by the
* system.
*
* @see com.android.multiwindowplayground.MainActivity#onStartUnresizableClick(View)
*/
public class UnresizableActivity extends LoggingActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_logging);
setBackgroundColor(R.color.purple);
setDescription(R.string.activity_description_unresizable);
}
}

View file

@ -0,0 +1,238 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.android.common.logger;
/**
* Helper class for a list (or tree) of LoggerNodes.
*
* <p>When this is set as the head of the list,
* an instance of it can function as a drop-in replacement for {@link android.util.Log}.
* Most of the methods in this class server only to map a method call in Log to its equivalent
* in LogNode.</p>
*/
public class Log {
// Grabbing the native values from Android's native logging facilities,
// to make for easy migration and interop.
public static final int NONE = -1;
public static final int VERBOSE = android.util.Log.VERBOSE;
public static final int DEBUG = android.util.Log.DEBUG;
public static final int INFO = android.util.Log.INFO;
public static final int WARN = android.util.Log.WARN;
public static final int ERROR = android.util.Log.ERROR;
public static final int ASSERT = android.util.Log.ASSERT;
// Stores the beginning of the LogNode topology.
private static LogNode mLogNode;
/**
* Returns the next LogNode in the linked list.
*/
public static LogNode getLogNode() {
return mLogNode;
}
/**
* Sets the LogNode data will be sent to.
*/
public static void setLogNode(LogNode node) {
mLogNode = node;
}
/**
* Instructs the LogNode to print the log data provided. Other LogNodes can
* be chained to the end of the LogNode as desired.
*
* @param priority Log level of the data being logged. Verbose, Error, etc.
* @param tag Tag for for the log data. Can be used to organize log statements.
* @param msg The actual message to be logged.
* @param tr If an exception was thrown, this can be sent along for the logging
* facilities
* to extract and print useful information.
*/
public static void println(int priority, String tag, String msg, Throwable tr) {
if (mLogNode != null) {
mLogNode.println(priority, tag, msg, tr);
}
}
/**
* Instructs the LogNode to print the log data provided. Other LogNodes can
* be chained to the end of the LogNode as desired.
*
* @param priority Log level of the data being logged. Verbose, Error, etc.
* @param tag Tag for for the log data. Can be used to organize log statements.
* @param msg The actual message to be logged. The actual message to be logged.
*/
public static void println(int priority, String tag, String msg) {
println(priority, tag, msg, null);
}
/**
* Prints a message at VERBOSE priority.
*
* @param tag Tag for for the log data. Can be used to organize log statements.
* @param msg The actual message to be logged.
* @param tr If an exception was thrown, this can be sent along for the logging facilities
* to extract and print useful information.
*/
public static void v(String tag, String msg, Throwable tr) {
println(VERBOSE, tag, msg, tr);
}
/**
* Prints a message at VERBOSE priority.
*
* @param tag Tag for for the log data. Can be used to organize log statements.
* @param msg The actual message to be logged.
*/
public static void v(String tag, String msg) {
v(tag, msg, null);
}
/**
* Prints a message at DEBUG priority.
*
* @param tag Tag for for the log data. Can be used to organize log statements.
* @param msg The actual message to be logged.
* @param tr If an exception was thrown, this can be sent along for the logging facilities
* to extract and print useful information.
*/
public static void d(String tag, String msg, Throwable tr) {
println(DEBUG, tag, msg, tr);
}
/**
* Prints a message at DEBUG priority.
*
* @param tag Tag for for the log data. Can be used to organize log statements.
* @param msg The actual message to be logged.
*/
public static void d(String tag, String msg) {
d(tag, msg, null);
}
/**
* Prints a message at INFO priority.
*
* @param tag Tag for for the log data. Can be used to organize log statements.
* @param msg The actual message to be logged.
* @param tr If an exception was thrown, this can be sent along for the logging facilities
* to extract and print useful information.
*/
public static void i(String tag, String msg, Throwable tr) {
println(INFO, tag, msg, tr);
}
/**
* Prints a message at INFO priority.
*
* @param tag Tag for for the log data. Can be used to organize log statements.
* @param msg The actual message to be logged.
*/
public static void i(String tag, String msg) {
i(tag, msg, null);
}
/**
* Prints a message at WARN priority.
*
* @param tag Tag for for the log data. Can be used to organize log statements.
* @param msg The actual message to be logged.
* @param tr If an exception was thrown, this can be sent along for the logging facilities
* to extract and print useful information.
*/
public static void w(String tag, String msg, Throwable tr) {
println(WARN, tag, msg, tr);
}
/**
* Prints a message at WARN priority.
*
* @param tag Tag for for the log data. Can be used to organize log statements.
* @param msg The actual message to be logged.
*/
public static void w(String tag, String msg) {
w(tag, msg, null);
}
/**
* Prints a message at WARN priority.
*
* @param tag Tag for for the log data. Can be used to organize log statements.
* @param tr If an exception was thrown, this can be sent along for the logging facilities
* to extract and print useful information.
*/
public static void w(String tag, Throwable tr) {
w(tag, null, tr);
}
/**
* Prints a message at ERROR priority.
*
* @param tag Tag for for the log data. Can be used to organize log statements.
* @param msg The actual message to be logged.
* @param tr If an exception was thrown, this can be sent along for the logging facilities
* to extract and print useful information.
*/
public static void e(String tag, String msg, Throwable tr) {
println(ERROR, tag, msg, tr);
}
/**
* Prints a message at ERROR priority.
*
* @param tag Tag for for the log data. Can be used to organize log statements.
* @param msg The actual message to be logged.
*/
public static void e(String tag, String msg) {
e(tag, msg, null);
}
/**
* Prints a message at ASSERT priority.
*
* @param tag Tag for for the log data. Can be used to organize log statements.
* @param msg The actual message to be logged.
* @param tr If an exception was thrown, this can be sent along for the logging facilities
* to extract and print useful information.
*/
public static void wtf(String tag, String msg, Throwable tr) {
println(ASSERT, tag, msg, tr);
}
/**
* Prints a message at ASSERT priority.
*
* @param tag Tag for for the log data. Can be used to organize log statements.
* @param msg The actual message to be logged.
*/
public static void wtf(String tag, String msg) {
wtf(tag, msg, null);
}
/**
* Prints a message at ASSERT priority.
*
* @param tag Tag for for the log data. Can be used to organize log statements.
* @param tr If an exception was thrown, this can be sent along for the logging facilities
* to extract and print useful information.
*/
public static void wtf(String tag, Throwable tr) {
wtf(tag, null, tr);
}
}

View file

@ -0,0 +1,105 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.android.common.logger;
import android.graphics.Typeface;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ScrollView;
/**
* Simple fraggment which contains a LogView and uses is to output log data it receives
* through the LogNode interface.
*/
public class LogFragment extends Fragment {
private LogView mLogView;
private ScrollView mScrollView;
public LogFragment() {
}
public View inflateViews() {
mScrollView = new ScrollView(getActivity());
ViewGroup.LayoutParams scrollParams = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
mScrollView.setLayoutParams(scrollParams);
mLogView = new LogView(getActivity());
ViewGroup.LayoutParams logParams = new ViewGroup.LayoutParams(scrollParams);
logParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
mLogView.setTextAppearance(android.R.style.TextAppearance_Material_Medium);
mLogView.setLayoutParams(logParams);
mLogView.setClickable(true);
mLogView.setFocusable(true);
mLogView.setTypeface(Typeface.create("monospace", Typeface.NORMAL));
// Want to set padding as 16 dips, setPadding takes pixels. Hooray math!
int paddingDips = 16;
double scale = getResources().getDisplayMetrics().density;
int paddingPixels = (int) ((paddingDips * (scale)) + .5);
mLogView.setPadding(paddingPixels, paddingPixels, paddingPixels, paddingPixels);
mLogView.setCompoundDrawablePadding(paddingPixels);
mLogView.setGravity(Gravity.BOTTOM);
mScrollView.addView(mLogView);
return mScrollView;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View result = inflateViews();
mLogView.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
mScrollView.post(new Runnable() {
@Override
public void run() {
mScrollView
.smoothScrollTo(0, mScrollView.getBottom() + mLogView.getHeight());
}
});
}
});
return result;
}
public LogView getLogView() {
return mLogView;
}
}

View file

@ -0,0 +1,41 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.android.common.logger;
/**
* Basic interface for a logging system that can output to one or more targets.
* Note that in addition to classes that will output these logs in some format,
* one can also implement this interface over a filter and insert that in the chain,
* such that no targets further down see certain data, or see manipulated forms of the data.
* You could, for instance, write a "ToHtmlLoggerNode" that just converted all the log data
* it received to HTML and sent it along to the next node in the chain, without printing it
* anywhere.
*/
public interface LogNode {
/**
* Instructs first LogNode in the list to print the log data provided.
*
* @param priority Log level of the data being logged. Verbose, Error, etc.
* @param tag Tag for for the log data. Can be used to organize log statements.
* @param msg The actual message to be logged. The actual message to be logged.
* @param tr If an exception was thrown, this can be sent along for the logging
* facilities
* to extract and print useful information.
*/
public void println(int priority, String tag, String msg, Throwable tr);
}

View file

@ -0,0 +1,149 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.android.common.logger;
import android.app.Activity;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.TextView;
/**
* Simple TextView which is used to output log data received through the LogNode interface.
*/
public class LogView extends TextView implements LogNode {
public LogView(Context context) {
super(context);
}
public LogView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public LogView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
/**
* Formats the log data and prints it out to the LogView.
*
* @param priority Log level of the data being logged. Verbose, Error, etc.
* @param tag Tag for for the log data. Can be used to organize log statements.
* @param msg The actual message to be logged. The actual message to be logged.
* @param tr If an exception was thrown, this can be sent along for the logging
* facilities
* to extract and print useful information.
*/
@Override
public void println(int priority, String tag, String msg, Throwable tr) {
String priorityStr = null;
// For the purposes of this View, we want to print the priority as readable text.
switch (priority) {
case android.util.Log.VERBOSE:
priorityStr = "VERBOSE";
break;
case android.util.Log.DEBUG:
priorityStr = "DEBUG";
break;
case android.util.Log.INFO:
priorityStr = "INFO";
break;
case android.util.Log.WARN:
priorityStr = "WARN";
break;
case android.util.Log.ERROR:
priorityStr = "ERROR";
break;
case android.util.Log.ASSERT:
priorityStr = "ASSERT";
break;
default:
break;
}
// Handily, the Log class has a facility for converting a stack trace into a usable string.
String exceptionStr = null;
if (tr != null) {
exceptionStr = android.util.Log.getStackTraceString(tr);
}
// Take the priority, tag, message, and exception, and concatenate as necessary
// into one usable line of text.
final StringBuilder outputBuilder = new StringBuilder();
String delimiter = "\t";
appendIfNotNull(outputBuilder, priorityStr, delimiter);
appendIfNotNull(outputBuilder, tag, delimiter);
appendIfNotNull(outputBuilder, msg, delimiter);
appendIfNotNull(outputBuilder, exceptionStr, delimiter);
// In case this was originally called from an AsyncTask or some other off-UI thread,
// make sure the update occurs within the UI thread.
((Activity) getContext()).runOnUiThread((new Thread(new Runnable() {
@Override
public void run() {
// Display the text we just generated within the LogView.
appendToLog(outputBuilder.toString());
}
})));
if (mNext != null) {
mNext.println(priority, tag, msg, tr);
}
}
public LogNode getNext() {
return mNext;
}
public void setNext(LogNode node) {
mNext = node;
}
/**
* Takes a string and adds to it, with a separator, if the bit to be added isn't null. Since
* the logger takes so many arguments that might be null, this method helps cut out some of the
* agonizing tedium of writing the same 3 lines over and over.
*
* @param source StringBuilder containing the text to append to.
* @param addStr The String to append
* @param delimiter The String to separate the source and appended strings. A tab or comma,
* for instance.
* @return The fully concatenated String as a StringBuilder
*/
private StringBuilder appendIfNotNull(StringBuilder source, String addStr, String delimiter) {
if (addStr != null) {
if (addStr.length() == 0) {
delimiter = "";
}
return source.append(addStr).append(delimiter);
}
return source;
}
// The next LogNode in the chain.
LogNode mNext;
/** Outputs the string as a new line of log data in the LogView. */
public void appendToLog(String s) {
append("\n" + s);
}
}

View file

@ -0,0 +1,77 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.android.common.logger;
import android.util.Log;
/**
* Helper class which wraps Android's native Log utility in the Logger interface. This way
* normal DDMS output can be one of the many targets receiving and outputting logs simultaneously.
*/
public class LogWrapper implements LogNode {
// For piping: The next node to receive Log data after this one has done its work.
private LogNode mNext;
/**
* Returns the next LogNode in the linked list.
*/
public LogNode getNext() {
return mNext;
}
/**
* Sets the LogNode data will be sent to..
*/
public void setNext(LogNode node) {
mNext = node;
}
/**
* Prints data out to the console using Android's native log mechanism.
*
* @param priority Log level of the data being logged. Verbose, Error, etc.
* @param tag Tag for for the log data. Can be used to organize log statements.
* @param msg The actual message to be logged. The actual message to be logged.
* @param tr If an exception was thrown, this can be sent along for the logging
* facilities
* to extract and print useful information.
*/
@Override
public void println(int priority, String tag, String msg, Throwable tr) {
// There actually are log methods that don't take a msg parameter. For now,
// if that's the case, just convert null to the empty string and move on.
String useMsg = msg;
if (useMsg == null) {
useMsg = "";
}
// If an exeption was provided, convert that exception to a usable string and attach
// it to the end of the msg method.
if (tr != null) {
msg += "\n" + Log.getStackTraceString(tr);
}
// This is functionally identical to Log.x(tag, useMsg);
// For instance, if priority were Log.VERBOSE, this would be the same as Log.v(tag, useMsg)
Log.println(priority, tag, useMsg);
// If this isn't the last node in the chain, move things along.
if (mNext != null) {
mNext.println(priority, tag, msg, tr);
}
}
}

View file

@ -0,0 +1,61 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.android.common.logger;
/**
* Simple {@link LogNode} filter, removes everything except the message.
* Useful for situations like on-screen log output where you don't want a lot of metadata
* displayed,
* just easy-to-read message updates as they're happening.
*/
public class MessageOnlyLogFilter implements LogNode {
LogNode mNext;
/**
* Takes the "next" LogNode as a parameter, to simplify chaining.
*
* @param next The next LogNode in the pipeline.
*/
public MessageOnlyLogFilter(LogNode next) {
mNext = next;
}
public MessageOnlyLogFilter() {
}
@Override
public void println(int priority, String tag, String msg, Throwable tr) {
if (mNext != null) {
getNext().println(Log.NONE, null, msg, null);
}
}
/**
* Returns the next LogNode in the chain.
*/
public LogNode getNext() {
return mNext;
}
/**
* Sets the LogNode data will be sent to..
*/
public void setNext(LogNode node) {
mNext = node;
}
}