安卓APP源码和设计报告——麻雀笔记

目录

一 安卓应用程序开发背景3

1.1开发背景3

1.2开发环境4

二 安卓应用程序开发理论与方法4

三 记事本应用程序的设计与实现5

3.1 拟解决的问题及目标5

3.2 总体设计6

3.3 详细设计与编码实现6

四 总结23

一 安卓应用程序开发背景

1.1开发背景

1.智能手机的市场

(1)功能多样化的智能手机挑战全球PC出货量

移动互联网时代的来临,直接促进了搭载智能操作系统、具有强大扩展性的智能手机、平板电脑等移动终端产业的蓬勃发展。来自美国最大的风险投资机构KPCB的数据显示,全球智能手机出货量正在以远高于台式电脑、笔记本电脑出货量的速度快速增长,该机构预计2011年全球智能手机出货量将达到4.13亿,超过台式电脑与笔记本电脑出货量的总和。

(2)智能手机的用户使用数量正在高速增长。据市场调研机构Gartner信息,2011年全球智能手机的总出货量将会达到4.68亿部,相比2010年实现了57.7%的增长,而谷歌Android操作系统将会在今年之内成为全球最大的智能手机操作系统。另外,全球市场调研机构IDC预计未来5年中国手机市场上,智能手机替代传统功能手机的趋势将日益明显,未来5年中国智能手机市场复合增长率将达到34.1%,人们对IT设备智能化的向往是这一增长率能够实现的主要因素,并且与其他国家相比,中国智能手机市场的发展空间更加广阔。

(3)操作系统格局预测:Android有望成为智能手机市场主导力量

搭载Android操作系统的智能手机目前已经成为市场上最炙手可热的智能产品。来自美国市场研究机构Gartner的数据显示,Android操作系统所占的市场份额从2008年的0.5%急剧增长到2011年的15.94%。开放的源代码和零成本已经让Android在全世界范围内受到青睐并迅速获得了主要手机厂商和数百万软件开发者的支持,Gartner预计,未来Android系统的市场份额有望超过其他操作系统,从而成为全球第一大智能手机操作系统。

2.安卓手机介绍

安卓手机指的是用Android操作系统的手机。安卓(Android)是基于Linux内核的操作系统,是Google公司在2007年11月5日公布的手机操作系统。

同样都是手机上面用的智能系统,安卓的系统是新生系统,界面更为华丽,开源性更强,当然因为是新生系统,所以在第三方软件方面暂时还不太多。因此,安卓应用程序的需求还是很迫切的。

3.软件人才需求

据业内统计,目前国内的Android研发人才缺口至少30万。由于目前Android技术较新,无论是相关书籍、培训还是大学教育,都处于初级阶段,因此Android人才短期将供不应求。从长期来看,随着各种移动应用和手机游戏等内容需求日益增加,也将激励大中小型手机应用开发商加大对Android应用的开发力度,因此Android人才的就业前景也非常广泛。

综上所述,在这样的背景下,安卓有很强的生命力。同时,作为一个新生的系统,其应用程序目前并不多,安卓应用程序的需求还是很迫切的,安卓研发人才的缺口还很大。这些都促进了我们学习开发安卓应用程序。

1.2开发环境

安卓应用程序开发环境如下:

①jdk1.8

②android studio 4.0

③Android SDK

