Android Programming:从零开始的安卓编程

Android Programming

须知

这篇文档是一个萌新初步学习了Android Programming之后做的总结,如果你也是从零开始学习Android编程,你需要知道:

  1. Android官方文档和csdn大佬的博客是你永远应该优先考虑参考的对象

  2. 必须同步阅读菜鸟教程或通过其他方式(b站大学)对android programming有一个初步的了解,包括Android资源组织,Java基本语法和活动、服务、广播分别是什么。

    Android 教程 | 菜鸟教程 (runoob.com)

  3. 你需要提前配置好Java编程环境,然后再下载Android Studio IDE,这一切我是在window操作系统完成的

Android Studio(IDE)

版本选择

在官网首页下最新版,需要配置Java环境(推荐jre 8和jdk 11)

存在的问题
  1. MainActivity默认是.kt文件,直接删除或者后缀改成.java

  2. res目录下缺少layout目录(layout相当于一个屏幕画板),在res上右键新建文件夹(directory)命名为layout,在新建的layout目录上右键新建Layout Resourse File,一般主画板通用命名为activity_main.xml。可选LinearLayout(线性布局)和RelativeLayout(相对布局),常用RelativeLayout。

  3. 当然res下同样缺少menu(菜单)目录,如果程序中需要用到,可以提前在res中新建menu文件夹,再新建menu_main.xml文件

  4. 新版本默认的SDK(30以上)和Android(10以上)版本都很高,有可能遇到版本问题

  5. debug示例:无报错信息一直闪退

    android:theme="@style/Theme.something”
    <!--改成-->
    android:theme="@style/Theme.AppCompat”
    

第一个Android程序:Hello World

android studio上实现Hello world 史上最全,最简单明了的教程_android studio hello world 在哪-CSDN博客

Android Hello World实例 |菜鸟教程 (runoob.com)

活动 Activity

概念

描述UI以及用户与机器屏幕的交互

回调方法
回调描述
onCreate()这是第一个回调,在活动第一次创建时调用
onDestroy()当活动被系统销毁之前调用
注意事项

一个应用程序可以有1个或多个活动,而没有限制,每个为应用程序所定义的活动都需要在AndroidManifest.xml中声明。应用的主要活动需要在清单中声明,且中需要包含MAIN动作和LAUNCHER类别

菜鸟教程实操

你需要跟着教程一步步实现Activity的基本服务

Android 活动(Activity) |菜鸟教程 (runoob.com)

服务Service

概述

处理与应用程序相关联的后台操作

服务是在后台运行的组件,即使应用被销毁也依然可以工作。服务包含两种状态

