65.9K
CodeProject 正在变化。 阅读更多。
Home

CPForAndroid和Android项目模板

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.76/5 (52投票s)

2010年8月30日

CPOL

11分钟阅读

viewsIcon

105054

downloadIcon

3360

MyDroidTemplate Eclipse项目模板和一个用于与CodeProject交互的Droid应用程序

 

MyDroidTemplate

cpforandroid/MyDroidTemplateIDE478x260.png

CPForAndroid

 

引言

本文将探讨我在开发 CPForAndroid 时发现的一些有趣的组件,这些组件对于学习开发 Android 应用程序的人可能很有用。还有一个模板应用程序,其中包含大多数应用程序所需的类,如数据库函数和菜单,这些在 Eclipse 的新建项目向导中找不到。

我猜想有很多读者熟悉 SQLite。我还没有机会使用轻量级嵌入式 SQL 数据库引擎库,并且很高兴它被用于 Android 开发。我决定制作一个小型的 SQLite 模板,由两个类组成,以便在将来的项目中重用。在尝试这个之后很短的时间内,我决定将我制作的一些内容与 alessandroFranzi 的 Creative Commons 许可的类 SQLiteDatabaseAdapter 合并(这就是我们在这里喜欢做的,对吧?代码重用 :smile:)。SQLite 似乎是帮助记住用户上次阅读的 CPForAndroid RSS 文章的有效解决方案。

Android SDK 和 Eclipse 集成开发环境 (IDE)

我相信 Codeproject 上有更多关于如何设置 Android 开发的深入教程,但这里是我为本文整理的一个快速参考指南

注意 (2014-11-06):以下步骤是在文章首次起草时创建的,请参考 此处 的文档以获取最新说明以及使用 Android Studio 的说明

  1. 确保你已安装 Eclipse IDE for Java
  2. 下载 Android SDK,运行 SDK 设置时可能会遇到错误,或者转到 Window -> Preferences。然后导航到 Install/update - available software sites。然后你可以将 http://dl-ssl.google.com/android/eclipse/site.xml 添加到列表中。现在如果你需要下载 Android 开发工具,请返回 Eclipse 主屏幕并导航到 Help -> Install New Software。在“Work with”字段中粘贴相同的 URL:http://dl-ssl.google.com/android/eclipse/site.xml。然后选择所有可用的开发工具。重启,你现在就可以使用 Android 开发工具了。更多帮助请点击此处
  3. 按照 快速入门 设置 Eclipse IDE。

MyDroidTemplate

cpforandroid/template_files208x421.png 当你使用 New -> Android Project 向导从头开始构建 Android 项目时,它会构建应用程序的基础,但还有一些预期的项目缺失。此模板旨在提供一个可以精简和自定义的模板,而不是四处查找代码并添加。要使用此模板,请将 *MyDroidTemplate.zip* 解压到新位置(例如,在你的 Eclipse 'workspace' 文件夹中),然后将根文件夹重命名为你的新项目名称。接下来,选择 File -> Import -> Existing Projects into Workspace。然后你需要更新项目类名和命名空间到你的新名称。

以下是我添加到 Eclipse 生成的 *MyDroidTemplate.java* 文件中的一些内容

import android.util.Log; //Used for debug and error logging [Log.e(TAG, "e.getMessage()");]
public final String TAG = "MyDroidTemplate"; //Used in logging etc.

Menu

我曾在某处读到,大多数 Android 用户都期望应用程序中存在菜单,所以让我们在项目模板中添加一个。我在 '*.\MyDroidTemplate\res'* 下创建了一个名为 'menu' 的子文件夹(如果你不熟悉 Eclipse,请记住,当你添加 Eclipse IDE 之外的文件夹或文件时,需要按 F5 刷新你的项目)。这将包含有关如何绘制菜单按钮的详细信息。对于模板,我们只需要三个按钮:“Options”(选项)、“Quit”(退出)和“About”(关于)。