二 安卓应用程序开发理论与方法

  1. ButterKnife
    ButterKnife 是一个专注于 Android 系统的 View 注入框架,以前总是要写很多 findViewById 来找到 View 对象,有了 ButterKnife 可以很轻松地省去这些步骤。使用 ButterKnife 对性能基本没有损失,因为 ButterKnife 用到的注解并不是在运行时反射的,而是在编译的时候生成新的 class。项目集成起来特别方便,使用起来也特别简单。
    ButterKnife 的优势:
    强大的 View 绑定和 Click 事件处理功能,简化代码,提升开发效率
    方便地处理 Adapter 里的 ViewHolder 绑定问题
    运行时不会影响 APP 效率,使用配置方便
    代码清晰,可读性强
  2. SharedPreferences
    SharedPreferences 是使用键值对的方式来存储数据的。当保存一条数据的时候,需要给这条数据提供一个对应的键,这样在读取数据的时候就可以通过这个键把相应的值取出来。而且 SharedPreferences 还支持多种不同的数据类型存储。
  3. SQLite + OrmLite
    SQLite 是一款轻量级的关系型数据库,它的运算速度非常快,占用资源很少,通常只需要几百 KB 的内存就足够了,因而特别适合在移动设备上使用。SQLite 不仅支持标准的 SQL 语法,还遵循了数据库的 ACID 事务,所以只要以前是用过其他的关系型数据库,就可以很快地上手 SQLite。
    ORM(全称 Object Relation Mapping)叫做对象关系映射,是一种程序设计技术,用于实现面向对象编程语言中不同类型系统的数据之间的转换。它可以直接将 Bean 文件转换成数据库中的表,Bean 中的属性就是表的列,它将繁琐的数据库操作封装成一个 Dao 类,使用 Dao 类和 Bean 可以直接对数据库进行操作,大多数的方法参数只有一个 Bean 对象。
  4. 多线程编程 Handler + Message
    Handler 顾名思义也就是处理者的意思,它主要是用于发送和处理消息的。发送消息一般是使用 Handler 的 sendMessage()方法,而发出的消息经过一系列的辗转处理后,最终会传递到 Handler 的 handleMessage()方法中。
    Message 是在线程之间传递的消息,它可以在内部携带少量的信息,用于在不同线程之间交换数据。除了 what 字段,Message 还可以使用 arg1 和 arg2 字段来携带一些整型数据,使用 obj 字段携带一个 Object 对象。
  5. Glide
    Glide 是一款快速高效的开源 Android 媒体管理和图片加载框架,它将媒体解码、内存和磁盘缓存以及资源池打包成一个简单易用的界面。
    Glide 支持抓取、解码和显示视频图片、图像和动态 gif。Glide 包括一个灵活的 API,允许开发人员插入几乎任何网络堆栈。默认情况下,Glide 使用了一个定制的基于 HttpUrlConnection 的堆栈,但也包含了可插入谷歌的 Volley 项目或 Square 的 OkHttp 库的实用程序库。
    Glide 的主要功能是尽可能平滑快速地滚动任何类型的图像列表,但它也适用于几乎任何需要获取、调整大小和显示远程图像的情况。
  6. RecyclerView 控件
    RecyclerView 是一个增强版的 ListView,不仅可以轻松实现和 ListView 同样的效果,还优化了 ListView 中存在的各种不足之处。同时 RecyclerView 支持横向滚动和瀑布流布局
  7. Fragment + ViewPager

Fragment 是一种可以嵌入在 Activity 当中的 UI 片段,它能让程序更加合理和充分地利用大屏幕的空间,因而在平板上应用得非常广泛。它和 Activity 同样都能包含布局,同样都有自己的生命周期。甚至可以理解成一个迷你的 Activity。

ViewPager 是 android 扩展包 v4 包中的类,这个类可以让用户左右切换当前的 view。ViewPager 类直接继承了 ViewGroup 类,因此它一个容器类,可以添加其他的 View 类 ViewPager 类需要一个 PagerAdapter 适配器类给它提供数据(类似 RecyclerView)。

ViewPager 经常和 Fragment 一起使用,并且官方还提供了专门的 FragmentPagerAdapter 类供 ViewPager 使用。

三 记事本应用程序的设计与实现

3.1 拟解决的问题及目标

一个简单的记事本应用,在人们繁忙的时候更快速的记笔记,程序要实现的目标有如下几个:

  1. 登录注册
  2. 笔记顶置
  3. 开始游戏笔记增删查改

3.2 总体设计

1、记事本操作流程

先注册一个账号,登录进去,可以添加笔记,编辑笔记,顶置笔记,查找笔记

3.3 详细设计与编码实现

  1. 记事本界面


注册界面


新建笔记界面


编辑界面


个人信息界面

  1. 核心代码如下:

RegisterActivity

