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系统相关的安全更新,做好课题背景相关研究。实现图案锁的破解。

posted @ 2020-03-15 23:59  Gst丶Paul  阅读(169)  评论(0编辑  收藏  举报