<?xml version="1.0" encoding="utf-8"?>
<menu
  xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/options" 
    android:title="Options" 
    android:icon="@android:drawable/ic_menu_preferences">
    </item>
    <item android:id="@+id/quit" 
    android:title="Quit" 
    android:icon="@android:drawable/ic_menu_close_clear_cancel">
    </item>
    <item android:id="@+id/about" 
    android:title="About" 
    android:icon="@android:drawable/ic_menu_info_details">
    </item>
</menu>

接下来,我们需要一些方法来触发和绘制菜单。当 Eclipse 检测到需要类库时,它会在自动添加导入行方面做得很好。以下是此 OptionsMenu 所需的类:

import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;

在 `MyDroidTemplate` 类中,我们有以下方法来实现它(**注意**:我已注释掉我们尚未准备好的行,例如 AboutDialog 等)。

//*** ANDROID.VIEW.MENU START ***// 
public boolean onCreateOptionsMenu(Menu menu) 
{
     // Create the menu from the menu_xml
     MenuInflater inflater = getMenuInflater();
     inflater.inflate(R.menu.menu, menu);
     return true;
}
public boolean onOptionsItemSelected(MenuItem item) {
     // Handle item selection
     switch (item.getItemId()) {
     case R.id.options:
          //DO OPTIONS()
          return true;
     case R.id.quit:
          finish();
          return true;
     case R.id.about:
          //new AboutDialog(this).show();
          return true;
     default:
          return super.onOptionsItemSelected(item);
     }
}
//*** ANDROID.VIEW.MENU END ***// 

AlertDialog

这是 AboutDialog 在模板中的添加方式。与所有 Android 视图一样,必须有一个相应的布局 XML 文件。我通过选择要添加 XML 的文件夹并选择“New -> Android XML File”,然后确保选中 layout 并将 'about.xml' 写入“File”文本框并点击 Finish 来在 Eclipse 中创建了一个。这是 about.xml,请注意我们主要添加 TextViews,以便以后可以格式化并发送文本(**注意**:我在 *\values\strings.xml* 中添加了一些颜色值)。[**注意**:*PopUpDialog.java* 和 *popup.xml* 已添加到模板中,这使你可以用一行代码创建弹出消息。]

<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/options" 
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     android:orientation="vertical">

          <LinearLayout
          android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:orientation="vertical">
          <TextView
          android:id="@+id/app_name"
          android:layout_height="wrap_content"
          android:layout_width="wrap_content"
          android:textStyle="bold"
          android:textSize="16sp"
          android:textColor="@color/white"
          android:layout_marginLeft="20dip"
          android:layout_marginRight="20dip"
          android:layout_marginTop="12dip"
          android:layout_marginBottom="4dip" />
          <TextView
          android:id="@+id/author"
          android:layout_height="wrap_content"
          android:layout_width="wrap_content"
          android:textStyle="bold"
          android:textSize="14sp"
          android:textColor="@color/white"
          android:layout_marginLeft="20dip"
          android:layout_marginRight="20dip"
          android:layout_marginTop="4dip"
          android:layout_marginBottom="4dip" />
          <TextView
          android:id="@+id/graphics_byline"
          android:layout_height="wrap_content"
          android:layout_width="wrap_content"
          android:textStyle="bold"
          android:textSize="14sp"
          android:textColor="@color/white"
          android:layout_marginLeft="20dip"
          android:layout_marginRight="20dip"
          android:layout_marginTop="4dip"
          android:layout_marginBottom="4dip" />
          <TextView
          android:id="@+id/license"
          android:layout_height="wrap_content"
          android:layout_width="wrap_content"
          android:textStyle="bold"
          android:textSize="14sp"
          android:layout_marginLeft="20dip"
          android:layout_marginRight="20dip"
          android:layout_marginTop="4dip"
          android:layout_marginBottom="8dip" />
          <TextView
          android:id="@+id/what_is_this"
          android:layout_height="wrap_content"
          android:layout_width="wrap_content"
          android:textStyle="bold"
          android:textSize="14sp"
          android:layout_marginLeft="20dip"
          android:layout_marginRight="20dip"
          android:layout_marginTop="8dip"
          android:layout_marginBottom="8dip" />
          <TextView
          android:id="@+id/website"
          android:autoLink="web"
          android:layout_height="wrap_content"
          android:layout_width="wrap_content"
          android:textStyle="bold"
          android:textSize="14sp"
          android:textColor="@color/white"
          android:layout_marginLeft="20dip"
          android:layout_marginRight="20dip"
          android:layout_marginTop="8dip"
          android:layout_marginBottom="4dip" />
          <TextView
          android:id="@+id/bugs"
          android:autoLink="web"
          android:layout_height="wrap_content"
          android:layout_width="wrap_content"
          android:textStyle="bold"
          android:textSize="14sp"
          android:textColor="@color/white"
          android:layout_marginLeft="20dip"
          android:layout_marginRight="20dip"
          android:layout_marginTop="4dip"
          android:layout_marginBottom="12dip" />