public class RegisterActivity extends AppCompatActivity {

@BindView(R.id.btn_register)
Button btnRegister;
@BindView(R.id.btn_reset)
Button btnReset;
@BindView(R.id.check_hide_pwd_reg)
CheckBox checkHidePwdReg;
@BindView(R.id.check_hide_pwd_reg2)
CheckBox checkHidePwdReg2;
@BindView(R.id.edit_username_reg)
EditText editUsernameReg;
@BindView(R.id.edit_confirm_pwd_reg)
EditText editConfirmPwdReg;
@BindView(R.id.edit_email_reg)
EditText editEmailReg;
@BindView(R.id.edit_password_reg)
EditText editPasswordReg;

SharedPreferenceUtil spu;
private static final String TAG = "RegisterActivity";
private UserDao userDao;
private String textUserName;
private String textPassword;
private String textConfirmPwd;
private String textEmail;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register);
ButterKnife.bind(this);
userDao = new UserDao(this);
spu = SharedPreferenceUtil.getInstance(this);
}

@OnClick({R.id.btn_register, R.id.btn_reset, R.id.check_hide_pwd_reg, R.id.check_hide_pwd_reg2})
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.btn_register:
// 检验非空
if (isNotEmpty()) {
// 获得用户输入
getEditText();
// 检验密码
if (comparePwd()) {
// 检查邮箱格式
if (checkEmail()) {
// 检查邮箱是否可用
if (checkOnlyEmail()) {
insertUserIntoDB();
queryAll();
Intent intent = new Intent(RegisterActivity.this, MainActivity.class);
intent.putExtra(Constant.HAS_REGISTERED, true);
startActivity(intent);
finish();
} else {
Toast.makeText(this, "邮箱已经被使用", Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(this, "邮箱格式错误", Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(this, "两次输入的密码不一致", Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(this, "用户名或密码不能为空", Toast.LENGTH_SHORT).show();
}
break;
case R.id.btn_reset:
editUsernameReg.setText("");
editPasswordReg.setText("");
editConfirmPwdReg.setText("");
editEmailReg.setText("");
break;
case R.id.check_hide_pwd_reg:
if (checkHidePwdReg.isChecked()) {
// 将密码显示出来
editPasswordReg.setTransformationMethod(HideReturnsTransformationMethod.getInstance());
} else {
// 隐藏密码
editPasswordReg.setTransformationMethod(PasswordTransformationMethod.getInstance());
}
// 将光标移动到文本最后
editPasswordReg.setSelection(editPasswordReg.getText().toString().length());
break;
case R.id.check_hide_pwd_reg2:
if (checkHidePwdReg2.isChecked()) {
// 将密码显示出来
editConfirmPwdReg.setTransformationMethod(HideReturnsTransformationMethod.getInstance());
} else {
// 隐藏密码
editConfirmPwdReg.setTransformationMethod(PasswordTransformationMethod.getInstance());
}
// 将光标移动到文本最后
editConfirmPwdReg.setSelection(editConfirmPwdReg.getText().toString().length());
break;
default:
break;
}
}

/**
* 检验输入非空
*
* @return
*/
public boolean isNotEmpty() {
return !"".equals(editUsernameReg.getText().toString()) &&
!"".equals(editPasswordReg.getText().toString()) &&
!"".equals(editConfirmPwdReg.getText().toString());
}

/**
* 从控件中得到输入值
*/
public void getEditText() {
textUserName = editUsernameReg.getText().toString();
textPassword = editPasswordReg.getText().toString();
textConfirmPwd = editConfirmPwdReg.getText().toString();
textEmail = editEmailReg.getText().toString();
}

/**
* 检查邮箱是否可用
*
* @return
*/
public boolean checkOnlyEmail() {
List<UserBean> userBeans = userDao.queryForWhat("email", textEmail);
return userBeans.size() == 0;
}

/**
* 验证两次输入的密码是否一致
*
* @return
*/
public boolean comparePwd() {
return textPassword.equals(textConfirmPwd);
}

/**
* 检查邮箱格式
*
* @return
*/
public boolean checkEmail() {
Matcher emailMatcher = Constant.EMAIL_PATTERN.matcher(textEmail);
return emailMatcher.matches();
}

/**
* 向数据库表插入数据
*/
public void insertUserIntoDB() {
UserBean userBean = new UserBean(textUserName, textPassword, textEmail);
userDao.insert(userBean);
// 同时存到SP中
spu.putString(Constant.USER_NAME, textUserName);
spu.putString(Constant.PASSWORD, textPassword);
}

/**
* 查询表中所有数据
*/
public void queryAll() {
List<UserBean> userBeans = userDao.queryAll();
for (int i = 0; i < userBeans.size(); i++) {
Log.d(TAG, "queryAll: " + userBeans.get(i).toString());
}
}
}

HomeActivity

public class HomeActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {

@BindView(R.id.toolbar)
Toolbar toolbar;
@BindView(R.id.btn_top)
RadioButton btnTop;
@BindView(R.id.btn_add)
RadioButton btnAdd;
@BindView(R.id.btn_all)
RadioButton btnAll;
@BindView(R.id.dock_radio_group)
RadioGroup dockRadioGroup;
@BindView(R.id.drawer_layout)
DrawerLayout drawerLayout;
@BindView(R.id.nav_view)
NavigationView navView;

private static final String TAG = "HomeActivity";
ActionBar actionBar;
Fragment fragment;
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
SharedPreferenceUtil spu;
private UserDao userDao;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
ButterKnife.bind(this);
userDao = new UserDao(this);
spu = SharedPreferenceUtil.getInstance(this);
initView();
}

/**
* 初始化控件
*/
public void initView() {
// 工具栏
toolbar.setTitle(R.string.app_name);
setTitleCenter(toolbar);
setSupportActionBar(toolbar);
actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setHomeAsUpIndicator(R.drawable.icon_setting);
}
// 抽屉
ViewGroup.LayoutParams params = navView.getLayoutParams();
params.width = getResources().getDisplayMetrics().widthPixels / 2;
navView.setLayoutParams(params);
navView.setNavigationItemSelectedListener(this);
// 抽屉中的header
View headerView = navView.getHeaderView(0);
TextView textUserName = headerView.findViewById(R.id.header_user_name);
TextView textEmail = headerView.findViewById(R.id.header_email);
textUserName.setText(spu.getString(Constant.USER_NAME));
textEmail.setText(getEmail());
// 默认加载置顶Fragment
fragment = new TopFragment();
transaction.replace(R.id.view_pager, fragment, Constant.TOP_TAG);
transaction.commit();
}

/**
* 单选按钮监听器 用来切换Fragment
*
* @param view
* @param isChanged
*/
@OnCheckedChanged({R.id.btn_add, R.id.btn_all, R.id.btn_top})
public void onCheckedChanged(CompoundButton view, boolean isChanged) {
transaction = manager.beginTransaction();
switch (view.getId()) {
case R.id.btn_top:
if (isChanged) {
fragment = new TopFragment();
transaction.replace(R.id.view_pager, fragment, Constant.TOP_TAG);
transaction.commit();
Constant.PAGE_STATE = "top";
}
break;
case R.id.btn_add:
if (isChanged) {
fragment = new AddFragment();
transaction.replace(R.id.view_pager, fragment, Constant.ADD_TAG);
transaction.commit();
}
break;
case R.id.btn_all:
if (isChanged) {
fragment = new AllFragment();
transaction.replace(R.id.view_pager, fragment, Constant.LIST_TAG);
transaction.commit();
Constant.PAGE_STATE = "all";
}
break;
default:
break;
}
}

/**
* 获得登录用户的邮箱
*
* @return
*/
public String getEmail() {
List<UserBean> userBeans = userDao
.queryByUserNameAndPassword(spu.getString(Constant.USER_NAME), spu.getString(Constant.PASSWORD));
return userBeans.get(0).getEmail();
}

/**
* 抽屉中菜单的点击事件
*
* @param item
* @return
*/
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
drawerLayout.closeDrawers();
switch (item.getItemId()) {
case R.id.nav_change_pwd:
DialogUtil.editInfoDialog(this, spu.getInt(Constant.USER_ID));
break;
case R.id.nav_dismiss:
DialogUtil.dismissDialog(this, spu.getInt(Constant.USER_ID));
break;
case R.id.nav_exit:
spu.putBoolean(Constant.AUTO_LOGIN, false);
Intent intent = new Intent(HomeActivity.this, MainActivity.class);
startActivity(intent);
finish();
break;

default:
break;
}
return true;
}

/**
* ToolBar的menu
*
* @param menu
* @return
*/
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.toolbar_menu, menu);
setIconsVisible(menu, true);
return true;
}

