20165320 毕业设计 第三周总结

20165320 毕业设计 第三周总结

任务及完成情况

周一 周二 周三 周四 周五 周六 周天
Android开发基础学习
开题答辩
修改开题报告
Android开发基础学习
文献翻译
Android开发基础学习
撰写总结博客
已完成
已完成
已完成
已完成
已完成
已完成
已完成

内容总结

一、Android开发基础

1、系统架构
  • Linux内核层

    • Android系统的最底层,为Android设备的硬件设施提供相应的驱动,比如相机驱动。
  • 系统运行库层

    • 这一层主要包括一些C/C++库为Android系统提供功能上的支持。

    • 同时还包括Android运行时所必需的核心库,允许开发人员使用Java语言来编写Android应用程序。

    • Dalvik虚拟机,每个Android程序运行时会启动一个新的Dalvik虚拟机,保证各进程的独立性。与在PC端运行的Java虚拟机不同,Dalvik虚拟机是针对移动设备定制的,并进行了相应的优化。(Android5.0系统后改为ART运行环境)

  • 应用框架层

    • 提供构建应用程序时可能用到的各种API。
  • 应用层

    • 安装在Android手机中的各种应用程序。
2、开发环境搭建(第一周已完成,略过)
3、一个Android项目的主要文件目录构成
  • build:包含一些在编译时自动生成的文件,无需过多关心。

  • libs:项目中使用到的第三方Jar包存放在此目录下,会被自动添加到构建路径里。

  • androidTest:编写测试用例用的。

  • java:存放所有Java代码的地方。

  • res:存放项目中使用到的所有资源文件。包含以下子目录:

    • drawable:图片。
    • layout:布局。
    • values:字符串。
    • mipmap:图标。
  • AndroidManifest.xml:整个Android项目的配置文件,程序中定义的组件都需要在这个文件中注册,同时可以给程序添加权限声明(非常重要,之后逆向的学习也会用到)。

  • build.gradle:APP模块的gradle构建脚本。

  • proguard-rules.pro:用于指定项目代码的混淆规则,之后学习Android应用保护手段的时候也会用到。

4、日志工具的使用
  • Android中的日志工具类是Log(Android.util.Log),提供以下五种方法打印日志:

    • Log.v()。打印最为琐碎的日志信息。对应的级别为verbose。
    • Log.d()。用于打印一些调试信息,对应级别为debug。
    • Log.i()。用于打印一些比较重要的数据,帮助分析用户行为数据。对应的级别为info。
    • Log.w()。用于打印一些警告信息,提示程序在这个地方可能会有潜在的风险。对应的级别为warn。
    • Log.e()。打印程序中的错误信息,比如程序进入catch语句当中时。对应级别为error。
  • 在Hello World项目中加入如下代码试用:

      Log.d("MainActivity","onCreate execute");
    • 结果如图所示:
5、资源文件的引用
  • 两种方式如下:

    • 在代码中通过R.文件名获得该引用。
    • 在XML中通过@id名获得该引用。

二、探究活动

1、项目中的任何活动都应该重写onCreate方法。
    @Override
    protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState)
    }
2、活动的注册
  • 需要在AndroidManifest.XML文件中进行注册。(AS中,创建一个新活动后会默认自动帮你注册好)

      <activity android:name=".活动名"></activity/>
3、主活动
  • 程序运行时首先运行的活动。需要在 标签中加入 标签,内容如下:

      <action android:name="android.intent.action.MAIN"/>
    <category android:name="android.intent.category.LAUNCHER" />