*状态**描述*
StartedAndroid的应用程序组件,如活动,通过startService()启动了服务,则服务是Started状态。一旦启动,服务可以在后台无限期运行,即使启动它的组件已经被销毁。
Bound当Android的应用程序组件通过bindService()绑定了服务,则服务是Bound状态。Bound状态的服务提供了一个客户服务器接口来允许组件与服务进行交互,如发送请求,获取结果,甚至通过IPC来进行跨进程通信。
服务的生命周期
  1. onCreate,onStart,onDestroy

  2. onCreate,onBind,onUnbind,[onRebind,onDestroy

要创建一个服务,你需要一个继承自Service基类或者它已知子类的Java类,显然你不需要重载所有回调方法

*回调**描述*
onStartCommand()其他组件(如活动)通过调用startService()来请求启动服务时,系统调用该方法。如果你实现该方法,你有责任在工作完成时通过stopSelf()或者stopService()方法来停止服务。
onBind当其他组件想要通过bindService()来绑定服务时,系统调用该方法。如果你实现该方法,你需要返回IBinder对象来提供一个接口,以便客户来与服务通信。你必须实现该方法,如果你不允许绑定,则直接返回null。
onUnbind()当客户中断所有服务发布的特殊接口时,系统调用该方法。
onRebind()当新的客户端与服务连接,且此前它已经通过onUnbind(Intent)通知断开连接时,系统调用该方法。
onCreate()当服务通过onStartCommand()和onBind()被第一次创建的时候,系统调用该方法。该调用要求执行一次性安装。
onDestroy()当服务不再有用或者被销毁时,系统调用该方法。你的服务需要实现该方法来清理任何资源,如线程,已注册的监听器,接收器等。
菜鸟教程实例

你需要跟着教程一步步实现Service的基本服务,同时也会学到关于menu,layout和button的小知识

Android 服务(Service) |菜鸟教程 (runoob.com)

广播与接收器 Broadcast Receiver

概念

广播用来处理Android操作系统和应用程序之间的通信

广播接收器用于响应来自其他应用程序或者系统的广播消息

  • 创建和注册广播接收器
  • 创建和广播意图(Intent)
静态注册广播接收器

以注册一个接收开机广播的Receiver为例

<receiver android:name=”.My Receiver”
          android:enabled="true"
          android:exported="true"
          android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter>
         <action android:name="android.intent.action.BOOT_COMPLETED">
         </action>
      </intent-filter>
</receiver>

上方授予权限(Permission)

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
package com.smali.secretchallenge;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;

import java.time.LocalDate;

public class SecretBootReceiver extends BroadcastReceiver {
    private static final String TAG = "SecretBootReceiver";
    @Override
    public void onReceive(Context context, Intent intent){
        if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {

            Log.d(TAG, "已经启动");
            Toast.makeText(context, "检测到意图", Toast.LENGTH_LONG).show();
            context.startService(new Intent(context,SecretService.class));
        }
    }
}
动态注册广播接收器

1.一篇很详细的博客:Android广播(接收,发送,标准,有序,全局,本地,实战,填坑)_android 广播-CSDN博客

2.官方文档:广播概览 | Background work | Android Developers (google.cn)

静态注册注意事项!!!

Android 8.0后,静态注册的接收器无法接收到隐式广播,但是我们发出的广播默认都为隐式的,因此需要调用setPackage方法指定此广播发送给应用程序,让其变成显示广播(tips:如果用户自定义广播,多用动态法注册)

//发送广播
Intent intent = new Intent("com.example.viewmodeltest.MY_BROADCAST_RECEIVER");
            intent.setPackage(getPackageName());
        	sendOrderedBroadcast(intent, null);
        });

adb命令行

adb命令能够帮助你模拟开机自启动的情况

adb shell 命令行模拟发送开机广播android.intent.action.BOOT_COMPLETED测试开机自启动_am broadcast -a android.intent.action.boot_complet-CSDN博客

AVD(安卓虚拟机)启动后,在Android Studio下方的window终端输入

adb root
adb shell am broadcast -a android.intent.action.BOOT_COMPLETED -p com.smali.secretchallenge

权限 Permission