/**
* 重写ToolBar上菜单点击事件
* 按照条件查找
*
* @param item
* @return
*/
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.search_title:
DialogUtil.searchTitleDialog(this);
break;
case R.id.search_content:
DialogUtil.searchContentDialog(this);
break;
case R.id.search_category:
DialogUtil.searchCategoryDialog(this);
break;
case android.R.id.home:
drawerLayout.openDrawer(GravityCompat.START);
break;
default:
break;
}
return true;
}

/**
* ToolBar标题居中
*
* @param toolbar
*/
public void setTitleCenter(Toolbar toolbar) {
String title = "title";
final CharSequence originalTitle = toolbar.getTitle();
toolbar.setTitle(title);
for (int i = 0; i < toolbar.getChildCount(); i++) {
View view = toolbar.getChildAt(i);
if (view instanceof TextView) {
TextView textView = (TextView) view;
if (title.equals(textView.getText())) {
textView.setGravity(Gravity.CENTER);
Toolbar.LayoutParams params = new Toolbar.LayoutParams(Toolbar.LayoutParams.WRAP_CONTENT, Toolbar.LayoutParams.MATCH_PARENT);
params.gravity = Gravity.CENTER;
textView.setLayoutParams(params);
}
}
toolbar.setTitle(originalTitle);
}
}