4、Intent组件
  • 是Android程序中各组件之间进行交互的重要方式,还可以在不同组件中传递数据,一般用于启动活动,启动服务以及发送广播等场景。分为显式Intent和隐式Intent。

  • 常用函数:

    • Intent(Context packageContext,Class<?>cls),第一个参数要求提供一个启动活动的上下文,第二个参数指定想要启动的目标活动。(显式)

    • Intent(String action,String category),第一个参数与第二个参数分别对应AndroidManifest.XML文件中定义的acntion标签名与category标签名。

    • 生成Intent对象后,通过调用startActivity()方法即可执行Intent。

    • setResult()方法接受两个参数,第一个参数用于向上一个活动返回处理结果,第二个参数把带有数据的Intent传递回去。

  • 标签能配置一个 标签,更精确地指定当前活动能够响应什么类型的数据。

    • android:scheme。数据的协议部分,如http。
    • android:host。数据的主机名部分,比如 www.baidu.com。

    • android:port。数据的端口部分,一般紧随主机名后
    • android:path。域名之后的部分
    • android:mimeType。可以处理的数据类型。

  • 通过Intent传递数据,需要利用Intent对象的putExtra()方法的重载。示例如下:

          FirstActivity.class
    
        String data = "Hello SecondActivity";
        Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
        intent.putextra("extra_data",data);
        startActivity(intnet);
    
        SecondActivity.class
    
        Intent intent = getIntent();  //通过getintent方法获取启动SecondActivity的Intent
        String data = intent.getStringExtra("extra_data");
        Log.d("SecondActivity",data);

  • 使用startActivityForResult()方法来启动Activity,返回上一个活动时会回调onActivityResult()方法,需要重写该方法。

    • 第一个参数为使用startActivityForResult()方法启动活动时的请求码。

    • 第二个参数为返回数据的处理结果。

    • 第三个参数为携带返回数据的Intent。

    简单实例如下:

          protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
          super.onActivityResult(requestCode, resultCode, data);
          switch (requestCode) {
          case 1:
              if (requestCode == RESULT_OK) {
                  String returnData = data.getStringExtra("data_retun");
                  Log.d("FirstActivity", returnData);
              }
              break;
          default:
              }
          }

  • 接上一条,如果是点击返回键,将数据传回,在==SecondActivity==中重写onBackPressed()方法,在该方法中添加返回数据的逻辑。

5、活动的生命周期
  • Activity类中定义了7个回调方法,覆盖活动生命周期的每一个环节。

    • onCreate()。该方法会在活动第一次被创建的时候调用,需要在此方法中完成活动的初始化操作,比如加载布局、绑定事件。

    • onStart()。该方法在不可见变为可见的时候调用。

    • onResume()。活动准备好与用户进行交互的时候调用,此时活动一定位于返回栈的栈顶,并且处于运行状态。

    • onPause()。这个方法在系统准备去启动或者恢复另一个活动的时候调用。通常在此方法中将一些消耗CPU的资源释放掉,以及保存一些关键数据。

    • onStop()。活动完全不可见的时候调用,与onPause()的区别在于,如果启动的新活动是一个对话框式的活动,那么onPause()方法会得到执行,onStop()不会得到执行。

    • onDestroy()。这个方法在活动被销毁之前调用,之后活动的状状态变为销毁状态。

    • onRestart()。这个方法在活动由停止状态变为运行状态之前调用,也就是活动被重新启动。

  • 完整生存周期:

  • 例子运行结果:

6、如何保存被回收活动中的数据
  • 当一个活动进入停止状态时,可能会被回收,为了保存临时数据,需要使用到onSaveInstanceState()回调方法。

  • onSaveInstanceState()方法会携带一个Bundle类型的参数,它提供了一系列方法用于保存数据。

      @Override
      protected void onSaveInstanceState(Bundle){
          super.onSaveInstanceState(outState);
          String temData = "Something you just typed";
          outState.putString("data_key",tempData);
      }
7、活动的启动模式
  • 修改方法:在 标签中,修改launchMode条目:

      android:launchMode = "模式名"
  • standard是活动默认的启动模式,每当启动一个新的活动,它就会在返回栈中入栈,并处于栈顶的位置,每次都会创建该活动的一个新实例。

    • 如图所示:
  • singleTop模式在启动活动时会检测返回栈的栈顶,如果是栈顶已经是该活动,则直接使用,不会创建新的实例,但不足之处是只检查了栈顶。

    • 如图所示:
  • singleTask模式每次在启动该活动之前,都会在返回栈中检查是否存在该活动的实例,如果发现存在则直接使用,并把活动之上的所有活动统统出栈,如果没有则创建一个新的活动实例。

    • 如图所示:
  • singleInstance模式下,启动的活动会启用一个新的返回栈来管理,这中模式的意义在于实现不同应用之间共享活动实例。

    • 如图所示:

三、UI开发

1、TextView控件
  • 属性标签

    • android:id:唯一标识符
    • android:layout_width:控件宽度
    • android:layout_height:控件高度
    • android:text:控件显式地文本内容
    • android:gravity:文字对齐方式
    • android:textSize:文字大小,使用sp为单位
    • textColor:文字颜色