//请求获得权限
//Manifest.permission.ACCESS_FINE_LOCATION(精确位置权限)可替换成任意权限名
if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
    //请求权限
   requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION},0);
}
else {
   Toast.makeText(this,"已经获得权限",Toast.LENGTH_LONG).show();
}
从接收器启动服务
context.startService(new Intent(context,SecretService.class));
位置服务
```
		if (checkSelfPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED ){
            Toast.makeText(this, "服务未获得位置权限", Toast.LENGTH_LONG).show();
			//未获得权限的操作
            //...
            // 例如ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_CODE_LOCATION);
        }
        else {
            Toast.makeText(this, "服务获得位置权限", Toast.LENGTH_LONG).show();
            //获得位置权限的操作
            //...
        }

```
```
//获取位置服务
            LocationManager locationManager = (LocationManager)                getSystemService(Context.LOCATION_SERVICE);
            LocationListener locationListener=new LocationListener() {
                @Override
                public void onLocationChanged(@NonNull Location location) {
                    double lat = location.getLatitude();//获取纬度
                    double lng = location.getLongitude();//获取经度
                    Log.d("Location", "Latitude: " + lat + ", Longitude: " + lng);
                }
                @Override
                public void onStatusChanged(String provider, int status, Bundle extras) {
                }
                @Override
                public void onProviderEnabled(String provider) {
                }
                @Override
                public void onProviderDisabled(String provider) {
                }
            };
     locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,0,0,locationListener);

Snackbar消息

构建并显示弹出式消息 | Android 开发者 | Android Developers (google.cn)

为什么要用
  1. 轻量级的消息,快速
  2. 可以结合按钮处理点击事件
需要导入的库
import com.google.android.material.snackbar.Snackbar;

在build.gradle中

implementation 'com.google.android.material:material:1.9.0'

必须要注意的是:

​ 版本,版本,还是tmd版本

在老版本中,有个叫design的库也在干和material同样的事情,chatGPD这个老东西往往会给你推荐这个库,但是如果你用的是androidX库的话和design是互相冲突的,因为我是一直致力于使用新版本这里也不再介绍design的用法了。

使用CoordinatorLayout

如果Snackbar附加到派生自View类的任何对象,它会提供基本的功能:弹出弹窗。不过如果Snackbar附加到CoordinatorLayoutSnackbar会获得额外的功能

  • 用户可以通过滑动把Snackbar关闭
  • Snackbar 出现时,布局会移动其他界面元素。例如,如果布局具有 FloatingActionButton,则当显示 Snackbar 时,布局会将按钮向上移动,而不是在按钮上绘制 Snackbar

如果你已经使用了其他的布局对象,可以将现有的布局元素封装再CoordinatorLayout中

<!-和Android官方唯一的不同:没用design库--->
<androidx.coordinatorlayout.widget.CoordinatorLayout
    android:id="@+id/myCoordinatorLayout"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- Here are the existing layout elements-->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        
        <!-- ...Toolbar, other layouts, other elements... -->
    </LinearLayout>

</android.support.design.widget.CoordinatorLayout>
显示消息
Snackbar mySnackbar = Snackbar.make(view, stringId, duration);
mySnackbar.show();

view:可以传递窗口上任意的View类对象或者是

View view=findViewById(R.id.myCoordinatorLayout);

如果您使用的是CoordinatorLayout

stringId:这里以String值传递您想要打印的消息

duration

处理 Handler

延时启动

处理Handler和运行Runnable

Android中Handler延迟执行、定时任务_handle明明设置了隔20秒执行一次,但是过了60多秒才执行-CSDN博客

线程Thread

Android开发中Thread线程的基本使用(总结)_android中实现线程tread的两种方法是什么-CSDN博客

通知 Nortification

通知为低权限应用提供了在后台发出消息的能力

Android开发之Notification(实现消息弹窗、提示音以及点击事件)_android通知栏弹出消息-CSDN博客

创建通知 | Android 开发者 | Android Developers (google.cn)

步骤
  1. 创建通知隧道channel

    private void createNotificationChannel() {
            // Create the NotificationChannel, but only on API 26+ because
            // the NotificationChannel class is not in the Support Library.
            CharSequence name = getString(R.string.channel_name);
            String description = getString(R.string.channel_description);
            int importance = NotificationManager.IMPORTANCE_HIGH;
            NotificationChannel channel = new NotificationChannel("channel_one", name, importance);
            channel.setDescription(description);
    
            NotificationManager notificationManager = getSystemService(NotificationManager.class);
            notificationManager.createNotificationChannel(channel);
        }
    
  2. 创建通知

    //通过点击可以跳转到你的MainActivity
    Intent intent = new Intent(SecretService.this, MainActivity.class);
                        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
                        PendingIntent pendingIntent = PendingIntent.getActivity(SecretService.this, 0, intent, PendingIntent.FLAG_IMMUTABLE);
    
                        builder = new NotificationCompat.Builder(SecretService.this, "channel_one")//隧道名要和你定义的隧道相同
                                .setContentTitle("Location")
                                .setContentText(msg)
                                .setSmallIcon(R.drawable.ic_launcher_background)
                                .setPriority(NotificationCompat.PRIORITY_MAX)
                                // Set the intent that fires when the user taps the notification.
                                .setContentIntent(pendingIntent)
                                .setAutoCancel(true);
                        NotificationManagerCompat notificationManager = NotificationManagerCompat.from(SecretService.this);
                        notificationManager.notify(1,builder.build());
    
  3. 发送通知

    NotificationManagerCompat notificationManager = NotificationManagerCompat.from(SecretService.this);
    notificationManager.notify(1,builder.build());
    
前台服务 ForeService

支持直接从后台启动?

可能的解决方案:JobSchedulerWorkManager,ForeServive

Task 2

task内容:在处理Button点击事件时,在屏幕上打印editText的内容

Dialog

对话框是提示用户做出决定或输入更多信息的小窗口。对话框不会填满屏幕,通常用于需要用户执行操作才能继续的模态事件。

对话框 | Android 开发者 | Android Developers

Handler异步通信

Android异步通信:手把手教你使用Handler消息传递机制(含实例讲解)_android sendmessage 异步-CSDN博客

EditText

android 如何获取输入框内容 - CSDN文库
如何获取输入框内容 1 获取 EditText 控件对象:2.使用 findViewById (),对象转换为 String:3.使用 toString () 方法将 Editable 对象转换为 String。

消息,处理和消息队列

完全解析Android:Looper与Handler机制 - 掘金 (juejin.cn)

package com.smali.secretchallenge2;

import android.app.Dialog;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {
    public Handler mhandler;
    public EditText mEditText;
    public String inputText;
    class Mhandler extends Handler {
        @Override
        public void handleMessage(Message msg){
            switch (msg.what){
                case 1:
                    AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
                    builder.setMessage(msg.obj.toString());
                    final AlertDialog dialog = builder.create();
                    dialog.show();
                    break;
            }
        }
    }
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //获取到EditText
        mEditText=findViewById(R.id.editText1);
        //实例化Handler
        mhandler=new Mhandler();
    }
    public void showDialog(View view){
        inputText=mEditText.getText().toString();
        Log.d("文本内容",inputText);
        //启动一个新线程
        new Thread(){
            @Override
            public void run(){
                Message msg=Message.obtain();
                msg.what=1;
                inputText=mEditText.getText().toString();
                msg.obj=inputText;
                mhandler.sendMessage(msg);
                //下次检查时退出线程
                Thread.currentThread().interrupt();
            }
        }.start();
    }
}
存在的问题

现在的实现每次点击都会启动一个额外的线程,虽然也不是不行,但是还是不太规范,正确的做法是用循环器Looper在一个线程中循环启动Handler,这样只需要在主活动的onCreate方法中启动一次线程Thread
在处理点击事件时,向消息队列中发送一个消息即可。

  • 16
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Title: Android Programming: The Big Nerd Ranch Guide, 3rd Edition Author: Bill Phillips, Chris Stewart Length: 624 pages Edition: 3 Language: English Publisher: Big Nerd Ranch Guides Publication Date: 2017-02-09 ISBN-10: 0134706056 ISBN-13: 9780134706054 Table of Contents Chapter 1. Your First Android Application Chapter 2. Android and Model-View-Controller Chapter 3. The Activity Lifecycle Chapter 4. Debugging Android Apps Chapter 5. Your Second Activity Chapter 6. Android SDK Versions and Compatibility Chapter 7. UI Fragments and the Fragment Manager Chapter 8. Displaying Lists with RecyclerView Chapter 9. Creating User Interfaces with Layouts and Widgets Chapter 10. Using Fragment Arguments Chapter 11. Using ViewPager Chapter 12. Dialogs Chapter 13. The Toolbar Chapter 14. SQLite Databases Chapter 15. Implicit Intents Chapter 16. Taking Pictures with Intents Chapter 17. Two-Pane Master-Detail Interfaces Chapter 18. Localization Chapter 19. Accessibility Chapter 20. Data Binding and MVVM Chapter 21. Unit Testing and Audio Playback Chapter 22. Styles and Themes Chapter 23. XML Drawables Chapter 24. More About Intents and Tasks Chapter 25. HTTP and Background Tasks Chapter 26. Loopers, Handlers, and HandlerThread Chapter 27. Search Chapter 28. Background Services Chapter 29. Broadcast Intents Chapter 30. Browsing the Web and WebView Chapter 31. Custom Views and Touch Events Chapter 32. Property Animation Chapter 33. Locations and Play Services Chapter 34. Maps Chapter 35. Material Design Chapter 36. Afterword

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值