/**
* menu显示图标
*
* @param menu
* @param flag
*/
private void setIconsVisible(Menu menu, boolean flag) {
// 判断menu是否为空
if (menu != null) {
try {
// 如果不为空,就反射拿到menu的setOptionalIconsVisible方法
Method method = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE);
// 暴力访问该方法
method.setAccessible(true);
// 调用该方法显示icon
method.invoke(menu, flag);
} catch (Exception e) {
e.printStackTrace();
}
}
}

FindPwdActivity

public class FindPwdActivity extends AppCompatActivity {

@BindView(R.id.btn_confirm_find)
Button btnConfirmFind;
@BindView(R.id.btn_reset_find)
Button btnResetFind;
@BindView(R.id.edit_confirm_pwd_find)
EditText editConfirmPwdFind;
@BindView(R.id.edit_password_find)
EditText editPasswordFind;
@BindView(R.id.edit_email_find)
EditText editEmailFind;
@BindView(R.id.check_hide_pwd_find)
CheckBox checkHidePwdFind;
@BindView(R.id.check_hide_pwd_find2)
CheckBox checkHidePwdFind2;

private static final String TAG = "FindPwdActivity";
private UserDao userDao;
private String textPassword;
private String textConfirmPwd;
private String textEmail;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_find_pwd);
ButterKnife.bind(this);
userDao = new UserDao(this);
}