2、Button控件
  • 属性标签

    • android:textAllCaps="false":禁用大写转换
  • 注册监听器的两种方法:

    • Button.setOnClickListener(new View.onClickListener){
      @Override
      public void onClick(View v){
      //此处添加逻辑
      }
      }

    • 使用实现接口的方式进行注册:implements View.OnClickListener{}

3、EditText控件
  • 程序用于和用户交互的重要控件,允许用户在控件里输入和编辑内容。

  • 属性标签

    • android:hint:提示性文本

    • android:maxLines:最大行数

4、ImageView控件
  • 用于在界面上展示图片的一个控件,图片通常保存在drawable目录下。

  • 属性标签

    • android:src:图片源
  • 特别注意:Android Studio资源目录中,为不同分辨率的图片建立了不同的文件夹,如果没有对应,可能运行会出错。

      java.lang.RuntimeException: Canvas: trying to draw too large(?bytes) bitmap
5、ProgressBar
  • 用于在界面上显示一个进度条,表示程序正在加载一些数据。

  • 属性标签:

    • android:visibility:是否可见
    • style:进度条的样式
6、AlertDialog
  • 该控件可以在当前的界面弹出一个对话框,这个对话框是置顶于所有界面元素之上的,一般用于提示一些非常重要的内容与警示信息。

  • 常用方法:

    • AlertDialog.Builder():创建一个AlertDialog实例。

    • setPositiveButton():为对话框的确定按钮设置点击事件。

    • setNegative():为对话框设置取消按钮的点击事件。

  • 使用实例:

      AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this);
    dialog.setTitle("This is Dialog");
    dialog.setMessage("Something important");
    dialog.setCancelable(false);
    dialog.setPositiveButton("OK",new DialogInterface.OnClickListener(){
          @Override
          public void onClick(DialogInterface dialog,int which){
    
                 }
              });
          dialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
          @Override
          public void onClick(DialogInterface dialog, int which) {
    
              }
          });
    dialog.show();
  • ProgresDialog与AlertDialog类似,不同点在于它会在对话框中显式一个进度条,

7、四种基本布局
  • 布局与控件的关系:

  • 线性布局:LinearLayout,这个布局会将它所有包含的控件在线性方向上依次排列。

    • 属性标签:

      • android:orientation:指定排列方向
      • android:layout_gravity:指定控件的对齐方式
      • android:layout_weight:使用比例的方式指定控件的大小,其规则是将weight值相加,然后每个控件所占大小的比例就是用该控件的weight值除以总值。
  • 相对布局:RelativeLayout通过相对定位的方式,让控件出现在布局的任何位置

    • 属性标签:

      • android:layout_alignParent+方向:和父布局的某一个位置对齐。
      • android:layout_方向:让一个控件位于另一个控件的某个方向(当一个控件引用另一个控件的id时,该控件一定要定义在引用控件的后面)
      • android:layout_align+方向:让某一控件的边缘与另一控件的边缘对齐
  • 帧布局:FrameLayout,这种布局默认所有的控件都是位于左上角。应用场景比较少。

  • 百分比布局:为FrameLayout与Relative进行的功能扩展,需要在项目的build.gradle中添加百分比布局库的依赖。

8、自定义控件
  • 常用控件与布局的继承关系

  • 引入布局可以解决代码重复的问题,直接在布局文件中include即可。

    • 属性标签:

      • android:layout_marginLeft:指定控件偏移的距离
  • 创建自定义控件可以省去在每一个活动中,为控件添加响应事件

    • 首先需要新建一个类,成为自定义控件。

    • 重写相关构造函数,借助LayoutInflater的inflate()方法动态加载布局文件。第一个参数是加载的布局id,第二个参数是父布局。

    • 随后在布局文件中通过完整的类名来引用。