</LinearLayout>
</ScrollView>

现在我们必须有一个 Java 类来处理 AboutDialog 框。我们可以通过右键单击“src”文件夹并选择“New -> class”在 Eclipse 中创建它。对于“Package”,我浏览到 'com.android.MyDroidTemplate',然后在“Name”字段中输入 'AboutDialog' 并点击 Finish 按钮。下面是 *AboutDialog.java* 和 *Utils.java*。我发现 AboutDialog 是一个适合复制以创建新对话框的类。`Utils` 类包含一些可重用代码,用于获取不断变化的应用程序详细信息。(**注意**:再次,我已将内容添加到 *\values\strings.xml* 以存储应用程序的常用文本。)

//AboutDialog.java
package com.android.MyDroidTemplate;

import android.app.AlertDialog;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;

public class AboutDialog {
@SuppressWarnings("unused")
private static final String TAG = "AboutDialog";
private final Context mCtx;

public AboutDialog(Context ctx) {
     super();
     this.mCtx = ctx;
     }

public void show() {
final LayoutInflater factory = LayoutInflater.from(mCtx);

View dialogView = factory.inflate(R.layout.about, null);
innerUpdate(dialogView);
AlertDialog.Builder adBuilder = new AlertDialog.Builder(mCtx).setTitle(
R.string.about).setIcon(android.R.drawable.ic_dialog_info)
.setView(dialogView);
adBuilder.show();
}
private void innerUpdate(View dialogView) {
TextView appName = (TextView) dialogView.findViewById(R.id.app_name);
TextView author = (TextView) dialogView.findViewById(R.id.author);
TextView graphics_byline = (TextView) dialogView.findViewById(R.id.graphics_byline);
TextView license = (TextView) dialogView.findViewById(R.id.license);
TextView whatIsThis = (TextView) dialogView.findViewById(R.id.what_is_this);
TextView website = (TextView) dialogView.findViewById(R.id.website);
TextView bugs = (TextView) dialogView.findViewById(R.id.bugs);

// app name & version
String appText = Utils.getAppName(mCtx, mCtx.getPackageName()) + " v"
+ Utils.getAppVersionName(mCtx, mCtx.getPackageName());
appName.setText(appText);

// author
author.setText(R.string.author);

// license
license.setText(R.string.license);

// text
whatIsThis.setText(R.string.about_text);
// website
website.setText(mCtx.getString(R.string.website) + ":\n\n"
+ mCtx.getString(R.string.website_url));

// email
bugs.setText("Suggestions or Bugs:\n\n"
+ mCtx.getString(R.string.issues));
     }
} 

以及 *Utils.java*

//Utils.java

import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;

public class Utils {
 public static boolean checkForInstalledApp(Context ctx, String pkgName) {
      try {
      PackageManager pm = ctx.getPackageManager();
      pm.getPackageInfo(pkgName, 0);
      // Log.d(TAG, pkgString + " is installed");
      return true;
      } catch (NameNotFoundException e) {
           // Log.d(TAG, pkgString + " is not installed");
      }
      return false;
}

public static String getAppName(Context ctx, String pkgName) {
     try {
           PackageManager pm = ctx.getPackageManager();
           ApplicationInfo appInfo = pm.getApplicationInfo(pkgName, 0);
          String label = pm.getApplicationLabel(appInfo).toString();
          return label;
           } catch (NameNotFoundException e) {
            return "";
           }
}