@OnClick({R.id.btn_confirm_find, R.id.btn_reset_find, R.id.check_hide_pwd_find, R.id.check_hide_pwd_find2})
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.btn_confirm_find:
// 检查非空
if (isNotEmpty()) {
// 获得用户输入
getEditText();
// 检查邮箱格式
if (checkEmail()) {
// 检查两次输入的密码是否一致
if (comparePwd()) {
// 更新密码
if (updatePwdFromDB()) {
// 跳转登录界面
Intent intent = new Intent(FindPwdActivity.this, MainActivity.class);
startActivity(intent);
FindPwdActivity.this.finish();
}
} else {
Toast.makeText(this, "两次输入的密码不一致", Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(this, "邮箱格式错误", Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(this, "邮箱或密码不能为空", Toast.LENGTH_SHORT).show();
}
break;
case R.id.btn_reset_find:
// 清空输入
editPasswordFind.setText("");
editConfirmPwdFind.setText("");
editEmailFind.setText("");
break;
case R.id.check_hide_pwd_find:
if (checkHidePwdFind.isChecked()) {
// 将密码显示出来
editPasswordFind.setTransformationMethod(HideReturnsTransformationMethod.getInstance());
} else {
// 隐藏密码
editPasswordFind.setTransformationMethod(PasswordTransformationMethod.getInstance());
}
// 将光标移动到文本最后
editPasswordFind.setSelection(editPasswordFind.getText().toString().length());
break;
case R.id.check_hide_pwd_find2:
if (checkHidePwdFind2.isChecked()) {
// 将密码显示出来
editConfirmPwdFind.setTransformationMethod(HideReturnsTransformationMethod.getInstance());
} else {
// 隐藏密码
editConfirmPwdFind.setTransformationMethod(PasswordTransformationMethod.getInstance());
}
// 将光标移动到文本最后
editConfirmPwdFind.setSelection(editConfirmPwdFind.getText().toString().length());
break;
default:
break;
}
}

/**
* 检验输入非空
*
* @return
*/
public boolean isNotEmpty() {
return !"".equals(editPasswordFind.getText().toString()) &&
!"".equals(editConfirmPwdFind.getText().toString()) &&
!"".equals(editEmailFind.getText().toString());
}

/**
* 从控件中得到输入值
*/
public void getEditText() {
textPassword = editPasswordFind.getText().toString();
textConfirmPwd = editConfirmPwdFind.getText().toString();
textEmail = editEmailFind.getText().toString();
Log.d(TAG, "getEditText: " + textEmail);
}

/**
* 检查邮箱格式
*
* @return
*/
public boolean checkEmail() {
Matcher emailMatcher = Constant.EMAIL_PATTERN.matcher(textEmail);
return emailMatcher.matches();
}

/**
* 验证两次输入的密码是否一致
*
* @return
*/
public boolean comparePwd() {
return textPassword.equals(textConfirmPwd);
}

/**
* 修改数据库中的密码
*
* @return 邮箱是否存在
*/
public boolean updatePwdFromDB() {
List<UserBean> userBeans = userDao.queryForWhat("email", textEmail);
if (userBeans.size() != 0) {
UserBean user = userBeans.get(0);
user.setPassword(textPassword);
userDao.update(user);
return true;
} else {
Toast.makeText(this, "邮箱错误", Toast.LENGTH_SHORT).show();
return false;
}
}
}

}

public void onLeaveApplication(Ad arg0) {

// TODO Auto-generated method stub

}

public void onFailedToReceiveAd(Ad arg0, ErrorCode arg1) {

// TODO Auto-generated method stub

}

public void onDismissScreen(Ad arg0) {

// TODO Auto-generated method stub

}

});

View gameMessage = findViewById(R.id.GameMessage);

int[] data = getSettingData();

TextView levelMessage = (TextView)findViewById(R.id.level_Message);

levelMessage.setText("SCORE: "+data[0]+"\nBEST: "+data[1]);

gameMessage.setOnClickListener(new View.OnClickListener() {

public void onClick(View arg0) {

Intent intent = new Intent(LoadingActivity.this, GameBirdActivity.class);

intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

startActivity(intent);

finish();

}

});

}

private int[] getSettingData() {

SharedPreferences gb_settings = getSharedPreferences(GameBirdActivity.GameBirdSettingsFile, 0);

int last = gb_settings.getInt(GameBirdActivity.Settings_LevelLast, 0);

int top = gb_settings.getInt(GameBirdActivity.Settings_LevelTop, 0);

return new int[]{last, top};

}

public boolean onKeyDown(int keyCode, KeyEvent event) {

if (keyCode == KeyEvent.KEYCODE_BACK) {

try{

GameBirdActivity.instance.finish();

}catch(Exception e){}

finish();

System.exit(0);

return true;

}

return super.onKeyDown(keyCode, event);

}

}

四 总结

100

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/2248.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

安卓APP源码和设计报告——好再来点餐

大作业文档 项目名称&#xff1a;好再来点餐专业&#xff1a;班级&#xff1a;学号&#xff1a;姓名&#xff1a; 目 录 一、项目功能介绍3 二、项目运行环境3 1、开发环境3 2、运行环境3 3、是否需要联网3 三、项目配置文件及工程结构3 1、工程配置文件3 2、工程结构…