9、ListView(难点)
  • Android最常用也是最难用的控件之一,解决手机屏幕空间有限的问题。

  • ListView中的数据需要通过适配器来传递进去,其中最常用的是ArrayAdapter。

    • 首先通过泛型指定要适配的数据类型,然后通过构造函数把要适配的数据传入。

    • 其构造函数第一个参数为上下文,第二个参数ListView子项布局的id,第三个参数为需要传入的数据。

    • 最后通过调用ListView的setAdapter()方法,将构建好的适配器对象传递进去。

  • 自定义的适配器需要继承ArrayAdapter,并且重写getView()方法。该方法在每个子项被滚动到屏幕内的时候会被调用。

  • ListView控件可以使用setOnItemClickListener()方法注册监听器:

      ListView.setOnitemClickListener(new AdapterView.OnitemClickListener(){
          @Override
          public void onItemClick(AdapterView<?> parent,View view,int position,long id){
              //逻辑
          }
      }
  • 利用RecyclerView编写一个简单的聊天界面:

四、广播机制

1、简介
  • Android中每个应用程序都可以对自己感兴趣的广播进行注册,这样该程序就只会接受到自己所关心的广播内容,这些广播来自系统或者其它应用程序。主要有两种类型:

    • 标准广播:完全异步执行的广播,发出之后,所有接收器几乎同时接收,效率高,无法截断。

    • 有序广播:同步执行的广播,发出之后同一时刻只有一个广播接受器能够收到这条消息,当这个接收器中的逻辑执行完毕后,广播才会继续传递。并且前面的接收器可以截断正在传递的广播。

2、接收系统广播
  • 动态注册:新建一个继承自BroadcastReceiver类,并重写父类的onReceive(Context context,Intent intent)方法。之后调用registerReceiver()方法对接收器进行注册,传入相应的实例。最后,动态注册的广播接收器一定都要取消注册,调用unregisterReceiver()方法来实现的。PS:程序有敏感操作时,需要在AndroidManifest.xml文件中声明。

    • 简单实例:

        public class MainActivity extends AppCompatActivity {
        private IntentFilter intentFilter;
        private NetworkChangeReceiver networkChangeReceiver;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            intentFilter = new IntentFilter();
            intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
            networkChangeReceiver = new NetworkChangeReceiver();
            registerReceiver(networkChangeReceiver,intentFilter);
        }
        @Override
        public void onDestroy(){
            super.onDestroy();
            unregisterReceiver(networkChangeReceiver);
        }
        class NetworkChangeReceiver extends BroadcastReceiver{
            @Override
            public void onReceive(Context context, Intent intent){
                Toast.makeText(context,"network changes",Toast.LENGTH_SHORT).show();
            }
        }
        }
  • 静态注册:动态注册的广播接收器可以自由控制注册与注销,但前提是程序启动后才能接收,因为逻辑写在onCreate()方法中。这个时候,静态注册就能完成程序未启动时的广播接收工作。

    • 使用AS的快捷方式创建一个广播接收器,并重写onReceive()方法,随后在AndroidManifest.xml文件中添加intent-filter过滤器,指定接收的广播action。

    • PS:Android8.0以后,对静态注册的广播接收器需要明确指出处理Intent的组件信息。参考资料

3、发送自定义广播
  • 发送标准广播

    • 首先需要调用Intent的构造方法构造出一条广播信息,action参数与广播接收器相对应,随后调用setComponent()方法明确指出接收该条广播的组件信息,最后调用sendBroadcast()方法发送。

    • 简单实例:

        Intent intent = new Intent("com.example.broadcasttest.MY_BROADCAST");
      intent.setComponent(new ComponentName("com.example.broadcasttest", "com.example.broadcasttest.MyBroadcastReceiver"));
      sendBroadcast(intent);
  • 发送有序广播

    • 将sendBroadcast()方法改为sendOrderedBroadcast(intent,null),第二个参数是与权限相关的字符串。

    • 在AndroidManifest.xml文件中,接收器的 标签中加入android:priority属性,设置优先级。

    • 如果需要截断广播,在onReceive()方法中调用abortBroadcast()方法。

4、使用本地广播
  • 为了能够简单地解决广播的安全问题,Android引入了本地广播机制,使用这个机制发出的广播只能够在应用程序的内部进行传递,并且广播接收器也只能接收来自本应用程序发出的广播,核心是使用LocalBroadcastManager来对广播进行管理,并提供发送广播和注册广播接收器的方法。

  • PS:LocalBroadcastManager类需要导入 androidx.appcompat扩展库。

待解决的问题&下周的计划

问题:

  • 这周开始了Android应用开发的基础学习,虽然有一定的Java基础,但还是存在一定代码阅读的困难。同时由于内容多,时间紧,学习计划也得做一定的调整,不能死扣一些细枝末节的原理,掌握大致的流程就先过,不然后面安全方面的学习时间可能不够。

下周的计划

  • 完成Android应用开发的基础知识学习,主要包括四大组件中剩下的内容提供器与服务的学习,以及Webview的使用。

  • 学习Android系统安全机制,以及近年来Android系统相关的安全更新,做好课题背景相关研究。实现图案锁的破解。

猜你喜欢

转载自www.cnblogs.com/Gst-Paul/p/12501248.html