upload android base code part7
31
android/development/tutorials/MoarRam/Android.mk
Normal file
|
@ -0,0 +1,31 @@
|
|||
# Copyright (C) 2013 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.
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
# We only want this apk build for tests.
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
|
||||
# Include all test java files.
|
||||
LOCAL_SRC_FILES := $(call all-java-files-under, src)
|
||||
|
||||
LOCAL_PACKAGE_NAME := MoarRam
|
||||
|
||||
include $(BUILD_PACKAGE)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
include $(call all-makefiles-under,$(LOCAL_PATH))
|
23
android/development/tutorials/MoarRam/AndroidManifest.xml
Normal file
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.android.benchmark.moarram"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0" >
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/AppTheme" >
|
||||
<activity
|
||||
android:name="com.android.benchmark.moarram.MainActivity"
|
||||
android:label="@string/app_name" >
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
17
android/development/tutorials/MoarRam/README.txt
Normal file
|
@ -0,0 +1,17 @@
|
|||
This is a simple app that can be used as a tutorial or reference benchmark
|
||||
for the development of the DDMS native heap tracker feature. It contains 3
|
||||
unique paths to allocate heap chunks:
|
||||
|
||||
1) Java_com_android_benchmark_moarram_MainActivity_add32ByteBlocksNative in
|
||||
foo.c (libmoarram-foo.so). Each invocation will allocate 32 bytes.
|
||||
2) Java_com_android_benchmark_moarram_MainActivity_add2MByteBlocksNative in
|
||||
bar.c (libmoarram-bar.so). Each invocation will allocate 2M bytes.
|
||||
3) Java_com_android_benchmark_moarram_MainActivity_addVariableSizedBlocksNative
|
||||
in baz.c (libmoarram-baz.so). Each invocation will allocate 17 or 71 bytes,
|
||||
depending on the active button in a radio group.
|
||||
|
||||
Each allocation can be freed by clicking the corresponding free button in the
|
||||
UI.
|
||||
|
||||
NOTE 09/16/2013
|
||||
A new feature is added to force a double free. Both debug libc and Valgrind can capture it.
|
52
android/development/tutorials/MoarRam/jni/Android.mk
Normal file
|
@ -0,0 +1,52 @@
|
|||
# Copyright (C) 2013 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.
|
||||
#
|
||||
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_MODULE := libmoarram-32
|
||||
LOCAL_SRC_FILES := foo.c
|
||||
LOCAL_SHARED_LIBRARIES += liblog
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_MODULE := libmoarram-2M
|
||||
LOCAL_SRC_FILES := bar.c
|
||||
LOCAL_SHARED_LIBRARIES += liblog
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_MODULE := libmoarram-17_71
|
||||
LOCAL_SRC_FILES := baz.c
|
||||
LOCAL_SHARED_LIBRARIES += liblog
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_MODULE := libmoarram-doublefree
|
||||
LOCAL_SRC_FILES := df.c
|
||||
LOCAL_SHARED_LIBRARIES += liblog
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
59
android/development/tutorials/MoarRam/jni/bar.c
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (C) 2013 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <jni.h>
|
||||
#include <malloc.h>
|
||||
#include <cutils/log.h>
|
||||
|
||||
#if defined(LOG_TAG)
|
||||
#undef LOG_TAG
|
||||
#define LOG_TAG "MOARRAM"
|
||||
#endif
|
||||
|
||||
char *gPtr2;
|
||||
static int num2MByteBlocks;
|
||||
|
||||
void
|
||||
Java_com_android_benchmark_moarram_MainActivity_add2MByteBlocksNative(
|
||||
JNIEnv* env,
|
||||
jobject this)
|
||||
{
|
||||
char **ptr = malloc(2*1024*1024);
|
||||
*ptr = gPtr2;
|
||||
gPtr2 = (char *) ptr;
|
||||
num2MByteBlocks++;
|
||||
ALOGW("%d 2M-byte blocks allocated so far (just allocated %p)",
|
||||
num2MByteBlocks, gPtr2);
|
||||
}
|
||||
|
||||
void
|
||||
Java_com_android_benchmark_moarram_MainActivity_free2MByteBlocksNative(
|
||||
JNIEnv* env,
|
||||
jobject this)
|
||||
{
|
||||
if (gPtr2 == NULL) {
|
||||
ALOGW("All 2M-byte blocks are freed");
|
||||
return;
|
||||
}
|
||||
|
||||
char **ptr = (char **) gPtr2;
|
||||
gPtr2 = *ptr;
|
||||
free(ptr);
|
||||
num2MByteBlocks--;
|
||||
ALOGW("%d 2M-byte blocks allocated so far (just freed %p)",
|
||||
num2MByteBlocks, ptr);
|
||||
}
|
82
android/development/tutorials/MoarRam/jni/baz.c
Normal file
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright (C) 2013 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <jni.h>
|
||||
#include <malloc.h>
|
||||
#include <cutils/log.h>
|
||||
|
||||
#if defined(LOG_TAG)
|
||||
#undef LOG_TAG
|
||||
#define LOG_TAG "MOARRAM"
|
||||
#endif
|
||||
|
||||
char *gPtr17;
|
||||
char *gPtr71;
|
||||
static int num17ByteBlocks;
|
||||
static int num71ByteBlocks;
|
||||
|
||||
void
|
||||
Java_com_android_benchmark_moarram_MainActivity_addVariableSizedBlocksNative(
|
||||
JNIEnv* env,
|
||||
jobject this,
|
||||
jint id)
|
||||
{
|
||||
int size;
|
||||
char **gPtr;
|
||||
char **ptr;
|
||||
if (id == 0) {
|
||||
size = 17;
|
||||
gPtr = &gPtr17;
|
||||
} else {
|
||||
size = 71;
|
||||
gPtr = &gPtr71;
|
||||
}
|
||||
ptr = malloc(size);
|
||||
*ptr = *gPtr;
|
||||
*gPtr = (char *) ptr;
|
||||
ALOGW("%d %d-byte blocks allocated so far (just allocated %p)",
|
||||
id == 0 ? ++num17ByteBlocks : ++num71ByteBlocks,
|
||||
size, ptr);
|
||||
}
|
||||
|
||||
void
|
||||
Java_com_android_benchmark_moarram_MainActivity_freeVariableSizedBlocksNative(
|
||||
JNIEnv* env,
|
||||
jobject this,
|
||||
jint id)
|
||||
{
|
||||
int size;
|
||||
char **ptr;
|
||||
char **gPtr;
|
||||
if (id == 0) {
|
||||
size = 17;
|
||||
gPtr = &gPtr17;
|
||||
} else {
|
||||
size = 71;
|
||||
gPtr = &gPtr71;
|
||||
}
|
||||
if (*gPtr == NULL) {
|
||||
ALOGW("All %d-byte blocks are freed", size);
|
||||
return;
|
||||
}
|
||||
ptr = (char **) *gPtr;
|
||||
*gPtr = *ptr;
|
||||
free(ptr);
|
||||
ALOGW("%d %d-byte blocks allocated so far (just freed %p)",
|
||||
id == 0 ? --num17ByteBlocks : --num71ByteBlocks,
|
||||
size, ptr);
|
||||
}
|
37
android/development/tutorials/MoarRam/jni/df.c
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (C) 2013 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <jni.h>
|
||||
#include <malloc.h>
|
||||
#include <cutils/log.h>
|
||||
|
||||
#if defined(LOG_TAG)
|
||||
#undef LOG_TAG
|
||||
#define LOG_TAG "MOARRAM"
|
||||
#endif
|
||||
|
||||
void
|
||||
Java_com_android_benchmark_moarram_MainActivity_forceDoubleFreeNative(
|
||||
JNIEnv* env,
|
||||
jobject this)
|
||||
{
|
||||
char *ptr = (char *) malloc(4);
|
||||
*ptr = 0;
|
||||
ALOGW("About to double free %p", ptr);
|
||||
free(ptr);
|
||||
free(ptr);
|
||||
}
|
59
android/development/tutorials/MoarRam/jni/foo.c
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (C) 2013 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <jni.h>
|
||||
#include <malloc.h>
|
||||
#include <cutils/log.h>
|
||||
|
||||
#if defined(LOG_TAG)
|
||||
#undef LOG_TAG
|
||||
#define LOG_TAG "MOARRAM"
|
||||
#endif
|
||||
|
||||
char *gPtr;
|
||||
static int num32ByteBlocks;
|
||||
|
||||
void
|
||||
Java_com_android_benchmark_moarram_MainActivity_add32ByteBlocksNative(
|
||||
JNIEnv* env,
|
||||
jobject this)
|
||||
{
|
||||
char **ptr = malloc(32);
|
||||
*ptr = gPtr;
|
||||
gPtr = (char *) ptr;
|
||||
num32ByteBlocks++;
|
||||
ALOGW("%d 32-byte blocks allocated so far (just allocated %p)",
|
||||
num32ByteBlocks, gPtr);
|
||||
}
|
||||
|
||||
void
|
||||
Java_com_android_benchmark_moarram_MainActivity_free32ByteBlocksNative(
|
||||
JNIEnv* env,
|
||||
jobject this)
|
||||
{
|
||||
if (gPtr == NULL) {
|
||||
ALOGW("All 32-byte blocks are freed");
|
||||
return;
|
||||
}
|
||||
|
||||
char **ptr = (char **) gPtr;
|
||||
gPtr = *ptr;
|
||||
free(ptr);
|
||||
num32ByteBlocks--;
|
||||
ALOGW("%d 32-byte blocks allocated so far (just freed %p)",
|
||||
num32ByteBlocks, ptr);
|
||||
}
|
After Width: | Height: | Size: 7.5 KiB |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 24 KiB |
|
@ -0,0 +1,119 @@
|
|||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="fill_parent"
|
||||
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"
|
||||
tools:context=".MainActivity" >
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<Button
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:text="@string/add_32"
|
||||
android:layout_weight="1"
|
||||
android:onClick="add32ByteBlocks" />
|
||||
|
||||
<Button
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:text="@string/free_32"
|
||||
android:layout_weight="1"
|
||||
android:onClick="free32ByteBlocks" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<Button
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:text="@string/add_2m"
|
||||
android:layout_weight="1"
|
||||
android:onClick="add2MByteBlocks" />
|
||||
|
||||
<Button
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:text="@string/free_2m"
|
||||
android:layout_weight="1"
|
||||
android:onClick="free2MByteBlocks" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/linearLayout2"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<RadioGroup
|
||||
android:id="@+id/blockSize"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center" >
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/radio17"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/_17byte"
|
||||
android:checked="true" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/radio71"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/_71byte" />
|
||||
</RadioGroup>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<Button
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:text="@string/add_variable"
|
||||
android:layout_weight="1"
|
||||
android:onClick="addVariableSizedBlocks" />
|
||||
|
||||
<Button
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:text="@string/free_variable"
|
||||
android:layout_weight="1"
|
||||
android:onClick="freeVariableSizedBlocks" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<Button
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:text="@string/force_double_free"
|
||||
android:layout_weight="1"
|
||||
android:onClick="forceDoubleFree" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
9
android/development/tutorials/MoarRam/res/menu/main.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
|
||||
<item
|
||||
android:id="@+id/action_settings"
|
||||
android:orderInCategory="100"
|
||||
android:showAsAction="never"
|
||||
android:title="@string/action_settings"/>
|
||||
|
||||
</menu>
|
|
@ -0,0 +1,8 @@
|
|||
<resources>
|
||||
|
||||
<!--
|
||||
Customize dimensions originally defined in res/values/dimens.xml (such as
|
||||
screen margins) for sw600dp devices (e.g. 7" tablets) here.
|
||||
-->
|
||||
|
||||
</resources>
|
|
@ -0,0 +1,9 @@
|
|||
<resources>
|
||||
|
||||
<!--
|
||||
Customize dimensions originally defined in res/values/dimens.xml (such as
|
||||
screen margins) for sw720dp devices (e.g. 10" tablets) in landscape here.
|
||||
-->
|
||||
<dimen name="activity_horizontal_margin">128dp</dimen>
|
||||
|
||||
</resources>
|
|
@ -0,0 +1,11 @@
|
|||
<resources>
|
||||
|
||||
<!--
|
||||
Base application theme for API 11+. This theme completely replaces
|
||||
AppBaseTheme from res/values/styles.xml on API 11+ devices.
|
||||
-->
|
||||
<style name="AppBaseTheme" parent="android:Theme.Holo.Light">
|
||||
<!-- API 11 theme customizations can go here. -->
|
||||
</style>
|
||||
|
||||
</resources>
|
|
@ -0,0 +1,12 @@
|
|||
<resources>
|
||||
|
||||
<!--
|
||||
Base application theme for API 14+. This theme completely replaces
|
||||
AppBaseTheme from BOTH res/values/styles.xml and
|
||||
res/values-v11/styles.xml on API 14+ devices.
|
||||
-->
|
||||
<style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
|
||||
<!-- API 14 theme customizations can go here. -->
|
||||
</style>
|
||||
|
||||
</resources>
|
|
@ -0,0 +1,7 @@
|
|||
<resources>
|
||||
|
||||
<!-- Default screen margins, per the Android Design guidelines. -->
|
||||
<dimen name="activity_horizontal_margin">16dp</dimen>
|
||||
<dimen name="activity_vertical_margin">16dp</dimen>
|
||||
|
||||
</resources>
|
17
android/development/tutorials/MoarRam/res/values/strings.xml
Normal file
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<string name="app_name">MoarRam</string>
|
||||
<string name="action_settings">Settings</string>
|
||||
<string name="hello_world">Hello world!</string>
|
||||
<string name="enter_num">Enter a number</string>
|
||||
<string name="add_32">Add 32 bytes</string>
|
||||
<string name="free_32">Free 32 bytes</string>
|
||||
<string name="add_2m">Add 2M bytes</string>
|
||||
<string name="free_2m">Free 2M bytes</string>
|
||||
<string name="add_variable">Add 17 or 71 bytes</string>
|
||||
<string name="free_variable">Free 17 or 71 bytes</string>
|
||||
<string name="_17byte">17 bytes</string>
|
||||
<string name="_71byte">71 bytes</string>
|
||||
<string name="force_double_free">Force a Double Free</string>
|
||||
</resources>
|
20
android/development/tutorials/MoarRam/res/values/styles.xml
Normal file
|
@ -0,0 +1,20 @@
|
|||
<resources>
|
||||
|
||||
<!--
|
||||
Base application theme, dependent on API level. This theme is replaced
|
||||
by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
|
||||
-->
|
||||
<style name="AppBaseTheme" parent="android:Theme.Light">
|
||||
<!--
|
||||
Theme customizations available in newer API levels can go in
|
||||
res/values-vXX/styles.xml, while customizations related to
|
||||
backward-compatibility can go here.
|
||||
-->
|
||||
</style>
|
||||
|
||||
<!-- Application theme. -->
|
||||
<style name="AppTheme" parent="AppBaseTheme">
|
||||
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
|
||||
</style>
|
||||
|
||||
</resources>
|
|
@ -0,0 +1,70 @@
|
|||
package com.android.benchmark.moarram;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.app.Activity;
|
||||
import android.view.Menu;
|
||||
import android.view.View;
|
||||
import android.widget.RadioGroup;
|
||||
|
||||
public class MainActivity extends Activity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
System.loadLibrary("moarram-32");
|
||||
System.loadLibrary("moarram-2M");
|
||||
System.loadLibrary("moarram-17_71");
|
||||
System.loadLibrary("moarram-doublefree");
|
||||
setContentView(R.layout.activity_main);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.main, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void add32ByteBlocks(View view) {
|
||||
add32ByteBlocksNative();
|
||||
}
|
||||
|
||||
public void free32ByteBlocks(View view) {
|
||||
free32ByteBlocksNative();
|
||||
}
|
||||
|
||||
public void add2MByteBlocks(View view) {
|
||||
add2MByteBlocksNative();
|
||||
}
|
||||
|
||||
public void free2MByteBlocks(View view) {
|
||||
free2MByteBlocksNative();
|
||||
}
|
||||
|
||||
public void addVariableSizedBlocks(View view) {
|
||||
|
||||
RadioGroup sizeGroup = (RadioGroup) findViewById(R.id.blockSize);
|
||||
|
||||
int sizeId = sizeGroup.getCheckedRadioButtonId();
|
||||
addVariableSizedBlocksNative(sizeId == R.id.radio17 ? 0 : 1);
|
||||
}
|
||||
|
||||
public void freeVariableSizedBlocks(View view) {
|
||||
|
||||
RadioGroup sizeGroup = (RadioGroup) findViewById(R.id.blockSize);
|
||||
|
||||
int sizeId = sizeGroup.getCheckedRadioButtonId();
|
||||
freeVariableSizedBlocksNative(sizeId == R.id.radio17 ? 0 : 1);
|
||||
}
|
||||
|
||||
public void forceDoubleFree(View view) {
|
||||
forceDoubleFreeNative();
|
||||
}
|
||||
|
||||
public native void add32ByteBlocksNative();
|
||||
public native void free32ByteBlocksNative();
|
||||
public native void add2MByteBlocksNative();
|
||||
public native void free2MByteBlocksNative();
|
||||
public native void addVariableSizedBlocksNative(int sizeId);
|
||||
public native void freeVariableSizedBlocksNative(int sizeId);
|
||||
public native void forceDoubleFreeNative();
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
#
|
||||
# Copyright (C) 2009 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.
|
||||
#
|
||||
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
# Only build apk if this package is added to CUSTOM_MODLUES in buildspec.mk
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
|
||||
# Only compile source java files in this apk.
|
||||
LOCAL_SRC_FILES := $(call all-java-files-under, src)
|
||||
|
||||
LOCAL_PACKAGE_NAME := Notepadv1
|
||||
|
||||
# Make the app build against the current SDK
|
||||
LOCAL_SDK_VERSION := current
|
||||
|
||||
include $(BUILD_PACKAGE)
|
12
android/development/tutorials/NotepadCodeLab/Notepadv1/AndroidManifest.xml
Executable file
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.android.demo.notepad1">
|
||||
<application android:icon="@drawable/icon">
|
||||
<activity android:name=".Notepadv1" android:label="@string/app_name">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
BIN
android/development/tutorials/NotepadCodeLab/Notepadv1/res/drawable/icon.png
Executable file
After Width: | Height: | Size: 6 KiB |
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
</LinearLayout>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">Notepad v1</string>
|
||||
<string name="no_notes">No Notes Yet</string>
|
||||
</resources>
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* 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.demo.notepad1;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
|
||||
public class Notepadv1 extends Activity {
|
||||
private int mNoteNumber = 1;
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
// TODO Auto-generated method stub
|
||||
return super.onCreateOptionsMenu(menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
// TODO Auto-generated method stub
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* 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.demo.notepad1;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.SQLException;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* Simple notes database access helper class. Defines the basic CRUD operations
|
||||
* for the notepad example, and gives the ability to list all notes as well as
|
||||
* retrieve or modify a specific note.
|
||||
*
|
||||
* This has been improved from the first version of this tutorial through the
|
||||
* addition of better error handling and also using returning a Cursor instead
|
||||
* of using a collection of inner classes (which is less scalable and not
|
||||
* recommended).
|
||||
*/
|
||||
public class NotesDbAdapter {
|
||||
|
||||
public static final String KEY_TITLE = "title";
|
||||
public static final String KEY_BODY = "body";
|
||||
public static final String KEY_ROWID = "_id";
|
||||
|
||||
private static final String TAG = "NotesDbAdapter";
|
||||
private DatabaseHelper mDbHelper;
|
||||
private SQLiteDatabase mDb;
|
||||
|
||||
/**
|
||||
* Database creation sql statement
|
||||
*/
|
||||
private static final String DATABASE_CREATE =
|
||||
"create table notes (_id integer primary key autoincrement, "
|
||||
+ "title text not null, body text not null);";
|
||||
|
||||
private static final String DATABASE_NAME = "data";
|
||||
private static final String DATABASE_TABLE = "notes";
|
||||
private static final int DATABASE_VERSION = 2;
|
||||
|
||||
private final Context mCtx;
|
||||
|
||||
private static class DatabaseHelper extends SQLiteOpenHelper {
|
||||
|
||||
DatabaseHelper(Context context) {
|
||||
super(context, DATABASE_NAME, null, DATABASE_VERSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
|
||||
db.execSQL(DATABASE_CREATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
|
||||
+ newVersion + ", which will destroy all old data");
|
||||
db.execSQL("DROP TABLE IF EXISTS notes");
|
||||
onCreate(db);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor - takes the context to allow the database to be
|
||||
* opened/created
|
||||
*
|
||||
* @param ctx the Context within which to work
|
||||
*/
|
||||
public NotesDbAdapter(Context ctx) {
|
||||
this.mCtx = ctx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the notes database. If it cannot be opened, try to create a new
|
||||
* instance of the database. If it cannot be created, throw an exception to
|
||||
* signal the failure
|
||||
*
|
||||
* @return this (self reference, allowing this to be chained in an
|
||||
* initialization call)
|
||||
* @throws SQLException if the database could be neither opened or created
|
||||
*/
|
||||
public NotesDbAdapter open() throws SQLException {
|
||||
mDbHelper = new DatabaseHelper(mCtx);
|
||||
mDb = mDbHelper.getWritableDatabase();
|
||||
return this;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
mDbHelper.close();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new note using the title and body provided. If the note is
|
||||
* successfully created return the new rowId for that note, otherwise return
|
||||
* a -1 to indicate failure.
|
||||
*
|
||||
* @param title the title of the note
|
||||
* @param body the body of the note
|
||||
* @return rowId or -1 if failed
|
||||
*/
|
||||
public long createNote(String title, String body) {
|
||||
ContentValues initialValues = new ContentValues();
|
||||
initialValues.put(KEY_TITLE, title);
|
||||
initialValues.put(KEY_BODY, body);
|
||||
|
||||
return mDb.insert(DATABASE_TABLE, null, initialValues);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the note with the given rowId
|
||||
*
|
||||
* @param rowId id of note to delete
|
||||
* @return true if deleted, false otherwise
|
||||
*/
|
||||
public boolean deleteNote(long rowId) {
|
||||
|
||||
return mDb.delete(DATABASE_TABLE, KEY_ROWID + "=" + rowId, null) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a Cursor over the list of all notes in the database
|
||||
*
|
||||
* @return Cursor over all notes
|
||||
*/
|
||||
public Cursor fetchAllNotes() {
|
||||
|
||||
return mDb.query(DATABASE_TABLE, new String[] {KEY_ROWID, KEY_TITLE,
|
||||
KEY_BODY}, null, null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a Cursor positioned at the note that matches the given rowId
|
||||
*
|
||||
* @param rowId id of note to retrieve
|
||||
* @return Cursor positioned to matching note, if found
|
||||
* @throws SQLException if note could not be found/retrieved
|
||||
*/
|
||||
public Cursor fetchNote(long rowId) throws SQLException {
|
||||
|
||||
Cursor mCursor =
|
||||
|
||||
mDb.query(true, DATABASE_TABLE, new String[] {KEY_ROWID,
|
||||
KEY_TITLE, KEY_BODY}, KEY_ROWID + "=" + rowId, null,
|
||||
null, null, null, null);
|
||||
if (mCursor != null) {
|
||||
mCursor.moveToFirst();
|
||||
}
|
||||
return mCursor;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the note using the details provided. The note to be updated is
|
||||
* specified using the rowId, and it is altered to use the title and body
|
||||
* values passed in
|
||||
*
|
||||
* @param rowId id of note to update
|
||||
* @param title value to set note title to
|
||||
* @param body value to set note body to
|
||||
* @return true if the note was successfully updated, false otherwise
|
||||
*/
|
||||
public boolean updateNote(long rowId, String title, String body) {
|
||||
ContentValues args = new ContentValues();
|
||||
args.put(KEY_TITLE, title);
|
||||
args.put(KEY_BODY, body);
|
||||
|
||||
return mDb.update(DATABASE_TABLE, args, KEY_ROWID + "=" + rowId, null) > 0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
#
|
||||
# Copyright (C) 2009 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.
|
||||
#
|
||||
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
# Only build apk if this package is added to CUSTOM_MODLUES in buildspec.mk
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
|
||||
# Only compile source java files in this apk.
|
||||
LOCAL_SRC_FILES := $(call all-java-files-under, src)
|
||||
|
||||
LOCAL_PACKAGE_NAME := Notepadv1Solution
|
||||
|
||||
# Make the app build against the current SDK
|
||||
LOCAL_SDK_VERSION := current
|
||||
|
||||
include $(BUILD_PACKAGE)
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.android.demo.notepad1">
|
||||
<application android:icon="@drawable/icon">
|
||||
<activity android:name=".Notepadv1" android:label="@string/app_name">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
After Width: | Height: | Size: 6 KiB |
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ListView android:id="@id/android:list"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
<TextView android:id="@id/android:empty"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/no_notes"/>
|
||||
|
||||
</LinearLayout>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TextView android:id="@+id/text1"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">Notepad v1</string>
|
||||
<string name="no_notes">No Notes Yet</string>
|
||||
<string name="menu_insert">Add Item</string>
|
||||
</resources>
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* 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.demo.notepad1;
|
||||
|
||||
import android.app.ListActivity;
|
||||
import android.database.Cursor;
|
||||
import android.os.Bundle;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.SimpleCursorAdapter;
|
||||
|
||||
public class Notepadv1 extends ListActivity {
|
||||
public static final int INSERT_ID = Menu.FIRST;
|
||||
|
||||
private int mNoteNumber = 1;
|
||||
private NotesDbAdapter mDbHelper;
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.notepad_list);
|
||||
mDbHelper = new NotesDbAdapter(this);
|
||||
mDbHelper.open();
|
||||
fillData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
boolean result = super.onCreateOptionsMenu(menu);
|
||||
menu.add(0, INSERT_ID, 0, R.string.menu_insert);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case INSERT_ID:
|
||||
createNote();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
private void createNote() {
|
||||
String noteName = "Note " + mNoteNumber++;
|
||||
mDbHelper.createNote(noteName, "");
|
||||
fillData();
|
||||
}
|
||||
|
||||
private void fillData() {
|
||||
// Get all of the notes from the database and create the item list
|
||||
Cursor c = mDbHelper.fetchAllNotes();
|
||||
startManagingCursor(c);
|
||||
|
||||
String[] from = new String[] { NotesDbAdapter.KEY_TITLE };
|
||||
int[] to = new int[] { R.id.text1 };
|
||||
|
||||
// Now create an array adapter and set it to display using our row
|
||||
SimpleCursorAdapter notes =
|
||||
new SimpleCursorAdapter(this, R.layout.notes_row, c, from, to);
|
||||
setListAdapter(notes);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* 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.demo.notepad1;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.SQLException;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* Simple notes database access helper class. Defines the basic CRUD operations
|
||||
* for the notepad example, and gives the ability to list all notes as well as
|
||||
* retrieve or modify a specific note.
|
||||
*
|
||||
* This has been improved from the first version of this tutorial through the
|
||||
* addition of better error handling and also using returning a Cursor instead
|
||||
* of using a collection of inner classes (which is less scalable and not
|
||||
* recommended).
|
||||
*/
|
||||
public class NotesDbAdapter {
|
||||
|
||||
public static final String KEY_TITLE = "title";
|
||||
public static final String KEY_BODY = "body";
|
||||
public static final String KEY_ROWID = "_id";
|
||||
|
||||
private static final String TAG = "NotesDbAdapter";
|
||||
private DatabaseHelper mDbHelper;
|
||||
private SQLiteDatabase mDb;
|
||||
|
||||
/**
|
||||
* Database creation sql statement
|
||||
*/
|
||||
private static final String DATABASE_CREATE =
|
||||
"create table notes (_id integer primary key autoincrement, "
|
||||
+ "title text not null, body text not null);";
|
||||
|
||||
private static final String DATABASE_NAME = "data";
|
||||
private static final String DATABASE_TABLE = "notes";
|
||||
private static final int DATABASE_VERSION = 2;
|
||||
|
||||
private final Context mCtx;
|
||||
|
||||
private static class DatabaseHelper extends SQLiteOpenHelper {
|
||||
|
||||
DatabaseHelper(Context context) {
|
||||
super(context, DATABASE_NAME, null, DATABASE_VERSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
|
||||
db.execSQL(DATABASE_CREATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
|
||||
+ newVersion + ", which will destroy all old data");
|
||||
db.execSQL("DROP TABLE IF EXISTS notes");
|
||||
onCreate(db);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor - takes the context to allow the database to be
|
||||
* opened/created
|
||||
*
|
||||
* @param ctx the Context within which to work
|
||||
*/
|
||||
public NotesDbAdapter(Context ctx) {
|
||||
this.mCtx = ctx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the notes database. If it cannot be opened, try to create a new
|
||||
* instance of the database. If it cannot be created, throw an exception to
|
||||
* signal the failure
|
||||
*
|
||||
* @return this (self reference, allowing this to be chained in an
|
||||
* initialization call)
|
||||
* @throws SQLException if the database could be neither opened or created
|
||||
*/
|
||||
public NotesDbAdapter open() throws SQLException {
|
||||
mDbHelper = new DatabaseHelper(mCtx);
|
||||
mDb = mDbHelper.getWritableDatabase();
|
||||
return this;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
mDbHelper.close();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new note using the title and body provided. If the note is
|
||||
* successfully created return the new rowId for that note, otherwise return
|
||||
* a -1 to indicate failure.
|
||||
*
|
||||
* @param title the title of the note
|
||||
* @param body the body of the note
|
||||
* @return rowId or -1 if failed
|
||||
*/
|
||||
public long createNote(String title, String body) {
|
||||
ContentValues initialValues = new ContentValues();
|
||||
initialValues.put(KEY_TITLE, title);
|
||||
initialValues.put(KEY_BODY, body);
|
||||
|
||||
return mDb.insert(DATABASE_TABLE, null, initialValues);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the note with the given rowId
|
||||
*
|
||||
* @param rowId id of note to delete
|
||||
* @return true if deleted, false otherwise
|
||||
*/
|
||||
public boolean deleteNote(long rowId) {
|
||||
|
||||
return mDb.delete(DATABASE_TABLE, KEY_ROWID + "=" + rowId, null) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a Cursor over the list of all notes in the database
|
||||
*
|
||||
* @return Cursor over all notes
|
||||
*/
|
||||
public Cursor fetchAllNotes() {
|
||||
|
||||
return mDb.query(DATABASE_TABLE, new String[] {KEY_ROWID, KEY_TITLE,
|
||||
KEY_BODY}, null, null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a Cursor positioned at the note that matches the given rowId
|
||||
*
|
||||
* @param rowId id of note to retrieve
|
||||
* @return Cursor positioned to matching note, if found
|
||||
* @throws SQLException if note could not be found/retrieved
|
||||
*/
|
||||
public Cursor fetchNote(long rowId) throws SQLException {
|
||||
|
||||
Cursor mCursor =
|
||||
|
||||
mDb.query(true, DATABASE_TABLE, new String[] {KEY_ROWID,
|
||||
KEY_TITLE, KEY_BODY}, KEY_ROWID + "=" + rowId, null,
|
||||
null, null, null, null);
|
||||
if (mCursor != null) {
|
||||
mCursor.moveToFirst();
|
||||
}
|
||||
return mCursor;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the note using the details provided. The note to be updated is
|
||||
* specified using the rowId, and it is altered to use the title and body
|
||||
* values passed in
|
||||
*
|
||||
* @param rowId id of note to update
|
||||
* @param title value to set note title to
|
||||
* @param body value to set note body to
|
||||
* @return true if the note was successfully updated, false otherwise
|
||||
*/
|
||||
public boolean updateNote(long rowId, String title, String body) {
|
||||
ContentValues args = new ContentValues();
|
||||
args.put(KEY_TITLE, title);
|
||||
args.put(KEY_BODY, body);
|
||||
|
||||
return mDb.update(DATABASE_TABLE, args, KEY_ROWID + "=" + rowId, null) > 0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
#
|
||||
# Copyright (C) 2009 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.
|
||||
#
|
||||
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
# Only build apk if this package is added to CUSTOM_MODLUES in buildspec.mk
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
|
||||
# Only compile source java files in this apk.
|
||||
LOCAL_SRC_FILES := $(call all-java-files-under, src)
|
||||
|
||||
LOCAL_PACKAGE_NAME := Notepadv2
|
||||
|
||||
# Make the app build against the current SDK
|
||||
LOCAL_SDK_VERSION := current
|
||||
|
||||
include $(BUILD_PACKAGE)
|
12
android/development/tutorials/NotepadCodeLab/Notepadv2/AndroidManifest.xml
Executable file
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.android.demo.notepad2">
|
||||
<application android:icon="@drawable/icon">
|
||||
<activity android:name=".Notepadv2" android:label="@string/app_name">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
BIN
android/development/tutorials/NotepadCodeLab/Notepadv2/res/drawable/icon.png
Executable file
After Width: | Height: | Size: 6 KiB |
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical" android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/title" />
|
||||
<EditText android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"/>
|
||||
</LinearLayout>
|
||||
|
||||
<TextView android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/body" />
|
||||
<EditText android:id="@+id/body" android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:scrollbars="vertical" />
|
||||
|
||||
<Button android:id="@+id/confirm"
|
||||
android:text="@string/confirm"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</LinearLayout>
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ListView android:id="@+id/android:list"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
<TextView android:id="@+id/android:empty"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/no_notes"/>
|
||||
</LinearLayout>
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TextView android:id="@+id/text1" xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">Notepad v2</string>
|
||||
<string name="no_notes">No Notes Yet</string>
|
||||
<string name="menu_insert">Add Note</string>
|
||||
<string name="menu_delete">Delete Note</string>
|
||||
<string name="title">Title</string>
|
||||
<string name="body">Body</string>
|
||||
<string name="confirm">Confirm</string>
|
||||
<string name="edit_note">Edit Note</string>
|
||||
</resources>
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* 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.demo.notepad2;
|
||||
|
||||
import android.app.ListActivity;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
import android.os.Bundle;
|
||||
import android.view.ContextMenu;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ContextMenu.ContextMenuInfo;
|
||||
import android.widget.ListView;
|
||||
import android.widget.SimpleCursorAdapter;
|
||||
|
||||
public class Notepadv2 extends ListActivity {
|
||||
private static final int ACTIVITY_CREATE=0;
|
||||
private static final int ACTIVITY_EDIT=1;
|
||||
|
||||
private static final int INSERT_ID = Menu.FIRST;
|
||||
private static final int DELETE_ID = Menu.FIRST + 1;
|
||||
|
||||
private NotesDbAdapter mDbHelper;
|
||||
private Cursor mNotesCursor;
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.notes_list);
|
||||
mDbHelper = new NotesDbAdapter(this);
|
||||
mDbHelper.open();
|
||||
fillData();
|
||||
}
|
||||
|
||||
private void fillData() {
|
||||
// Get all of the rows from the database and create the item list
|
||||
mNotesCursor = mDbHelper.fetchAllNotes();
|
||||
startManagingCursor(mNotesCursor);
|
||||
|
||||
// Create an array to specify the fields we want to display in the list (only TITLE)
|
||||
String[] from = new String[]{NotesDbAdapter.KEY_TITLE};
|
||||
|
||||
// and an array of the fields we want to bind those fields to (in this case just text1)
|
||||
int[] to = new int[]{R.id.text1};
|
||||
|
||||
// Now create a simple cursor adapter and set it to display
|
||||
SimpleCursorAdapter notes =
|
||||
new SimpleCursorAdapter(this, R.layout.notes_row, mNotesCursor, from, to);
|
||||
setListAdapter(notes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
super.onCreateOptionsMenu(menu);
|
||||
menu.add(0, INSERT_ID,0, R.string.menu_insert);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemSelected(int featureId, MenuItem item) {
|
||||
switch(item.getItemId()) {
|
||||
case INSERT_ID:
|
||||
createNote();
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.onMenuItemSelected(featureId, item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateContextMenu(ContextMenu menu, View v,
|
||||
ContextMenuInfo menuInfo) {
|
||||
super.onCreateContextMenu(menu, v, menuInfo);
|
||||
|
||||
// TODO: fill in rest of method
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onContextItemSelected(MenuItem item) {
|
||||
return super.onContextItemSelected(item);
|
||||
|
||||
// TODO: fill in rest of method
|
||||
}
|
||||
|
||||
private void createNote() {
|
||||
// TODO: fill in implementation
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onListItemClick(ListView l, View v, int position, long id) {
|
||||
super.onListItemClick(l, v, position, id);
|
||||
|
||||
// TODO: fill in rest of method
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
|
||||
super.onActivityResult(requestCode, resultCode, intent);
|
||||
|
||||
// TODO: fill in rest of method
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* 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.demo.notepad2;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.SQLException;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* Simple notes database access helper class. Defines the basic CRUD operations
|
||||
* for the notepad example, and gives the ability to list all notes as well as
|
||||
* retrieve or modify a specific note.
|
||||
*
|
||||
* This has been improved from the first version of this tutorial through the
|
||||
* addition of better error handling and also using returning a Cursor instead
|
||||
* of using a collection of inner classes (which is less scalable and not
|
||||
* recommended).
|
||||
*/
|
||||
public class NotesDbAdapter {
|
||||
|
||||
public static final String KEY_TITLE = "title";
|
||||
public static final String KEY_BODY = "body";
|
||||
public static final String KEY_ROWID = "_id";
|
||||
|
||||
private static final String TAG = "NotesDbAdapter";
|
||||
private DatabaseHelper mDbHelper;
|
||||
private SQLiteDatabase mDb;
|
||||
|
||||
/**
|
||||
* Database creation sql statement
|
||||
*/
|
||||
private static final String DATABASE_CREATE =
|
||||
"create table notes (_id integer primary key autoincrement, "
|
||||
+ "title text not null, body text not null);";
|
||||
|
||||
private static final String DATABASE_NAME = "data";
|
||||
private static final String DATABASE_TABLE = "notes";
|
||||
private static final int DATABASE_VERSION = 2;
|
||||
|
||||
private final Context mCtx;
|
||||
|
||||
private static class DatabaseHelper extends SQLiteOpenHelper {
|
||||
|
||||
DatabaseHelper(Context context) {
|
||||
super(context, DATABASE_NAME, null, DATABASE_VERSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
|
||||
db.execSQL(DATABASE_CREATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
|
||||
+ newVersion + ", which will destroy all old data");
|
||||
db.execSQL("DROP TABLE IF EXISTS notes");
|
||||
onCreate(db);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor - takes the context to allow the database to be
|
||||
* opened/created
|
||||
*
|
||||
* @param ctx the Context within which to work
|
||||
*/
|
||||
public NotesDbAdapter(Context ctx) {
|
||||
this.mCtx = ctx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the notes database. If it cannot be opened, try to create a new
|
||||
* instance of the database. If it cannot be created, throw an exception to
|
||||
* signal the failure
|
||||
*
|
||||
* @return this (self reference, allowing this to be chained in an
|
||||
* initialization call)
|
||||
* @throws SQLException if the database could be neither opened or created
|
||||
*/
|
||||
public NotesDbAdapter open() throws SQLException {
|
||||
mDbHelper = new DatabaseHelper(mCtx);
|
||||
mDb = mDbHelper.getWritableDatabase();
|
||||
return this;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
mDbHelper.close();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new note using the title and body provided. If the note is
|
||||
* successfully created return the new rowId for that note, otherwise return
|
||||
* a -1 to indicate failure.
|
||||
*
|
||||
* @param title the title of the note
|
||||
* @param body the body of the note
|
||||
* @return rowId or -1 if failed
|
||||
*/
|
||||
public long createNote(String title, String body) {
|
||||
ContentValues initialValues = new ContentValues();
|
||||
initialValues.put(KEY_TITLE, title);
|
||||
initialValues.put(KEY_BODY, body);
|
||||
|
||||
return mDb.insert(DATABASE_TABLE, null, initialValues);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the note with the given rowId
|
||||
*
|
||||
* @param rowId id of note to delete
|
||||
* @return true if deleted, false otherwise
|
||||
*/
|
||||
public boolean deleteNote(long rowId) {
|
||||
|
||||
return mDb.delete(DATABASE_TABLE, KEY_ROWID + "=" + rowId, null) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a Cursor over the list of all notes in the database
|
||||
*
|
||||
* @return Cursor over all notes
|
||||
*/
|
||||
public Cursor fetchAllNotes() {
|
||||
|
||||
return mDb.query(DATABASE_TABLE, new String[] {KEY_ROWID, KEY_TITLE,
|
||||
KEY_BODY}, null, null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a Cursor positioned at the note that matches the given rowId
|
||||
*
|
||||
* @param rowId id of note to retrieve
|
||||
* @return Cursor positioned to matching note, if found
|
||||
* @throws SQLException if note could not be found/retrieved
|
||||
*/
|
||||
public Cursor fetchNote(long rowId) throws SQLException {
|
||||
|
||||
Cursor mCursor =
|
||||
|
||||
mDb.query(true, DATABASE_TABLE, new String[] {KEY_ROWID,
|
||||
KEY_TITLE, KEY_BODY}, KEY_ROWID + "=" + rowId, null,
|
||||
null, null, null, null);
|
||||
if (mCursor != null) {
|
||||
mCursor.moveToFirst();
|
||||
}
|
||||
return mCursor;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the note using the details provided. The note to be updated is
|
||||
* specified using the rowId, and it is altered to use the title and body
|
||||
* values passed in
|
||||
*
|
||||
* @param rowId id of note to update
|
||||
* @param title value to set note title to
|
||||
* @param body value to set note body to
|
||||
* @return true if the note was successfully updated, false otherwise
|
||||
*/
|
||||
public boolean updateNote(long rowId, String title, String body) {
|
||||
ContentValues args = new ContentValues();
|
||||
args.put(KEY_TITLE, title);
|
||||
args.put(KEY_BODY, body);
|
||||
|
||||
return mDb.update(DATABASE_TABLE, args, KEY_ROWID + "=" + rowId, null) > 0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
#
|
||||
# Copyright (C) 2009 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.
|
||||
#
|
||||
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
# Only build apk if this package is added to CUSTOM_MODLUES in buildspec.mk
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
|
||||
# Only compile source java files in this apk.
|
||||
LOCAL_SRC_FILES := $(call all-java-files-under, src)
|
||||
|
||||
LOCAL_PACKAGE_NAME := Notepadv2Solution
|
||||
|
||||
# Make the app build against the current SDK
|
||||
LOCAL_SDK_VERSION := current
|
||||
|
||||
include $(BUILD_PACKAGE)
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.demo.notepad2">
|
||||
<application android:icon="@drawable/icon">
|
||||
<activity android:name=".Notepadv2" android:label="@string/app_name">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name=".NoteEdit" />
|
||||
</application>
|
||||
</manifest>
|
After Width: | Height: | Size: 6 KiB |
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical" android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/title" />
|
||||
<EditText android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"/>
|
||||
</LinearLayout>
|
||||
|
||||
<TextView android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/body" />
|
||||
<EditText android:id="@+id/body" android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:scrollbars="vertical" />
|
||||
|
||||
<Button android:id="@+id/confirm"
|
||||
android:text="@string/confirm"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</LinearLayout>
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ListView android:id="@+id/android:list"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
<TextView android:id="@+id/android:empty"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/no_notes"/>
|
||||
</LinearLayout>
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TextView android:id="@+id/text1" xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">Notepad v2</string>
|
||||
<string name="no_notes">No Notes Yet</string>
|
||||
<string name="menu_insert">Add Note</string>
|
||||
<string name="menu_delete">Delete Note</string>
|
||||
<string name="title">Title</string>
|
||||
<string name="body">Body</string>
|
||||
<string name="confirm">Confirm</string>
|
||||
<string name="edit_note">Edit Note</string>
|
||||
</resources>
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* 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.demo.notepad2;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
|
||||
public class NoteEdit extends Activity {
|
||||
|
||||
private EditText mTitleText;
|
||||
private EditText mBodyText;
|
||||
private Long mRowId;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.note_edit);
|
||||
setTitle(R.string.edit_note);
|
||||
|
||||
mTitleText = (EditText) findViewById(R.id.title);
|
||||
mBodyText = (EditText) findViewById(R.id.body);
|
||||
|
||||
Button confirmButton = (Button) findViewById(R.id.confirm);
|
||||
|
||||
mRowId = null;
|
||||
Bundle extras = getIntent().getExtras();
|
||||
if (extras != null) {
|
||||
String title = extras.getString(NotesDbAdapter.KEY_TITLE);
|
||||
String body = extras.getString(NotesDbAdapter.KEY_BODY);
|
||||
mRowId = extras.getLong(NotesDbAdapter.KEY_ROWID);
|
||||
|
||||
if (title != null) {
|
||||
mTitleText.setText(title);
|
||||
}
|
||||
if (body != null) {
|
||||
mBodyText.setText(body);
|
||||
}
|
||||
}
|
||||
|
||||
confirmButton.setOnClickListener(new View.OnClickListener() {
|
||||
|
||||
public void onClick(View view) {
|
||||
Bundle bundle = new Bundle();
|
||||
|
||||
bundle.putString(NotesDbAdapter.KEY_TITLE, mTitleText.getText().toString());
|
||||
bundle.putString(NotesDbAdapter.KEY_BODY, mBodyText.getText().toString());
|
||||
if (mRowId != null) {
|
||||
bundle.putLong(NotesDbAdapter.KEY_ROWID, mRowId);
|
||||
}
|
||||
|
||||
Intent mIntent = new Intent();
|
||||
mIntent.putExtras(bundle);
|
||||
setResult(RESULT_OK, mIntent);
|
||||
finish();
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* 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.demo.notepad2;
|
||||
|
||||
import android.app.ListActivity;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
import android.os.Bundle;
|
||||
import android.view.ContextMenu;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ContextMenu.ContextMenuInfo;
|
||||
import android.widget.ListView;
|
||||
import android.widget.SimpleCursorAdapter;
|
||||
import android.widget.AdapterView.AdapterContextMenuInfo;
|
||||
|
||||
public class Notepadv2 extends ListActivity {
|
||||
private static final int ACTIVITY_CREATE=0;
|
||||
private static final int ACTIVITY_EDIT=1;
|
||||
|
||||
private static final int INSERT_ID = Menu.FIRST;
|
||||
private static final int DELETE_ID = Menu.FIRST + 1;
|
||||
|
||||
private NotesDbAdapter mDbHelper;
|
||||
private Cursor mNotesCursor;
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.notes_list);
|
||||
mDbHelper = new NotesDbAdapter(this);
|
||||
mDbHelper.open();
|
||||
fillData();
|
||||
registerForContextMenu(getListView());
|
||||
}
|
||||
|
||||
private void fillData() {
|
||||
// Get all of the rows from the database and create the item list
|
||||
mNotesCursor = mDbHelper.fetchAllNotes();
|
||||
startManagingCursor(mNotesCursor);
|
||||
|
||||
// Create an array to specify the fields we want to display in the list (only TITLE)
|
||||
String[] from = new String[]{NotesDbAdapter.KEY_TITLE};
|
||||
|
||||
// and an array of the fields we want to bind those fields to (in this case just text1)
|
||||
int[] to = new int[]{R.id.text1};
|
||||
|
||||
// Now create a simple cursor adapter and set it to display
|
||||
SimpleCursorAdapter notes =
|
||||
new SimpleCursorAdapter(this, R.layout.notes_row, mNotesCursor, from, to);
|
||||
setListAdapter(notes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
super.onCreateOptionsMenu(menu);
|
||||
menu.add(0, INSERT_ID, 0, R.string.menu_insert);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemSelected(int featureId, MenuItem item) {
|
||||
switch(item.getItemId()) {
|
||||
case INSERT_ID:
|
||||
createNote();
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.onMenuItemSelected(featureId, item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateContextMenu(ContextMenu menu, View v,
|
||||
ContextMenuInfo menuInfo) {
|
||||
super.onCreateContextMenu(menu, v, menuInfo);
|
||||
menu.add(0, DELETE_ID, 0, R.string.menu_delete);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onContextItemSelected(MenuItem item) {
|
||||
switch(item.getItemId()) {
|
||||
case DELETE_ID:
|
||||
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
|
||||
mDbHelper.deleteNote(info.id);
|
||||
fillData();
|
||||
return true;
|
||||
}
|
||||
return super.onContextItemSelected(item);
|
||||
}
|
||||
|
||||
private void createNote() {
|
||||
Intent i = new Intent(this, NoteEdit.class);
|
||||
startActivityForResult(i, ACTIVITY_CREATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onListItemClick(ListView l, View v, int position, long id) {
|
||||
super.onListItemClick(l, v, position, id);
|
||||
Cursor c = mNotesCursor;
|
||||
c.moveToPosition(position);
|
||||
Intent i = new Intent(this, NoteEdit.class);
|
||||
i.putExtra(NotesDbAdapter.KEY_ROWID, id);
|
||||
i.putExtra(NotesDbAdapter.KEY_TITLE, c.getString(
|
||||
c.getColumnIndexOrThrow(NotesDbAdapter.KEY_TITLE)));
|
||||
i.putExtra(NotesDbAdapter.KEY_BODY, c.getString(
|
||||
c.getColumnIndexOrThrow(NotesDbAdapter.KEY_BODY)));
|
||||
startActivityForResult(i, ACTIVITY_EDIT);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
|
||||
super.onActivityResult(requestCode, resultCode, intent);
|
||||
Bundle extras = intent.getExtras();
|
||||
switch(requestCode) {
|
||||
case ACTIVITY_CREATE:
|
||||
String title = extras.getString(NotesDbAdapter.KEY_TITLE);
|
||||
String body = extras.getString(NotesDbAdapter.KEY_BODY);
|
||||
mDbHelper.createNote(title, body);
|
||||
fillData();
|
||||
break;
|
||||
case ACTIVITY_EDIT:
|
||||
Long rowId = extras.getLong(NotesDbAdapter.KEY_ROWID);
|
||||
if (rowId != null) {
|
||||
String editTitle = extras.getString(NotesDbAdapter.KEY_TITLE);
|
||||
String editBody = extras.getString(NotesDbAdapter.KEY_BODY);
|
||||
mDbHelper.updateNote(rowId, editTitle, editBody);
|
||||
}
|
||||
fillData();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* 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.demo.notepad2;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.SQLException;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* Simple notes database access helper class. Defines the basic CRUD operations
|
||||
* for the notepad example, and gives the ability to list all notes as well as
|
||||
* retrieve or modify a specific note.
|
||||
*
|
||||
* This has been improved from the first version of this tutorial through the
|
||||
* addition of better error handling and also using returning a Cursor instead
|
||||
* of using a collection of inner classes (which is less scalable and not
|
||||
* recommended).
|
||||
*/
|
||||
public class NotesDbAdapter {
|
||||
|
||||
public static final String KEY_TITLE = "title";
|
||||
public static final String KEY_BODY = "body";
|
||||
public static final String KEY_ROWID = "_id";
|
||||
|
||||
private static final String TAG = "NotesDbAdapter";
|
||||
private DatabaseHelper mDbHelper;
|
||||
private SQLiteDatabase mDb;
|
||||
|
||||
/**
|
||||
* Database creation sql statement
|
||||
*/
|
||||
private static final String DATABASE_CREATE =
|
||||
"create table notes (_id integer primary key autoincrement, "
|
||||
+ "title text not null, body text not null);";
|
||||
|
||||
private static final String DATABASE_NAME = "data";
|
||||
private static final String DATABASE_TABLE = "notes";
|
||||
private static final int DATABASE_VERSION = 2;
|
||||
|
||||
private final Context mCtx;
|
||||
|
||||
private static class DatabaseHelper extends SQLiteOpenHelper {
|
||||
|
||||
DatabaseHelper(Context context) {
|
||||
super(context, DATABASE_NAME, null, DATABASE_VERSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
|
||||
db.execSQL(DATABASE_CREATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
|
||||
+ newVersion + ", which will destroy all old data");
|
||||
db.execSQL("DROP TABLE IF EXISTS notes");
|
||||
onCreate(db);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor - takes the context to allow the database to be
|
||||
* opened/created
|
||||
*
|
||||
* @param ctx the Context within which to work
|
||||
*/
|
||||
public NotesDbAdapter(Context ctx) {
|
||||
this.mCtx = ctx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the notes database. If it cannot be opened, try to create a new
|
||||
* instance of the database. If it cannot be created, throw an exception to
|
||||
* signal the failure
|
||||
*
|
||||
* @return this (self reference, allowing this to be chained in an
|
||||
* initialization call)
|
||||
* @throws SQLException if the database could be neither opened or created
|
||||
*/
|
||||
public NotesDbAdapter open() throws SQLException {
|
||||
mDbHelper = new DatabaseHelper(mCtx);
|
||||
mDb = mDbHelper.getWritableDatabase();
|
||||
return this;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
mDbHelper.close();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new note using the title and body provided. If the note is
|
||||
* successfully created return the new rowId for that note, otherwise return
|
||||
* a -1 to indicate failure.
|
||||
*
|
||||
* @param title the title of the note
|
||||
* @param body the body of the note
|
||||
* @return rowId or -1 if failed
|
||||
*/
|
||||
public long createNote(String title, String body) {
|
||||
ContentValues initialValues = new ContentValues();
|
||||
initialValues.put(KEY_TITLE, title);
|
||||
initialValues.put(KEY_BODY, body);
|
||||
|
||||
return mDb.insert(DATABASE_TABLE, null, initialValues);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the note with the given rowId
|
||||
*
|
||||
* @param rowId id of note to delete
|
||||
* @return true if deleted, false otherwise
|
||||
*/
|
||||
public boolean deleteNote(long rowId) {
|
||||
|
||||
return mDb.delete(DATABASE_TABLE, KEY_ROWID + "=" + rowId, null) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a Cursor over the list of all notes in the database
|
||||
*
|
||||
* @return Cursor over all notes
|
||||
*/
|
||||
public Cursor fetchAllNotes() {
|
||||
|
||||
return mDb.query(DATABASE_TABLE, new String[] {KEY_ROWID, KEY_TITLE,
|
||||
KEY_BODY}, null, null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a Cursor positioned at the note that matches the given rowId
|
||||
*
|
||||
* @param rowId id of note to retrieve
|
||||
* @return Cursor positioned to matching note, if found
|
||||
* @throws SQLException if note could not be found/retrieved
|
||||
*/
|
||||
public Cursor fetchNote(long rowId) throws SQLException {
|
||||
|
||||
Cursor mCursor =
|
||||
|
||||
mDb.query(true, DATABASE_TABLE, new String[] {KEY_ROWID,
|
||||
KEY_TITLE, KEY_BODY}, KEY_ROWID + "=" + rowId, null,
|
||||
null, null, null, null);
|
||||
if (mCursor != null) {
|
||||
mCursor.moveToFirst();
|
||||
}
|
||||
return mCursor;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the note using the details provided. The note to be updated is
|
||||
* specified using the rowId, and it is altered to use the title and body
|
||||
* values passed in
|
||||
*
|
||||
* @param rowId id of note to update
|
||||
* @param title value to set note title to
|
||||
* @param body value to set note body to
|
||||
* @return true if the note was successfully updated, false otherwise
|
||||
*/
|
||||
public boolean updateNote(long rowId, String title, String body) {
|
||||
ContentValues args = new ContentValues();
|
||||
args.put(KEY_TITLE, title);
|
||||
args.put(KEY_BODY, body);
|
||||
|
||||
return mDb.update(DATABASE_TABLE, args, KEY_ROWID + "=" + rowId, null) > 0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
#
|
||||
# Copyright (C) 2009 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.
|
||||
#
|
||||
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
# Only build apk if this package is added to CUSTOM_MODLUES in buildspec.mk
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
|
||||
# Only compile source java files in this apk.
|
||||
LOCAL_SRC_FILES := $(call all-java-files-under, src)
|
||||
|
||||
LOCAL_PACKAGE_NAME := Notepadv3
|
||||
|
||||
# Make the app build against the current SDK
|
||||
LOCAL_SDK_VERSION := current
|
||||
|
||||
include $(BUILD_PACKAGE)
|
12
android/development/tutorials/NotepadCodeLab/Notepadv3/AndroidManifest.xml
Executable file
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.demo.notepad3">
|
||||
<application android:icon="@drawable/icon">
|
||||
<activity android:name=".Notepadv3" android:label="@string/app_name">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name=".NoteEdit" />
|
||||
</application>
|
||||
</manifest>
|
BIN
android/development/tutorials/NotepadCodeLab/Notepadv3/res/drawable/icon.png
Executable file
After Width: | Height: | Size: 6 KiB |
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical" android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/title" />
|
||||
<EditText android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"/>
|
||||
</LinearLayout>
|
||||
|
||||
<TextView android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/body" />
|
||||
<EditText android:id="@+id/body" android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:scrollbars="vertical" />
|
||||
|
||||
<Button android:id="@+id/confirm"
|
||||
android:text="@string/confirm"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</LinearLayout>
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ListView android:id="@+id/android:list"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
<TextView android:id="@+id/android:empty"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/no_notes"/>
|
||||
</LinearLayout>
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TextView android:id="@+id/text1" xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">Notepad v3</string>
|
||||
<string name="no_notes">No Notes Yet</string>
|
||||
<string name="menu_insert">Add Note</string>
|
||||
<string name="menu_delete">Delete Note</string>
|
||||
<string name="title">Title</string>
|
||||
<string name="body">Body</string>
|
||||
<string name="confirm">Confirm</string>
|
||||
<string name="edit_note">Edit Note</string>
|
||||
</resources>
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* 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.demo.notepad3;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
|
||||
public class NoteEdit extends Activity {
|
||||
|
||||
private EditText mTitleText;
|
||||
private EditText mBodyText;
|
||||
private Long mRowId;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.note_edit);
|
||||
setTitle(R.string.edit_note);
|
||||
|
||||
mTitleText = (EditText) findViewById(R.id.title);
|
||||
mBodyText = (EditText) findViewById(R.id.body);
|
||||
|
||||
Button confirmButton = (Button) findViewById(R.id.confirm);
|
||||
|
||||
mRowId = null;
|
||||
Bundle extras = getIntent().getExtras();
|
||||
if (extras != null) {
|
||||
String title = extras.getString(NotesDbAdapter.KEY_TITLE);
|
||||
String body = extras.getString(NotesDbAdapter.KEY_BODY);
|
||||
mRowId = extras.getLong(NotesDbAdapter.KEY_ROWID);
|
||||
|
||||
if (title != null) {
|
||||
mTitleText.setText(title);
|
||||
}
|
||||
if (body != null) {
|
||||
mBodyText.setText(body);
|
||||
}
|
||||
}
|
||||
|
||||
confirmButton.setOnClickListener(new View.OnClickListener() {
|
||||
|
||||
public void onClick(View view) {
|
||||
Bundle bundle = new Bundle();
|
||||
|
||||
bundle.putString(NotesDbAdapter.KEY_TITLE, mTitleText.getText().toString());
|
||||
bundle.putString(NotesDbAdapter.KEY_BODY, mBodyText.getText().toString());
|
||||
if (mRowId != null) {
|
||||
bundle.putLong(NotesDbAdapter.KEY_ROWID, mRowId);
|
||||
}
|
||||
|
||||
Intent mIntent = new Intent();
|
||||
mIntent.putExtras(bundle);
|
||||
setResult(RESULT_OK, mIntent);
|
||||
finish();
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* 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.demo.notepad3;
|
||||
|
||||
import android.app.ListActivity;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
import android.os.Bundle;
|
||||
import android.view.ContextMenu;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ContextMenu.ContextMenuInfo;
|
||||
import android.widget.ListView;
|
||||
import android.widget.SimpleCursorAdapter;
|
||||
import android.widget.AdapterView.AdapterContextMenuInfo;
|
||||
|
||||
public class Notepadv3 extends ListActivity {
|
||||
private static final int ACTIVITY_CREATE=0;
|
||||
private static final int ACTIVITY_EDIT=1;
|
||||
|
||||
private static final int INSERT_ID = Menu.FIRST;
|
||||
private static final int DELETE_ID = Menu.FIRST + 1;
|
||||
|
||||
private NotesDbAdapter mDbHelper;
|
||||
private Cursor mNotesCursor;
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.notes_list);
|
||||
mDbHelper = new NotesDbAdapter(this);
|
||||
mDbHelper.open();
|
||||
fillData();
|
||||
registerForContextMenu(getListView());
|
||||
}
|
||||
|
||||
private void fillData() {
|
||||
// Get all of the rows from the database and create the item list
|
||||
mNotesCursor = mDbHelper.fetchAllNotes();
|
||||
startManagingCursor(mNotesCursor);
|
||||
|
||||
// Create an array to specify the fields we want to display in the list (only TITLE)
|
||||
String[] from = new String[]{NotesDbAdapter.KEY_TITLE};
|
||||
|
||||
// and an array of the fields we want to bind those fields to (in this case just text1)
|
||||
int[] to = new int[]{R.id.text1};
|
||||
|
||||
// Now create a simple cursor adapter and set it to display
|
||||
SimpleCursorAdapter notes =
|
||||
new SimpleCursorAdapter(this, R.layout.notes_row, mNotesCursor, from, to);
|
||||
setListAdapter(notes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
super.onCreateOptionsMenu(menu);
|
||||
menu.add(0, INSERT_ID, 0, R.string.menu_insert);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemSelected(int featureId, MenuItem item) {
|
||||
switch(item.getItemId()) {
|
||||
case INSERT_ID:
|
||||
createNote();
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.onMenuItemSelected(featureId, item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateContextMenu(ContextMenu menu, View v,
|
||||
ContextMenuInfo menuInfo) {
|
||||
super.onCreateContextMenu(menu, v, menuInfo);
|
||||
menu.add(0, DELETE_ID, 0, R.string.menu_delete);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onContextItemSelected(MenuItem item) {
|
||||
switch(item.getItemId()) {
|
||||
case DELETE_ID:
|
||||
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
|
||||
mDbHelper.deleteNote(info.id);
|
||||
fillData();
|
||||
return true;
|
||||
}
|
||||
return super.onContextItemSelected(item);
|
||||
}
|
||||
|
||||
private void createNote() {
|
||||
Intent i = new Intent(this, NoteEdit.class);
|
||||
startActivityForResult(i, ACTIVITY_CREATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onListItemClick(ListView l, View v, int position, long id) {
|
||||
super.onListItemClick(l, v, position, id);
|
||||
Cursor c = mNotesCursor;
|
||||
c.moveToPosition(position);
|
||||
Intent i = new Intent(this, NoteEdit.class);
|
||||
i.putExtra(NotesDbAdapter.KEY_ROWID, id);
|
||||
i.putExtra(NotesDbAdapter.KEY_TITLE, c.getString(
|
||||
c.getColumnIndexOrThrow(NotesDbAdapter.KEY_TITLE)));
|
||||
i.putExtra(NotesDbAdapter.KEY_BODY, c.getString(
|
||||
c.getColumnIndexOrThrow(NotesDbAdapter.KEY_BODY)));
|
||||
startActivityForResult(i, ACTIVITY_EDIT);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
|
||||
super.onActivityResult(requestCode, resultCode, intent);
|
||||
Bundle extras = intent.getExtras();
|
||||
switch(requestCode) {
|
||||
case ACTIVITY_CREATE:
|
||||
String title = extras.getString(NotesDbAdapter.KEY_TITLE);
|
||||
String body = extras.getString(NotesDbAdapter.KEY_BODY);
|
||||
mDbHelper.createNote(title, body);
|
||||
fillData();
|
||||
break;
|
||||
case ACTIVITY_EDIT:
|
||||
Long rowId = extras.getLong(NotesDbAdapter.KEY_ROWID);
|
||||
if (rowId != null) {
|
||||
String editTitle = extras.getString(NotesDbAdapter.KEY_TITLE);
|
||||
String editBody = extras.getString(NotesDbAdapter.KEY_BODY);
|
||||
mDbHelper.updateNote(rowId, editTitle, editBody);
|
||||
}
|
||||
fillData();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* 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.demo.notepad3;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.SQLException;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* Simple notes database access helper class. Defines the basic CRUD operations
|
||||
* for the notepad example, and gives the ability to list all notes as well as
|
||||
* retrieve or modify a specific note.
|
||||
*
|
||||
* This has been improved from the first version of this tutorial through the
|
||||
* addition of better error handling and also using returning a Cursor instead
|
||||
* of using a collection of inner classes (which is less scalable and not
|
||||
* recommended).
|
||||
*/
|
||||
public class NotesDbAdapter {
|
||||
|
||||
public static final String KEY_TITLE = "title";
|
||||
public static final String KEY_BODY = "body";
|
||||
public static final String KEY_ROWID = "_id";
|
||||
|
||||
private static final String TAG = "NotesDbAdapter";
|
||||
private DatabaseHelper mDbHelper;
|
||||
private SQLiteDatabase mDb;
|
||||
|
||||
/**
|
||||
* Database creation sql statement
|
||||
*/
|
||||
private static final String DATABASE_CREATE =
|
||||
"create table notes (_id integer primary key autoincrement, "
|
||||
+ "title text not null, body text not null);";
|
||||
|
||||
private static final String DATABASE_NAME = "data";
|
||||
private static final String DATABASE_TABLE = "notes";
|
||||
private static final int DATABASE_VERSION = 2;
|
||||
|
||||
private final Context mCtx;
|
||||
|
||||
private static class DatabaseHelper extends SQLiteOpenHelper {
|
||||
|
||||
DatabaseHelper(Context context) {
|
||||
super(context, DATABASE_NAME, null, DATABASE_VERSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
|
||||
db.execSQL(DATABASE_CREATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
|
||||
+ newVersion + ", which will destroy all old data");
|
||||
db.execSQL("DROP TABLE IF EXISTS notes");
|
||||
onCreate(db);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor - takes the context to allow the database to be
|
||||
* opened/created
|
||||
*
|
||||
* @param ctx the Context within which to work
|
||||
*/
|
||||
public NotesDbAdapter(Context ctx) {
|
||||
this.mCtx = ctx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the notes database. If it cannot be opened, try to create a new
|
||||
* instance of the database. If it cannot be created, throw an exception to
|
||||
* signal the failure
|
||||
*
|
||||
* @return this (self reference, allowing this to be chained in an
|
||||
* initialization call)
|
||||
* @throws SQLException if the database could be neither opened or created
|
||||
*/
|
||||
public NotesDbAdapter open() throws SQLException {
|
||||
mDbHelper = new DatabaseHelper(mCtx);
|
||||
mDb = mDbHelper.getWritableDatabase();
|
||||
return this;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
mDbHelper.close();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new note using the title and body provided. If the note is
|
||||
* successfully created return the new rowId for that note, otherwise return
|
||||
* a -1 to indicate failure.
|
||||
*
|
||||
* @param title the title of the note
|
||||
* @param body the body of the note
|
||||
* @return rowId or -1 if failed
|
||||
*/
|
||||
public long createNote(String title, String body) {
|
||||
ContentValues initialValues = new ContentValues();
|
||||
initialValues.put(KEY_TITLE, title);
|
||||
initialValues.put(KEY_BODY, body);
|
||||
|
||||
return mDb.insert(DATABASE_TABLE, null, initialValues);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the note with the given rowId
|
||||
*
|
||||
* @param rowId id of note to delete
|
||||
* @return true if deleted, false otherwise
|
||||
*/
|
||||
public boolean deleteNote(long rowId) {
|
||||
|
||||
return mDb.delete(DATABASE_TABLE, KEY_ROWID + "=" + rowId, null) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a Cursor over the list of all notes in the database
|
||||
*
|
||||
* @return Cursor over all notes
|
||||
*/
|
||||
public Cursor fetchAllNotes() {
|
||||
|
||||
return mDb.query(DATABASE_TABLE, new String[] {KEY_ROWID, KEY_TITLE,
|
||||
KEY_BODY}, null, null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a Cursor positioned at the note that matches the given rowId
|
||||
*
|
||||
* @param rowId id of note to retrieve
|
||||
* @return Cursor positioned to matching note, if found
|
||||
* @throws SQLException if note could not be found/retrieved
|
||||
*/
|
||||
public Cursor fetchNote(long rowId) throws SQLException {
|
||||
|
||||
Cursor mCursor =
|
||||
|
||||
mDb.query(true, DATABASE_TABLE, new String[] {KEY_ROWID,
|
||||
KEY_TITLE, KEY_BODY}, KEY_ROWID + "=" + rowId, null,
|
||||
null, null, null, null);
|
||||
if (mCursor != null) {
|
||||
mCursor.moveToFirst();
|
||||
}
|
||||
return mCursor;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the note using the details provided. The note to be updated is
|
||||
* specified using the rowId, and it is altered to use the title and body
|
||||
* values passed in
|
||||
*
|
||||
* @param rowId id of note to update
|
||||
* @param title value to set note title to
|
||||
* @param body value to set note body to
|
||||
* @return true if the note was successfully updated, false otherwise
|
||||
*/
|
||||
public boolean updateNote(long rowId, String title, String body) {
|
||||
ContentValues args = new ContentValues();
|
||||
args.put(KEY_TITLE, title);
|
||||
args.put(KEY_BODY, body);
|
||||
|
||||
return mDb.update(DATABASE_TABLE, args, KEY_ROWID + "=" + rowId, null) > 0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
#
|
||||
# Copyright (C) 2009 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.
|
||||
#
|
||||
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
# Only build apk if this package is added to CUSTOM_MODLUES in buildspec.mk
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
|
||||
# Only compile source java files in this apk.
|
||||
LOCAL_SRC_FILES := $(call all-java-files-under, src)
|
||||
|
||||
LOCAL_PACKAGE_NAME := Notepadv3Solution
|
||||
|
||||
# Make the app build against the current SDK
|
||||
LOCAL_SDK_VERSION := current
|
||||
|
||||
include $(BUILD_PACKAGE)
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.demo.notepad3">
|
||||
<application android:icon="@drawable/icon">
|
||||
<activity android:name=".Notepadv3" android:label="@string/app_name">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name=".NoteEdit" />
|
||||
</application>
|
||||
</manifest>
|
After Width: | Height: | Size: 6 KiB |
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical" android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/title" />
|
||||
<EditText android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"/>
|
||||
</LinearLayout>
|
||||
|
||||
<TextView android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/body" />
|
||||
<EditText android:id="@+id/body" android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:scrollbars="vertical" />
|
||||
|
||||
<Button android:id="@+id/confirm"
|
||||
android:text="@string/confirm"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</LinearLayout>
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ListView android:id="@+id/android:list"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
<TextView android:id="@+id/android:empty"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/no_notes"/>
|
||||
</LinearLayout>
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TextView android:id="@+id/text1" xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">Notepad v3</string>
|
||||
<string name="no_notes">No Notes Yet</string>
|
||||
<string name="menu_insert">Add Note</string>
|
||||
<string name="menu_delete">Delete Note</string>
|
||||
<string name="title">Title</string>
|
||||
<string name="body">Body</string>
|
||||
<string name="confirm">Confirm</string>
|
||||
<string name="edit_note">Edit Note</string>
|
||||
</resources>
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* 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.demo.notepad3;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.database.Cursor;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
|
||||
public class NoteEdit extends Activity {
|
||||
|
||||
private EditText mTitleText;
|
||||
private EditText mBodyText;
|
||||
private Long mRowId;
|
||||
private NotesDbAdapter mDbHelper;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mDbHelper = new NotesDbAdapter(this);
|
||||
mDbHelper.open();
|
||||
|
||||
setContentView(R.layout.note_edit);
|
||||
setTitle(R.string.edit_note);
|
||||
|
||||
mTitleText = (EditText) findViewById(R.id.title);
|
||||
mBodyText = (EditText) findViewById(R.id.body);
|
||||
|
||||
Button confirmButton = (Button) findViewById(R.id.confirm);
|
||||
|
||||
mRowId = (savedInstanceState == null) ? null :
|
||||
(Long) savedInstanceState.getSerializable(NotesDbAdapter.KEY_ROWID);
|
||||
if (mRowId == null) {
|
||||
Bundle extras = getIntent().getExtras();
|
||||
mRowId = extras != null ? extras.getLong(NotesDbAdapter.KEY_ROWID)
|
||||
: null;
|
||||
}
|
||||
|
||||
populateFields();
|
||||
|
||||
confirmButton.setOnClickListener(new View.OnClickListener() {
|
||||
|
||||
public void onClick(View view) {
|
||||
setResult(RESULT_OK);
|
||||
finish();
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
private void populateFields() {
|
||||
if (mRowId != null) {
|
||||
Cursor note = mDbHelper.fetchNote(mRowId);
|
||||
startManagingCursor(note);
|
||||
mTitleText.setText(note.getString(
|
||||
note.getColumnIndexOrThrow(NotesDbAdapter.KEY_TITLE)));
|
||||
mBodyText.setText(note.getString(
|
||||
note.getColumnIndexOrThrow(NotesDbAdapter.KEY_BODY)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
saveState();
|
||||
outState.putSerializable(NotesDbAdapter.KEY_ROWID, mRowId);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
saveState();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
populateFields();
|
||||
}
|
||||
|
||||
private void saveState() {
|
||||
String title = mTitleText.getText().toString();
|
||||
String body = mBodyText.getText().toString();
|
||||
|
||||
if (mRowId == null) {
|
||||
long id = mDbHelper.createNote(title, body);
|
||||
if (id > 0) {
|
||||
mRowId = id;
|
||||
}
|
||||
} else {
|
||||
mDbHelper.updateNote(mRowId, title, body);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* 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.demo.notepad3;
|
||||
|
||||
import android.app.ListActivity;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
import android.os.Bundle;
|
||||
import android.view.ContextMenu;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ContextMenu.ContextMenuInfo;
|
||||
import android.widget.ListView;
|
||||
import android.widget.SimpleCursorAdapter;
|
||||
import android.widget.AdapterView.AdapterContextMenuInfo;
|
||||
|
||||
public class Notepadv3 extends ListActivity {
|
||||
private static final int ACTIVITY_CREATE=0;
|
||||
private static final int ACTIVITY_EDIT=1;
|
||||
|
||||
private static final int INSERT_ID = Menu.FIRST;
|
||||
private static final int DELETE_ID = Menu.FIRST + 1;
|
||||
|
||||
private NotesDbAdapter mDbHelper;
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.notes_list);
|
||||
mDbHelper = new NotesDbAdapter(this);
|
||||
mDbHelper.open();
|
||||
fillData();
|
||||
registerForContextMenu(getListView());
|
||||
}
|
||||
|
||||
private void fillData() {
|
||||
Cursor notesCursor = mDbHelper.fetchAllNotes();
|
||||
startManagingCursor(notesCursor);
|
||||
|
||||
// Create an array to specify the fields we want to display in the list (only TITLE)
|
||||
String[] from = new String[]{NotesDbAdapter.KEY_TITLE};
|
||||
|
||||
// and an array of the fields we want to bind those fields to (in this case just text1)
|
||||
int[] to = new int[]{R.id.text1};
|
||||
|
||||
// Now create a simple cursor adapter and set it to display
|
||||
SimpleCursorAdapter notes =
|
||||
new SimpleCursorAdapter(this, R.layout.notes_row, notesCursor, from, to);
|
||||
setListAdapter(notes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
super.onCreateOptionsMenu(menu);
|
||||
menu.add(0, INSERT_ID, 0, R.string.menu_insert);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemSelected(int featureId, MenuItem item) {
|
||||
switch(item.getItemId()) {
|
||||
case INSERT_ID:
|
||||
createNote();
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.onMenuItemSelected(featureId, item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateContextMenu(ContextMenu menu, View v,
|
||||
ContextMenuInfo menuInfo) {
|
||||
super.onCreateContextMenu(menu, v, menuInfo);
|
||||
menu.add(0, DELETE_ID, 0, R.string.menu_delete);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onContextItemSelected(MenuItem item) {
|
||||
switch(item.getItemId()) {
|
||||
case DELETE_ID:
|
||||
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
|
||||
mDbHelper.deleteNote(info.id);
|
||||
fillData();
|
||||
return true;
|
||||
}
|
||||
return super.onContextItemSelected(item);
|
||||
}
|
||||
|
||||
private void createNote() {
|
||||
Intent i = new Intent(this, NoteEdit.class);
|
||||
startActivityForResult(i, ACTIVITY_CREATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onListItemClick(ListView l, View v, int position, long id) {
|
||||
super.onListItemClick(l, v, position, id);
|
||||
Intent i = new Intent(this, NoteEdit.class);
|
||||
i.putExtra(NotesDbAdapter.KEY_ROWID, id);
|
||||
startActivityForResult(i, ACTIVITY_EDIT);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
|
||||
super.onActivityResult(requestCode, resultCode, intent);
|
||||
fillData();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* 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.demo.notepad3;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.SQLException;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* Simple notes database access helper class. Defines the basic CRUD operations
|
||||
* for the notepad example, and gives the ability to list all notes as well as
|
||||
* retrieve or modify a specific note.
|
||||
*
|
||||
* This has been improved from the first version of this tutorial through the
|
||||
* addition of better error handling and also using returning a Cursor instead
|
||||
* of using a collection of inner classes (which is less scalable and not
|
||||
* recommended).
|
||||
*/
|
||||
public class NotesDbAdapter {
|
||||
|
||||
public static final String KEY_TITLE = "title";
|
||||
public static final String KEY_BODY = "body";
|
||||
public static final String KEY_ROWID = "_id";
|
||||
|
||||
private static final String TAG = "NotesDbAdapter";
|
||||
private DatabaseHelper mDbHelper;
|
||||
private SQLiteDatabase mDb;
|
||||
|
||||
/**
|
||||
* Database creation sql statement
|
||||
*/
|
||||
private static final String DATABASE_CREATE =
|
||||
"create table notes (_id integer primary key autoincrement, "
|
||||
+ "title text not null, body text not null);";
|
||||
|
||||
private static final String DATABASE_NAME = "data";
|
||||
private static final String DATABASE_TABLE = "notes";
|
||||
private static final int DATABASE_VERSION = 2;
|
||||
|
||||
private final Context mCtx;
|
||||
|
||||
private static class DatabaseHelper extends SQLiteOpenHelper {
|
||||
|
||||
DatabaseHelper(Context context) {
|
||||
super(context, DATABASE_NAME, null, DATABASE_VERSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
|
||||
db.execSQL(DATABASE_CREATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
|
||||
+ newVersion + ", which will destroy all old data");
|
||||
db.execSQL("DROP TABLE IF EXISTS notes");
|
||||
onCreate(db);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor - takes the context to allow the database to be
|
||||
* opened/created
|
||||
*
|
||||
* @param ctx the Context within which to work
|
||||
*/
|
||||
public NotesDbAdapter(Context ctx) {
|
||||
this.mCtx = ctx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the notes database. If it cannot be opened, try to create a new
|
||||
* instance of the database. If it cannot be created, throw an exception to
|
||||
* signal the failure
|
||||
*
|
||||
* @return this (self reference, allowing this to be chained in an
|
||||
* initialization call)
|
||||
* @throws SQLException if the database could be neither opened or created
|
||||
*/
|
||||
public NotesDbAdapter open() throws SQLException {
|
||||
mDbHelper = new DatabaseHelper(mCtx);
|
||||
mDb = mDbHelper.getWritableDatabase();
|
||||
return this;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
mDbHelper.close();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new note using the title and body provided. If the note is
|
||||
* successfully created return the new rowId for that note, otherwise return
|
||||
* a -1 to indicate failure.
|
||||
*
|
||||
* @param title the title of the note
|
||||
* @param body the body of the note
|
||||
* @return rowId or -1 if failed
|
||||
*/
|
||||
public long createNote(String title, String body) {
|
||||
ContentValues initialValues = new ContentValues();
|
||||
initialValues.put(KEY_TITLE, title);
|
||||
initialValues.put(KEY_BODY, body);
|
||||
|
||||
return mDb.insert(DATABASE_TABLE, null, initialValues);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the note with the given rowId
|
||||
*
|
||||
* @param rowId id of note to delete
|
||||
* @return true if deleted, false otherwise
|
||||
*/
|
||||
public boolean deleteNote(long rowId) {
|
||||
|
||||
return mDb.delete(DATABASE_TABLE, KEY_ROWID + "=" + rowId, null) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a Cursor over the list of all notes in the database
|
||||
*
|
||||
* @return Cursor over all notes
|
||||
*/
|
||||
public Cursor fetchAllNotes() {
|
||||
|
||||
return mDb.query(DATABASE_TABLE, new String[] {KEY_ROWID, KEY_TITLE,
|
||||
KEY_BODY}, null, null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a Cursor positioned at the note that matches the given rowId
|
||||
*
|
||||
* @param rowId id of note to retrieve
|
||||
* @return Cursor positioned to matching note, if found
|
||||
* @throws SQLException if note could not be found/retrieved
|
||||
*/
|
||||
public Cursor fetchNote(long rowId) throws SQLException {
|
||||
|
||||
Cursor mCursor =
|
||||
|
||||
mDb.query(true, DATABASE_TABLE, new String[] {KEY_ROWID,
|
||||
KEY_TITLE, KEY_BODY}, KEY_ROWID + "=" + rowId, null,
|
||||
null, null, null, null);
|
||||
if (mCursor != null) {
|
||||
mCursor.moveToFirst();
|
||||
}
|
||||
return mCursor;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the note using the details provided. The note to be updated is
|
||||
* specified using the rowId, and it is altered to use the title and body
|
||||
* values passed in
|
||||
*
|
||||
* @param rowId id of note to update
|
||||
* @param title value to set note title to
|
||||
* @param body value to set note body to
|
||||
* @return true if the note was successfully updated, false otherwise
|
||||
*/
|
||||
public boolean updateNote(long rowId, String title, String body) {
|
||||
ContentValues args = new ContentValues();
|
||||
args.put(KEY_TITLE, title);
|
||||
args.put(KEY_BODY, body);
|
||||
|
||||
return mDb.update(DATABASE_TABLE, args, KEY_ROWID + "=" + rowId, null) > 0;
|
||||
}
|
||||
}
|
28
android/development/tutorials/ReverseDebug/Android.mk
Normal file
|
@ -0,0 +1,28 @@
|
|||
# Copyright (C) 2013 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.
|
||||
|
||||
ifneq ($(filter arm ,$(TARGET_ARCH)),)
|
||||
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES:= main.c.arm
|
||||
|
||||
LOCAL_CFLAGS := -std=gnu99 -O0
|
||||
|
||||
LOCAL_MODULE := reverse_debug
|
||||
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
||||
endif # arm in TARGET_ARCH
|
137
android/development/tutorials/ReverseDebug/README.txt
Normal file
|
@ -0,0 +1,137 @@
|
|||
This is a tutorial/unittest for gdb's reverse debugging feature. It is a new
|
||||
feature that allows users to take a snapshot of the machine state, continue
|
||||
until a later stage of the program, then return to the previously recorded
|
||||
state and execute again. An ideal usage case is to help track down the reason
|
||||
why a memory location is clobbered.
|
||||
|
||||
In the sample below, the "clobber" function trashes a neighboring variable "p"
|
||||
on the stack next to the "values" variable, and the program will crash at
|
||||
line 42 when "p" is being dereferenced.
|
||||
|
||||
18 #include <stdio.h>
|
||||
19 #include <stdlib.h>
|
||||
20
|
||||
21 #define ARRAY_LENGTH 10
|
||||
22
|
||||
23 int flag;
|
||||
24
|
||||
25 void clobber(int *array, int size) {
|
||||
26 /* Make sure it clobbers something. */
|
||||
27 array[-1] = 0x123;
|
||||
28 array[size] = 0x123;
|
||||
29 }
|
||||
30
|
||||
31 int main(void) {
|
||||
32 int values[ARRAY_LENGTH];
|
||||
33 int *p = (int *) malloc(sizeof(int));
|
||||
34 *p = 10;
|
||||
35
|
||||
36 while (!flag) {
|
||||
37 sleep(1);
|
||||
38 }
|
||||
39
|
||||
40 /* Set a breakpint here: "b main.c:41" */
|
||||
41 clobber(values, ARRAY_LENGTH);
|
||||
42 printf("*p = %d\n", *p);
|
||||
43 free(p);
|
||||
44
|
||||
45 return 0;
|
||||
46 }
|
||||
|
||||
The test program can be built/installed on the device by doing:
|
||||
|
||||
> mmm development/tutorials/ReverseDebug
|
||||
> adb sync
|
||||
> adb shell reverse_debug
|
||||
|
||||
In another window the following command can be used to attach to the running
|
||||
program:
|
||||
|
||||
> gdbclient reverse_debug :5039 reverse_debug
|
||||
[1] 12802
|
||||
Attached; pid = 1842
|
||||
Listening on port 5039
|
||||
GNU gdb (GDB) 7.6
|
||||
Copyright (C) 2013 Free Software Foundation, Inc.
|
||||
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
|
||||
This is free software: you are free to change and redistribute it.
|
||||
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
|
||||
and "show warranty" for details.
|
||||
This GDB was configured as "--host=x86_64-linux-gnu --target=arm-linux-android".
|
||||
For bug reporting instructions, please see:
|
||||
<http://source.android.com/source/report-bugs.html>...
|
||||
Reading symbols from /usr/local/google/work/master/out/target/product/manta/symbols/system/bin/reverse_debug...done.
|
||||
Remote debugging from host 127.0.0.1
|
||||
nanosleep () at bionic/libc/arch-arm/syscalls/nanosleep.S:10
|
||||
10 mov r7, ip
|
||||
|
||||
====
|
||||
|
||||
Now set a breakpoint on line 41 and set flag to 1 so that the program can
|
||||
continue.
|
||||
|
||||
(gdb) b main.c:41
|
||||
Breakpoint 1 at 0xb6f174a8: file development/tutorials/ReverseDebug/main.c, line 41.
|
||||
(gdb) p flag=1
|
||||
$1 = 1
|
||||
(gdb) c
|
||||
Continuing.
|
||||
|
||||
====
|
||||
|
||||
Now try the new "record" command to take a snapshot of the machine state.
|
||||
|
||||
Breakpoint 1, main () at development/tutorials/ReverseDebug/main.c:41
|
||||
41 clobber(values, ARRAY_LENGTH);
|
||||
(gdb) record
|
||||
(gdb) c
|
||||
Continuing.
|
||||
|
||||
====
|
||||
|
||||
Now the program crashes as expected as "p" has been clobbered. The
|
||||
"reverse-continue" command will bring the program back to line 41 and let you
|
||||
replay each instruction from there.
|
||||
|
||||
Program received signal SIGSEGV, Segmentation fault.
|
||||
0xb6f174bc in main () at development/tutorials/ReverseDebug/main.c:42
|
||||
42 printf("*p = %d\n", *p);
|
||||
(gdb) reverse-continue
|
||||
Continuing.
|
||||
|
||||
No more reverse-execution history.
|
||||
main () at development/tutorials/ReverseDebug/main.c:41
|
||||
41 clobber(values, ARRAY_LENGTH);
|
||||
|
||||
|
||||
====
|
||||
|
||||
Now let's add a watch point at "&p" to hopefully catch the clobber on the spot:
|
||||
|
||||
(gdb) watch *(&p)
|
||||
Hardware watchpoint 2: *(&p)
|
||||
(gdb) c
|
||||
Continuing.
|
||||
Hardware watchpoint 2: *(&p)
|
||||
|
||||
====
|
||||
|
||||
And here it is:
|
||||
|
||||
Old value = (int *) 0xb728c020
|
||||
New value = (int *) 0x123
|
||||
0xb6f17440 in clobber (array=0xbebcaab0, size=10)
|
||||
at development/tutorials/ReverseDebug/main.c:28
|
||||
28 array[size] = 0x123;
|
||||
|
||||
|
||||
===============================
|
||||
|
||||
That said, reverse debugging on ARM is still in the infant stage. Currently
|
||||
(as of gdb 7.6) it only recognizes ARM instructions and will punt on all
|
||||
Thumb(2) instructions. To give it a try you will need to recompile your
|
||||
program in ARM mode. To do that you have to add the ".arm" suffix to the
|
||||
desired file in Android.mk:
|
||||
|
||||
LOCAL_SRC_FILES:= main.c.arm
|
||||
|
46
android/development/tutorials/ReverseDebug/main.c
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (C) 2013 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define ARRAY_LENGTH 10
|
||||
|
||||
int flag;
|
||||
|
||||
void clobber(int *array, int size) {
|
||||
/* Make sure it clobbers something. */
|
||||
array[-1] = 0x123;
|
||||
array[size] = 0x123;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
int values[ARRAY_LENGTH];
|
||||
int *p = (int *) malloc(sizeof(int));
|
||||
*p = 10;
|
||||
|
||||
while (!flag) {
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
/* Set a breakpint here: "b main.c:41" */
|
||||
clobber(values, ARRAY_LENGTH);
|
||||
printf("*p = %d\n", *p);
|
||||
free(p);
|
||||
|
||||
return 0;
|
||||
}
|