     public static String getAppVersionName(Context ctx, String pkgName) {
     try {
          PackageManager pm = ctx.getPackageManager();
          PackageInfo pkgInfo = pm.getPackageInfo(pkgName, 0);
          String ver = pkgInfo.versionName;
          return ver;
     } catch (NameNotFoundException e) {
     return "0";
          }
}

public static int getAppVersionCode(Context ctx, String pkgName) {
try {
PackageManager pm = ctx.getPackageManager();
PackageInfo pkgInfo = pm.getPackageInfo(pkgName, 0);
return pkgInfo.versionCode;
} catch (NameNotFoundException e) {
return 0;
}
}
}

SQLite 数据库类

*SQLiteDatabaseAdapter.java*(提供管理 SQLite 数据库方法的类)和 *DbDataLayer.java*(用于管理数据库版本、打开、创建和升级的配套类)已添加以支持 SQLite 数据库。我将不发布整个类,而是解释创建和获取数据库信息的重要方法。大多数情况下,唯一需要自定义的类是 `DbDataLayer`(如果你以后需要执行升级,请修改 SQLiteDatabaseAdapter 中的 `OnUpgrade` 方法)。`DbDataLayer` 需要你的数据库名称和表名。它还需要你的表数据结构,采用标准的 SQL 'create table' 语句。最后,你需要修改 `AddRecord` 方法,使其能够正确地向表架构添加记录。

//DbDataLayer.java
private static final String DATABASE_NAME = "mydbname.db"; //CUSTOMIZE
private static final String TABLE_NAME = "mytablename";//CUSTOMIZE

此外,你还需要自定义表创建以满足你的需求(见下文)。你会注意到模板默认创建一个名为 'mytablename' 的表,并在数据库 'mydbname.db' 中包含 'ID'、'Link'、'Title' 和 'Pubdate' 列。

//DbDataLayer.java
public DbDataLayer(Context c) 
{
     //CUSTOMIZE FOR YOUR TABLE
     String sql = "create table "+ TABLE_NAME + " " +
     "("+ BaseColumns._ID + " integer primary key autoincrement, " +
     "Link text not null, " +
     "Title text not null, " +
     "Pubdate text not null); "; 

     _dbHelper = new SQLiteDatabaseAdapter(c, DATABASE_NAME, null , 1, sql);
}

现在,在执行任何读写操作之前,可以按以下方式初始化数据库

//MyDroidTemplate.java

public DbDataLayer d ;

public class MyDroidTemplate extends Activity {
public DbDataLayer db ;
...
...
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setContentView(R.layout.main);

            try {
               //DO SOMETHING
               db = new DbDataLayer(getBaseContext());//Initialize the database
     } catch (Exception e) {
          Log.e(TAG, e.getMessage());
     }
} 

调用以下方法向数据库写入数据

//DbDataLayer.java
//CUSTOMIZE FOR YOUR DATABASE ENTRIES
public void AddRecord(String title, String link, String pubdate) {
     SQLiteDatabase db = _dbHelper.getWritableDatabase();
     try {
          ContentValues values = new ContentValues();
          values.put("Link", link);
          values.put("Title", title);
          values.put("Pubdate", pubdate);

          db.insert(TABLE_NAME, "", values);
     }catch (Exception e)
     {
          Log.e(tag,"AddRecord Exception [" + e.getMessage() + "]");
     } finally {
          if (db != null)
          db.close();
     }
}

ProgressDialog 类

这是到目前为止最难实现的功能之一,而且我仍然不满意。因此,任何建议和反馈都将非常有益。但是,我在模板中需要一个 `Progressbar` 功能,所以这是我为第 1 版准备的内容。调用 `showDialog` 会触发 `onCreateDialog`,后者会显示请求的 `ProgressDialog`。

//MyDroidTemplate
import android.app.ProgressDialog;