来打卡!吴恩达3门AI新课;我用AI出版97本书;如何在创业小厂做技术领导;手把手教你用SD写好提示词 | ShowMeAI日报

&#x1f440;日报&周刊合集 | &#x1f3a1;生产力工具与行业应用大全 | &#x1f9e1; 点赞关注评论拜托啦&#xff01; &#x1f916; 「讯飞听见会写」开放内测申请&#xff0c;基于AI的文件内容处理 「讯飞听见会写」是讯飞「星火认知大模型」的个人示范应用产品&…

安卓APP源码和设计报告——基于Android的垃圾分类系统

《移动应用开发》大作业报告 题 目基于Android的垃圾分类系统系 部班 级学 生 姓 名学 号指 导 教 师时 间 1、项目名称 垃圾分类系统 2、项目概述 近些年&#xff0c;由于人民生活水平是的提高&#xff0c;生活方式与生活节奏的加快&#xff0c;使我国的垃圾生产数量已远…

安卓期末大作业——购物商城(源码+18页报告)

Android系统原理及应用报告 题 目&#xff1a; 学 号&#xff1a; 班 级&#xff1a; 姓 名&#xff1a; 完成时间 报告要求须知 项目报告按照实践开发实际情况编写&#xff0c;着重工程项目的需求分析、系统功能分析及模块图、数据库及E-…

安卓APP源码和报告——音乐播放器

课 程 设 计 报 告 院 系&#xff1a;专 业&#xff1a;题 目&#xff1a;科 目&#xff1a;学 生&#xff1a;指导教师&#xff1a;完成时间&#xff1a; 目 录 1. 引言1 1.1 目的1 1.2 背景1 2. 需求分析1 3. 系统设计1 3.1总体设计1 3.2功能设计1 4. 系统开发2 4.1…

【AIGC使用教程】Notion AI 从注册到体验:如何免费使用

欢迎关注【AIGC使用教程】 专栏 【AIGC使用教程】SciSpace 论文阅读神器 【AIGC使用教程】Microsoft Edge/Bing Chat 注册使用完全指南 【AIGC使用教程】GitHub Copilot 免费注册及在 VS Code 中的安装使用 【AIGC使用教程】GitHub Copilot 免费注册及在 PyCharm 中的安装使用 …

体验不了ChatGPT?来试试POE桌面版!

POE Poe App目前备受欢迎&#xff0c;许多用户已开始使用加入ChatGPT API后引入的聊天机器人。最早在App Store推出&#xff0c;目前Poe App还没有推出针对Android用户的版本&#xff0c;但今天poe.com推出了桌面版&#xff0c;Android用户也可以通过桌面浏览器使用ChatGPT。需…

推特、微博对手Threads软件的下载、注册、使用最新超详细教程

经过马斯克不断折腾&#xff0c;推特面临用户大量流失的风险&#xff0c;尤其近期限制推文阅读量&#xff0c;更是导致大量用户出走。 于是乎&#xff0c;Meta公司7月6日正式发布对标推特的新社交平台 Threads&#xff0c;当前Threads只能在 iOS、Android 平台上安装 APP 使用&…

【ChatGPT+MindShow高效生成PPT,保姆级安装教程】

&#x1f680; AI破局先行者 &#x1f680; &#x1f332; AI工具、AI绘图、AI专栏 &#x1f340; &#x1f332; 如果你想学到最前沿、最火爆的技术&#xff0c;赶快加入吧✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;CSDN-Java领域优质创作者&#x1f3c6;&am…

安卓期末大作业——日记APP

2022/2023 学年 第 一 学期 课程设计 实验报告 模 块 名 称 Android课程设计 专 业 通信工程&#xff08;嵌入式培养&#xff09; 学 生 班 级 学 生 学 号 学 生 姓 名 指 导 教 师 设计题目熟悉adt-bundle-windows-x86或android-studio-ide应用开发环境&#xff1a;安…

手把手教你怎么搭建自己的ChatGPT和Midjourney绘图(含源码)