public class MyDroidTemplate extends Activity {
...
static final int PROGRESS_DIALOG = 0; //Used for DownloadedThread PRogressBar handling
DownloaderThread progressThread; //Used for DownloadedThread PRogressBar handling
ProgressDialog progressDialog; //Used for DownloadedThread PRogressBar handling

//*** PROGRESSBAR THREAD START ***//
// Define the Handler that receives messages from the thread and update the progress
final Handler handler = new Handler() {
     public void handleMessage(Message msg) {
          dismissDialog(PROGRESS_DIALOG);
          progressThread.setState(DownloaderThread.STATE_DONE);
     }
};

protected Dialog onCreateDialog(int id) {
     switch(id) {
     case PROGRESS_DIALOG:
          progressDialog = new ProgressDialog(this);
          progressDialog.setMessage("Loading...");
          progressThread = new DownloaderThread(handler);
          progressThread.start();
          return progressDialog;
     default:
          return null;
     }
}

/** Nested class that performs progress */
private class DownloaderThread extends Thread {
     Handler mHandler;
     final static int STATE_DONE = 0;
     final static int STATE_RUNNING = 1;
     int mState;
     int total;

     DownloaderThread(Handler h) {
     mHandler = h;
     }

     public void run() {
     mState = STATE_RUNNING; 
     while (mState == STATE_RUNNING) 
     {
          Message msg = mHandler.obtainMessage();
     try {
     //Do The Work
     Thread.sleep(10000);
     } catch (Exception e) {
          Log.e("ERROR", "Thread Interrupted Exception [" + e.getMessage() + "]");
     }
     mHandler.sendMessage(msg);
     }}

/* sets the current state for the thread,
* used to stop the thread */
public void setState(int state) {
     mState = state;
     }
}

TabView 模板 (android.widget.TabHost)

模板中包含一组类,以防你需要选项卡式视图支持。*MyTabView.java* 和 *mytabview.xml* 处理 2 个选项卡(你可以添加更多)的主显示,这些选项卡是通过 *MyTabActivity.java* 和 *MyTabActivity2.java* 创建的。*MyTabActivity.java* 使用简单的 `String` 数组填充 `ListView`,*MyTabActivity2.java* 则使用自定义适配器(*MyLVAdapter.java* [My List View Adapter])进行填充。

Android 调试桥 (adb.exe)

Android Debug Bridge (adb.exe) 允许你直接访问模拟器实例或 Android 设备进行调试。例如,对于此模板应用,我可以使用它在进行一些条目后查看数据库(**注意**:*adb.exe* 位于 'android-sdk-windows\tools' 文件夹中)。启动模拟器,然后启动 Android 应用程序。下面是我放在文本文件中的命令,以便我方便地复制和粘贴(**注意**:有些命令需要修改才能访问正确的数据库和表名)。

C:\android-sdk-windows\tools>adb shell

cd data

cd data

cd com.android.MyDroidTemplate

cd databases

sqlite3 mydbname.db

cd data

cd data

cd com.android.MyDroidTemplate

cd databases

#ls
ls
mydbname.db
# sqlite3 mydbname.db
sqlite3 mydbname.db
SQLite version 3.5.9
Enter ".help" for instructions
sqlite> select * from mytablename;
select * from mytablename;
1|http://msn.com|MSN|Mon Aug 30 08:00
2|http://codeproject.com|Codeproject|Mon Aug 30 09:00
3|http://cpforandroid.googlecode.com|CPForAndroid|Mon Aug 30 10:00
sqlite>

CPForAndroid:一个与 CodeProject.com 交互的 Droid 应用

 

立即在你的 Android 手机上的 Market 上获取 `CPForAndroid`。尝试后请评分!!

cpforandroid/qrcode.png

CPForAndroid

一个用于与 CodeProject.com 交互的应用!关注你喜欢的编程社区的最新动态。对眼睛友好且有趣。
当前功能包括

  • 查看最新文章 RSS feed
  • 查看 Lounge RSS feed
  • 移除已读项目
  • 查看每项的详细信息,可选择跳转链接
  • Facebook、Google、Twitter、Windows Live、CP 电子邮件链接分享

  

https://market.android.com/details?id=org.android.CPForAndroidPlusPlus

如果你有兴趣帮助开发或提供反馈,请访问 开发和支持网站

发布你的应用到 Market

  1. 请确保你在清单文件中声明了 'android:minSdkVersion' 属性(https://developer.android.com.cn/guide/appendix/api-levels.html),然后将你的应用导出为 .apk 文件 [File -> Export]。这将生成 .apk 所需的证书。(尽快备份你的 KEYSTORE!!!以后你会感谢我的。)
  2. 发布你的应用程序到 Android Market 需要 $25.00。http://market.android.com/publish
  3. 完成注册过程。
  4. 根据发布说明上传你的文件。

技巧

这些只是我在过程中需要查找的一些项目。你可能会发现它们在编写代码时很有用。

结论

在我的移动设备上浏览 Codeproject.com 就足以激励我学习使用 Android SDK 及其模拟器进行开发。将所有内容记录在这里,将在 6 到 12 个月后,当我有了另一个 Android 应用的想法时,对我有所帮助。希望其他人会发现本文很有帮助,并且 `MyDroidTemplate` 是一个有用的 Android 项目骨架起点。除了模板,我还提供了一些有用的链接来帮助你开发应用程序,以及一个关于如何将你的应用程序上传到 Android Market 的快速参考。我计划很快发布一个视频,供那些没有 Android 手机也没有 Eclipse IDE 的读者观看,以了解本文的内容。

此模板是 CPForAndroid 的副产品。`CPForAndroid` 是一个用于跟踪 Codeproject.com 的 Android 应用程序。它是一个开源项目,对所有人开放。只需访问开发和支持网站了解更多信息。快来帮忙吧;人越多越热闹!

参考文献

  • Developer.Android.com [^]
  • Eclipse Development [^]
  • CPForAndroid 开源项目支持和开发网站 [^]
  • SQLite.org [^]

更新

  • 8/30/2010
    • 已上传 `MyDroidTemplate` v1.0.0.0(在 Eclipse 3.4 中测试)
  • 9/1/2010
    • 在 Eclipse 3.6 中测试 `MyDroidTemplate` v1.0.0.0(因此在 3.4 和 3.6 中均已验证)
  • 9/5/2010
    • 向 `MyDroidTemplate` 添加了 *PopUpDialog.java* 和 *popup.xml*
    • 已上传 `MyDroidTemplate.zip` 版本 1.1
    • 已更新 *template_files208x421.png*
    • 已更新 *cpforandroid_main.png*
    • 已更新 *MyDroidTemplateIDE478x260.png*
    • `CPForAndroid` 现在版本为 1.17,可在 Android Market 上获取
  • 9/8/2010
    • 在类 `DbDataLayer` 方法 `DoesExist()` 中添加了 cur.deactivate() 以避免任何错误
    • 添加了示例 Toast
    • 已上传 `MyDroidTemplate` versionName="1.2" versionCode="3"
  • 9/13/2010
    • 已上传 `MyDroidTemplate.zip` 版本 1.3  
    • 向 `Utils` 类添加了 `ToastMsg`
    • 添加了 *MyTabView.java* 和 *mytabview.xml*
    • 添加了 *MyTabActivity.java* 和 *mytabact.xml*
    • 添加了 *MyTabActivity2.java*(使用 `MyLVAdapter`)
    • 在 *main.xml* 布局中添加了“Show TabView”按钮
    • 为 *MyLVView.java* 添加了 *listview_row.xml*
    • 添加了 *MyLVView.java*
    • 添加了 *MyLVAdapter.java*
    • 在异常 `catch` 语句中添加了 `e.printStackTrace();` 以获得更好的调试效果
  • 2/11/2011
    • `CPForAndroid` 现在是 CPForAndroid++
    • 更新了 qcode 和 Market Publishing 部分
  • 11/06/2014
    • `MyDroidTemplate.java` 在 Android Studio (beta) 0.8.14 和 Android 4.4.2 中成功测试(已转换项目)
    • CPForAndroid++ 由于一些 string.xml 错误无法编译,我还没有时间去调查
    • 更新了“Android SDK 和 Eclipse 集成开发环境 (IDE)”部分
© . All rights reserved.