AI程序采用NUXT3LARAVEL9开发&#xff08;目前版本V1.1.7&#xff09; 授权方式&#xff1a;三个顶级域名两次更换 1.AI智能对话-对接官方和官方反代&#xff08;markdown输出&#xff09;PS:采用百度与自用库检测文字 2.AI绘图-根据关键词绘图-增加dreamStudio绘画-增加mid…

制作自己的ChatGPT

Feb 11, 20235 min read 推荐&#xff1a;使用 NSDT场景设计器 快速搭建 3D场景。 众所周知&#xff0c;ChatGPT 目前能够取得令人印象深刻的壮举。 很可能许多人都有在他们自己的项目中使用该技术的想法。 不过需要注意的是&#xff0c;ChatGPT 目前并没有官方的 API。 使用非…

【ChatGPT】教你搭建多任务模型

ChatGPT教你搭建多任务模型 You: tell me what’s your version of gpt ? ChatGPT: As an AI language model developed by OpenAI, I am based on the GPT (Generative Pretrained Transformer) architecture. However, my version is known as GPT-3.5, which is an updat…

以一己之力搭建分布式ChatGPT

原以为去年年底ChatGPT已经火过一阵子了&#xff0c;慢慢热度会降下来。出乎意料的是&#xff0c;其热度有增无减。我也是从去年年底一直关注并使用&#xff0c;包括ChatGPT网页版、GPT3 API以及ChatGPT内测API&#xff0c;还包括其他国内外一些人工智能算法的体验。 为了方便使…

【AIGC】使用 Vercel 快速搭建 ChatGPT服务器

前言 在中国大陆境内域名提供商购买的域名&#xff0c;需要实名认证才能开启 DNS 解析。而在国外域名提供商买的域名则不用。指向中国大陆内的云服务器的域名提供的网站&#xff0c;必须备案才能正常被访问。但是任何指向国外服务器的域名却可以不受此规则的限制。Vercel 是一…

小白快速搭建 ChatGpt

小白快速搭建 ChatGpt 前言一、页面展示二、前期准备1.魔法账号2.GitHub账号3.Vercel账号 三、项目部署1.GitHub复制项目到自己的仓库2.Vercel添加项目1&#xff09;创建项目2&#xff09;导入项目3&#xff09;环境变量配置4&#xff09;Deploy 和 Ccontinue to DashBoard 即可…

如何快速搭建一款自用的chatgpt-web网站

文章目录 前言一、准备工作二、开始搭建1.node安装2.拉取源码 三、总结 前言 ChatGPT 是一款由 OpenAI 开发的聊天机器人&#xff0c;可以用自然语言与用户进行交互。它基于 GPT 模型&#xff0c;拥有非常强大的语言生成能力&#xff0c;可以在许多场景中被广泛应用&#xff0…

ChatGPT列出全球最强的10个国家,中国排名意外

近日&#xff0c;ChatGPT横空出世&#xff0c;算是彻底火出了圈。 有人把这款“聊天软件”形容为上知天文、下知地理&#xff0c;能编代码&#xff0c;还会写诗作词&#xff0c;简直是无所不能。遇事不决&#xff0c;问问ChatGPT似乎成了一种流行。这不&#xff0c;小编也向Cha…

[ChatGPT]意大利成为首个封禁ChatGPT的国家,这代表了什么

前言 几天前&#xff0c;意大利国家数据机构——意大利个人数据保护局&#xff08;DPA&#xff09; DPA以“非法收集个人资料&#xff1b;未成年人年龄核实系统缺失”之名宣布禁用ChatGPT。DPA声称&#xff0c;对ChatGPT可能侵犯隐私以及未能按要求验证用户年龄为13岁或以上表…

意大利成首个封禁ChatGPT的国家!OpenAI CEO:我觉得没违规

【导读】周五&#xff0c;意大利全国上下对ChatGPT下了封杀令。在20天内&#xff0c;OpenAI拿不出补救措施的话&#xff0c;将会面临最高2000万欧元罚款。 就在昨天&#xff0c;意大利政府突然下令&#xff0c;封禁ChatGPT&#xff01; 很快&#xff0c;OpenAI首席执行官Sam …