Android开发从0开始(ContentProvider与数据)

news2024/11/16 23:31:15

内容提供者:ContentProvider

  为App存取内部数据提供外部接口,让不同应用共享数据。

①在配置里AndroidManifest.xml       

 <provider

            android:name=".UserInfoProvider"

            android:authorities="com.example.chapter07_server.provider.UserInfoProvider"

            android:enabled="true"

            android:exported="true"/>

危险权限表

运行时动态申请权限Lazy模式:

①检查是否开启指定权限:

public class PermissionUtil {

    //检查权限,返回true则已完全启用权限,返回false表示未完全启用权限

    public static boolean checkPermission(Activity act,String[] permissions,int requestCode)

    {

        int check = PackageManager.PERMISSION_GRANTED;

        //逐一将各个权限取出判断

        for(String permission: permissions){

            ContextCompat.checkSelfPermission(act,permission);

            check=ContextCompat.checkSelfPermission(act,permission);

            if(check!=PackageManager.PERMISSION_GRANTED){break;}

        }

  //②若有未开启的权限,则请求系统弹窗

        if (check!=PackageManager.PERMISSION_GRANTED){

            ActivityCompat.requestPermissions(act,permissions,requestCode);

            return false;

        }

            return true;   }  }

  ③判断用户的权限选择结果

    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        //判断用户是否授权

        switch (requestCode){

            case REQUEST_CODE_CONTACTS:

                if(PermissionUtil.checkGRant(grantResults)){

                    Log.d("ning","通讯录权限获取成功");

                }else

                {

                    Log.d("ning","获取通讯录读写权限失败");

                }

                break;

            case REQUEST_CODE_SMS:

                if (PermissionUtil.checkGRant(grantResults)){

                    Log.d("ning","收发短信权限获取成功");

                }else

                {

                    Log.d("ning","收发短信权限获取失败");

  jumpToSetting();

                }

                break;    }    }

    //跳转带应用设置界面

    private  void jumpToSetting(){

        Intent intent = new Intent();

        intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);

        intent.setData(Uri.fromParts("package",getPackageName(),null));

        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        startActivity(intent);

    }

运行时动态申请权限Hunger模式:直接在onCreate中申请所有权限。

ContentResovler基本用法

添加联系人:

public void onClick(View view) {

        int id = view.getId();

        if (id == R.id.add) {//创建一个联系人对象

            Contact contact = new Contact();

            contact.name= et_name.getText().toString().trim();

            contact.email=et_email.getText().toString().trim();

            contact.phone=et_phone.getText().toString().trim();

            //方法一,使用ContentResolver多次写入.

            addContacts(getContentResolver(),contact);

        } else if (id == R.id.find) {

        }

}

    //往手机通讯录里添加一个联系人

    private void addContacts(ContentResolver resolver, Contact contact) {

        ContentValues values = new ContentValues();

        Uri uri= resolver.insert(ContactsContract.RawContacts.CONTENT_URI,values);

        long rawContactId = ContentUris.parseId(uri);

        ContentValues name = new ContentValues();

        //关联联系人编号

        name.put(Contacts.Data.RAW_CONTACT_ID,rawContactId);

        //"姓名"数据类型

        name.put(Contacts.Data.MIMETYPE,CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);

        //联系人的姓名

        name.put(Contacts.Data.DATA2,contact.name);

        //往提供器添加联系人姓名

        resolver.insert(ContactsContract.Data.CONTENT_URI,name);

        ContentValues phone = new ContentValues();

        //关联联系人编号

        phone.put(Contacts.Data.RAW_CONTACT_ID,rawContactId);

        //"电话号码"数据类型

        phone.put(Contacts.Data.MIMETYPE,CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);

        //联系人的电话号码

        phone.put(Contacts.Data.DATA2,contact.phone);

        phone.put(Contacts.Data.DATA2,CommonDataKinds.phone.TYPE_MOBILE);

        //往提供器添加联系人姓名电话号码

        resolver.insert(ContactsContract.Data.CONTENT_URI,phone);

        ContentValues email = new ContentValues();

        //关联联系人编号

        email.put(Contacts.Data.RAW_CONTACT_ID,rawContactId);

        //"邮箱"数据类型

        email.put(Contacts.Data.MIMETYPE,CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);

        //联系人的邮箱

        email.put(Contacts.Data.DATA2,contact.email);

        //往提供器添加联系人邮箱

        resolver.insert(ContactsContract.Data.CONTENT_URI,email);

    }

批量处理添加联系人:

private void addFullContacts(ContentResolver resolver , Contact contact){

        //构建一个插入联系人主记录的内容操作器

        ContentProviderOperation op_main=ContentProviderOperation

                .newInsert(ContactsContract.RawContacts.CONTENT_URI)

                .withValue(ContactsContract.RawContacts.ACCOUNT_NAME,null)

                .build();

      //构建对于姓名的操作

      ContentProviderOperation op_name= ContentProviderOperation

              .newInsert(ContactsContract.RawContacts.CONTENT_URI)

              .withValueBackReference(Contacts.Data.RAW_CONTACT_ID,0)

              .withValue(Contacts.Data.MIMETYPE,CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)

              .withValue(Contacts.Data.DATA2,contact.name)

              .build();

        //构建对于电话号码操作

        ContentProviderOperation phone= ContentProviderOperation

                .newInsert(ContactsContract.RawContacts.CONTENT_URI)

                .withValueBackReference(Contacts.Data.RAW_CONTACT_ID,0)

                .withValue(Contacts.Data.MIMETYPE,CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)

                .withValue(Contacts.Data.DATA2,contact.phone)

                .build();

        //构建对于邮箱的操作

        ContentProviderOperation email= ContentProviderOperation

                .newInsert(ContactsContract.RawContacts.CONTENT_URI)

                .withValueBackReference(Contacts.Data.RAW_CONTACT_ID,0)

                .withValue(Contacts.Data.MIMETYPE,CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)

                .withValue(Contacts.Data.DATA2,contact.email)

                .build();

        //构建列表将三个操作放入

        ArrayList<ContentProviderOperation> operations=new ArrayList<>();

        operations.add(op_main);

        operations.add(op_name);

        operations.add(phone);

        operations.add(email);

        //批处理提交四个操作

        try {

            resolver.applyBatch(ContactsContract.AUTHORITY,operations);

        } catch (OperationApplicationException e) {

            throw new RuntimeException(e);

        } catch (RemoteException e) {

            throw new RuntimeException(e);      }    }

批量查询联系人:

     //查询通讯录信息

    @SuppressLint("Range")

    private void readPhoneContacts(ContentResolver resolver ) {

      Cursor cursor= resolver.query(ContactsContract.RawContacts.CONTENT_URI,new String[]{ContactsContract.RawContacts._ID},null,null,null,null);

      while (cursor.moveToNext()){

          int rawContactId = cursor.getInt(0);

          Uri uri = Uri.parse("content://com.android.contacts/contacts"+rawContactId+"/data");

        Cursor dataCursor=resolver.query(uri,new String[]{Contacts.Data.MIMETYPE,Contacts.Data.DATA1,Contacts.Data.DATA2},null,null,null);

        Contact contact = new Contact();

        while (dataCursor.moveToNext()){

           String data1= dataCursor.getString(dataCursor.getColumnIndex(Contacts.Data.DATA1));

           String mimeType=dataCursor.getString(dataCursor.getColumnIndex(Contacts.Data.MIMETYPE));

           switch (mimeType){

               case CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE:

                   contact.name=data1; break;

               case CommonDataKinds.Email.CONTENT_ITEM_TYPE:

                   contact.Email=data1; break;

               case CommonDataKinds.Phone.CONTENT_ITEM_TYPE:

                   contact.Phone=data1; break;

           }

        }

        dataCursor.close();

      }

      cursor.close();   }

ContentObserver监听短信:

  public class MonitorSmsActivity extends AppCompatActivity {

    private SmsGetObserver mObserver;

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_monitor_sms);

        //指定一个注册内容观察器,一单数据发生变化,就触发OnChange方法

        Uri uri = Uri.parse("content://sms");

        mObserver = new SmsGetObserver(this);

        getContentResolver().registerContentObserver(uri,true,mObserver);

    }

    protected void onDestroy(){

        super.onDestroy();

        getContentResolver().unregisterContentObserver(mObserver);

    }

    private static class SmsGetObserver extends ContentObserver {

        private final Context mContext;

        public SmsGetObserver(Context context){

            super(new Handler(Looper.getMainLooper()));

            this.mContext=context;   }

public void onChange(boolean selfChange, @Nullable Uri uri){

            super.onChange(selfChange,uri);   

            if(uri==null){return;}

            if(uri.toString().contains("content://sms/raw")||uri.toString().equals("content://sms")) {return;}

            Cursor cursor = mContext.getContentResolver().query(uri, new String[]{"address", "body", "date"}, null, null, "date DESC");

            if(cursor.moveToNext()){

                //短信的发送号码

                @SuppressLint("Range")  String sender=cursor.getString(cursor.getColumnIndex("address"));

                @SuppressLint("Range")  String content=cursor.getString(cursor.getColumnIndex("body"));

                Log.d("ning",String.format("sender:%s,content:%s",sender,content));

            }

            cursor.close();

        }

    }   }

跳转选择图片:

  ①创建意图

  Intent intent = new Intent(Intent.ACTION_GET_CONTENT );

②设置图片内容类型与跳转

Intent.setType(image/*);

mResultLauncher.launch(intent );

FileProvider:

 继承于ContentProvider,对第三方应用暴露文件,并授权读写操作的权限。

①首先在AndroidManifest.xml文件中配置

        <provider

            android:authorities="@string/file_provider"

            android:name="androidx.core.content.FileProvider"

            android:grantUriPermissions="true">

        <!--配置哪些路径是可以通过FileProvider访问-->

            <meta-data android:name="android.support.FILE_PROVIDER_PATHS"

                android:resource="@xml/file_paths"/>

        </provider>

②其次在对应路径xml的文件夹中的file_paths中写配置文件。

③在代码中对应实现。  

访问其他程序中的数据:

  ①使用现有的内容提供器来读取和操作相应的程序数据

  ②创建自己的内容提供器给我们程序的数据提供外部访问接口。

Notification通知栏的使用:

   Notification notification = new Notification.Builder(this)

         .setContentTitle("this is content title") //指定通知栏标题内容

         .setContentText("this is content text")//指定通知栏正文内容

         .setWhen(System.currentTimeMillis())//创建时间

         .setSmallIcon(R.mipmap.ic_launcher) //通知栏小图标

         .setLargeIcon(BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher))

                    .build(); //通知栏大图标

           manager.notify(NOTIFICATION_ID, notification); //通道号要提前创建

                       参数1:通道号  参数2:notification对象

PendingIntent延迟意图:

   方法1:getActivity()

   方法2:getBroadcast()

   方法3:getService()

以上均为三个参数:参1:Context 。参2:一般不用传0。参数3:意图

参数4:确定行为FLAG_ONESHOT,FLAG_NO_CREATE,FLAG_CANCEL,FLAG_UPDATE_CURRENT通常可以填0.

点击后图标消失:

①在后部分调用.setAutoCancel( true )方法

②在onCreate中

NotificationManager manager = (Notif icat ionManager) getSystemService

(NOTIFICATION_ SERVICE) ; //注册管理器

manager . cancel((NOTIFICATION_ID); . //注册取消。

调用摄像头

  ①创建File对象,用于存储。

  ②调用getExternalCacheDir( )方法获取目录。

  ③做版本适配

  ④用intent去启动摄像头。

注意调用都有权限注册。

播放音频:

一般使用MediaPlayer类实现,常用方法如下

调用播放视频

一般使用VideoView类的方法。

数据存储部分:

 共享参数-SharedPreferences:轻量级存储工具,Key-Value形式。

使用场景:

  ①简单且孤立的数据。

  ②文本形式数据。

  ③需要持久化存储的数据。

  ④App个性化配置信息,用户使用App行为信息。

  ⑤临时片段信息。

 getSharedPreferences("config", Context.MODE_PRIVATE);

①然后先ALT+ENTER声明成变量,再Ctrl+ALT+F变全局

private SharedPreferences preferences;

preferences = getSharedPreferences("config", Context.MODE_PRIVATE);

//在下面监听

public void onClick(View view) {

        String name = et_name.getText().toString();

        String age = et_age.getText().toString();

        String height = et_height.getText().toString();

        String weight = et_weight.getText().toString();

        //获取编辑器

        SharedPreferences.Editor editor = preferences.edit();

        editor.putString("name",name);

        editor.putInt("age", Integer.parseInt(age));

        editor.putFloat("height",Float.parseFloat(height));

        editor.putFloat("weight",Float.parseFloat(weight));

        editor.putBoolean("married",gr_married.isChecked());

        editor.commit();

}

②重新再取数据:(通过键值对取)

        String name= preferences.getString("name","");

SQLite

(1) 数据定义语言

CREATE TABLE IF NOT EXISTS 表名(

字段A PRIMARY KEY

字段B,

字段C

支持类型

NULL:表示空值。

INTEGER:表示整数,可以存储整数值。

REAL:表示浮点数,可以存储浮点数值。

TEXT:表示文本,可以存储字符串。

BLOB:表示二进制数据,可以存储任意二进制数据。

(2)删除表格:

 DROP TABLE IF EXISTS user_info

(3)修改表格:

ALTER TABLE user_info ADD COLUMN phone VARCHAR;

(只支持增加字段,不支持修改,删除字段)添加多列就分多次。

(4)数据操作语言与其他数据库相似

  1. SQLite Database 数据库管理器

  1,管理类:

  OpenDatabase():打开指定路径数据库。

  isOpen():判断数据库是否已经打开。

Close():关闭数据库。

getVersion():获取版本。

SetVersion():设置数据库版本。

  2,事务类:

beginTransaction:开始事物。

SetTransactionSuccessful:设置事务的成功标志.

endTransaction:结束事务。

创建数据库,删除数据库:

①首先在全局生命这个数据库名

private String mDataBaseName;

mDataBaseName = getFilesDir() + "/test.db";

    public void onClick(View view) {

      int id = view.getId();

      if (id == R.id.btn_database_create) {

            //打开数据库,参数1:数据库名地址+名字,参数2:打开模式,参数3:游标

SQLiteDatabase db = openOrCreateDatabase(mDataBaseName, Context.MODE_PRIVATE, null);

            //输出化语言:

String desc = String.format("数据库%s创建%s", db.getPath(), (db != null) ? "成功" : "失败");

            tv_database.setText(desc);}

else if (id == R.id.btn_database_delete) {

            //删除数据库

            boolean result = deleteDatabase(mDataBaseName);

String desc_fail = String.format("数据库%s删除%s", mDataBaseName, result ? "成功" : "失败");

tv_database.setText(desc_fail);   }    }

数据库所在路径:data->data->包名->file

页面与数据库交互SQLiteOpenhelper

两个抽象方法: onCreate ( ), onUpgrade ( )

两个重要实例方法getReadableDatabase( ), getWritableDatabase( )。均可创建或打开数据库。

(6)事务管理:(一致性,原子性)

  beginTransaction:开始事务.

  setTransactionSuccessful:设置事务的成功标志.

endTransaction:结束事务.

若事务失败泽会回滚操作,保证原子性。

  1. 外部存储空间

定义部分

import java.io.BufferedReader;

import java.io.BufferedWriter;

import java.io.File;

import java.io.FileReader;

import java.io.FileWriter;

import java.io.IOException;

import java.nio.Buffer;

public class FileUtil {

    //把字符串保存到指定路径

    public static void saveText(String path,String txt){

        BufferedWriter os =null;  //创建一个os

        try {os = new BufferedWriter(new FileWriter(path));  //new一个对象,其中包含指定路径

            os.write(txt);                                  //将txt 写入该路径

        }catch (Exception e){

            e.printStackTrace();

        }finally {

            if (os!=null)

            {

                try {

                    os.close();

                }catch (IOException e){

                    e.printStackTrace();

                }

            }

        }

    }

    //从指定路径读取内容字符串

    public static String openText(String path){

        BufferedReader is=null;

        StringBuilder sb =new StringBuilder();

        try {

            is =new BufferedReader(new FileReader(path));

            String line = null;

            while ((line=is.readLine())!=null){

                sb.append(line);

            }

        }catch (Exception e){

            e.printStackTrace();

        }finally {

            if (is!=null)

            {

                try {

                    is.close();

                }catch (IOException e){

                    e.printStackTrace();

                }

            }

        }

        return sb.toString();

    }

}

引用部分:

      //外部存储的私有空间写入

  String directory = null; //创建一个字符串

  String fileName = System.currentTimeMillis()+".txt"; //创建一个当前时间的文件名

  directory = getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString(); //获取路径

  path =directory + File.separatorChar+fileName;  //构建完整路径

                FileUtil.saveText(path,sb.toString());          //进行保存

                ToastUtil.show(this,"保存成功");

//外部存储的私有空间读出

tv_txt.setText(FileUtil.openText(path))

外部存储公有空间:还要手机获取权限

directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString();

(7)存储卡上读写图片文件

BitmapFactory工具用于读取各种来源的图片:相关方法如下:

decodeResource:该方法可从资源文件中读取图片信息。

DecodeFile:该方法可将指定路径的图片读取到Bitmap对象。

DecodeStream:该方法从输入流中读取位图数据。

①定义触发保存事件

    public void onClick(View view) {

        int id = view.getId();

        if (id == R.id.btn_save) {

            String fileName = System.currentTimeMillis() + ".jpeg";

            //获取当前App的私有下载目录

            path = getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString() + File.separatorChar + fileName;

            //从指定资源文件获取位图像对象

            Bitmap b1 = BitmapFactory.decodeResource(getResources(), R.drawable.ting1);

            //将位图对象保存下来

            FileUtil.saveImage(path, b1);

            ToastUtil.show(this, "保存成功");

        } else if (id == R.id.btn_read) {

            Bitmap b2 = FileUtil.openImage(path);

            iv_content.setImageBitmap(b2);

         }    }

②对应保存

   //把位图数据保存到指定路径的图片文件

    public static void saveImage(String path, Bitmap b1) {

        FileOutputStream fos = null;

        try{

            fos=new FileOutputStream(path);

            //把位图数据压缩到文件流中

            b1.compress(Bitmap.CompressFormat.JPEG,100,fos);}

        catch (Exception e){ e.printStackTrace(); }finally {

            //关闭输入输出流

            if(fos!=null){

                try {   fos.close();   }catch (IOException e){

                    e.printStackTrace();  }  }   }   }

③读取相应位图

    //从指定路径读取位图数据

    public static Bitmap openImage(String path) {

            Bitmap bitmap=null;

            FileInputStream fis=null;

            try {

                fis =new FileInputStream(path);

                bitmap = BitmapFactory.decodeStream(fis);

            }catch (Exception e){

                e.printStackTrace();

            }finally {

                if (fis!=null){

                    try {

                        fis.close();

                    }catch (IOException e)

                    {

                        e.printStackTrace();

                    }      }     }  return bitmap; }

(8)Application生命周期

  在App运行过程中有且仅有一个Application对象,贯穿生命周期。

public class MyApplication extends Application {

    //在APP启动时调用

    @Override

    public void onCreate() {

        super.onCreate();

        Log.d("ning","onCreate");

    }

    //APP终止(在真实的产品不会回调)

    @Override

    public void onTerminate() {

        super.onTerminate();

        Log.d("ning","onTerminate");

    }

    //配置改变时调用

    @Override

    public void onConfigurationChanged(@NonNull Configuration newConfig) {

        super.onConfigurationChanged(newConfig);

    }

}

  1. Application全局变量

适用于会频繁读取的信息,如用户名,手机号。

不方便由意图传输的数据,例如位图对象,非字符串类型。

容易因频繁分配内存导致的内存泄漏的对象,Handler等。可以采用单例模式。

操作:

  • private static MyApplication mApp;  //定义一个私有静态的实例MyApplication名为app
  • public static MyApplication getInstance(){   return mApp; }//获取单例,返回mApp
  • public void onCreate() {

super.onCreate();   mApp = this; }//在oncreate里实例化,将this指针地址给mApp

④在外部再调用MyApplication.getInstance();

  1. JetPackRoom:

Room框架通过注解技术简化数据库操作

在build.gradle的dependencies中配置    

implementation 'androidx.room:room-runtime:2.2.5'// 导入 Room 依赖库

annotationProcessor 'androidx.room:room-compiler:2.2.5'// 导入注解处理器 ( Java )

编写一个表对应的实体类Bookinfo

package com.example.myapplication.enity;

import androidx.room.Entity;

import androidx.room.PrimaryKey;

@Entity

public class Bookinfo {

    @PrimaryKey(autoGenerate = true) //自动增长

    private int id;

    private String name;

    private String author;

    private String press;

    private  double price;

    public int getId() {

        return id;

    }

    public void setId(int id) {

        this.id = id;

    }

    public String getName() {

        return name;

    }

    public void setName(String name) {

        this.name = name;

    }

    public String getAuthor() {

        return author;

    }

    public void setAuthor(String author) {

        this.author = author;

    }

    public String getPress() {

        return press;

    }

    public void setPress(String press) {

        this.press = press;

    }

    public double getPrice() {

        return price;

    }

    public void setPrice(double price) {

        this.price = price;

    }

    @Override

    public String toString() {

        return "Bookinfo{" +

                "id=" + id +

                ", name='" + name + '\'' +

                ", author='" + author + '\'' +

                ", press='" + press + '\'' +

                ", price=" + price +

                '}';

    }

}

③编写一个表对应的持久化类BookDao的接口。会自动生产类。

package com.example.myapplication.dao;

import androidx.room.Dao;

import androidx.room.Delete;

import androidx.room.Insert;

import androidx.room.Query;

import androidx.room.Update;

import com.example.myapplication.enity.Bookinfo;

import java.util.List;

@Dao

public interface BookDao {

    @Insert

    void insert(Bookinfo... book);

    @Delete

    void delete(Bookinfo... book);

    @Query("DELETE FROM Bookinfo")

    void deleteAll();

    @Update

    int update(Bookinfo... book);

    @Query("SELECT * FROM bookinfo ")

    List<Bookinfo>queryAll();

    @Query("SELECT * FROM bookinfo WHERE name = :name ORDER BY id DESC limit 1")

    Bookinfo queryByName(String name);

}

④创建一个抽象类:BookDatabase

@Database(entities = {Bookinfo.class},version = 1,exportSchema = true)

public abstract class BookDatabase extends RoomDatabase {

    //获取该数据库中某张表的持久化对象

public abstract BookDao bookDao();   }

⑤在自定义的Application类中声明书籍数据库的唯一实例。

  public class RoomWriteActivity extends AppCompatActivity implements View.OnClickListener {

    private EditText shuming;

    private EditText zuozhe;

    private EditText chubanshe;

    private EditText jiage;

private BookDatabase bookDB;

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_room_write);

        shuming = findViewById(R.id.shuming);

        zuozhe = findViewById(R.id.zuozhe);

        chubanshe = findViewById(R.id.chubanshe);

        jiage = findViewById(R.id.jiage);

        findViewById(R.id.btn_chaxun).setOnClickListener(this);

        findViewById(R.id.btn_shanchu).setOnClickListener(this);

        findViewById(R.id.btn_tianjia).setOnClickListener(this);

        findViewById(R.id.btn_xiugai).setOnClickListener(this);

        //从App实例中获取唯一的书籍持续化对象

        bookDB = MyApplication.getInstance().getBookDB();

    }

    @Override

    public void onClick(View view) {

        String  name=shuming.getText().toString();

        String  author=zuozhe.getText().toString();

        String  press=chubanshe.getText().toString();

        String  price=jiage.getText().toString();

        int id = view.getId();

        if (id == R.id.btn_tianjia) {

            Bookinfo b1 = new Bookinfo();

            b1.setName(name);

            b1.setAuthor(author);

            b1.setPress(press);

            b1.setPrice(Double.parseDouble(price));

            bookDao.insert(b1);

        } else if (id == R.id.btn_xiugai) {

            List<Bookinfo> list= bookDao.queryAll();

            for(Bookinfo b:list){

                Log.d("ning",b.toString());

            }

        } else if (id == R.id.btn_shanchu) {

        } else if (id == R.id.btn_chaxun) {

        }

    }

}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

springboot+vue基本微信小程序的旅游社系统

项目介绍 现今市面上有关于旅游信息管理的微信小程序还是比较少的&#xff0c;所以本课题想对如今这么多的旅游景区做一个收集和分类。这样可以给身边喜欢旅游的朋友更好地推荐分享适合去旅行的地方。 前端采用HTML架构&#xff0c;遵循HTMLss JavaScript的开发方式&#xff0…

MySQL数据库入门到大牛_基础_14_视图及基本操作

本章开始将会介绍表之外的数据库对象。 文章目录 1. 常见的数据库对象2. 视图概述2.1 为什么使用视图&#xff1f;2.2 视图的理解 3. 创建视图3.1 创建单表视图3.2 创建多表联合视图3.3 基于视图创建视图 4. 查看视图5. 更新视图的数据5.1 一般情况5.2 不可更新的视图 6. 修改…

3款免费次数多且功能又强大的国产AI绘画工具

hi&#xff0c;同学们&#xff0c;本期是我们第55 期 AI工具教程 最近两个月&#xff0c;国内很多AI绘画软件被关停&#xff0c;国外绝大部分AI绘画工具费用不低&#xff0c;因此 这两天我 重新整理 国产 AI绘画 工具 &#xff0c; 最终 筛选了 3款功能强大&#xf…

[每周一更]-(第74期):Docker-compose 部署Jenkins容器-英文版及错误纠错

1、前文概要 通过物理机部署Jenkins前文已经讲过&#xff08;地址&#xff1a;[Jenkins] 物理机 安装 Jenkins&#xff09;&#xff0c;也已经公司内部平稳运行若干年&#xff0c;考虑到容器化的使用场景&#xff0c;部分项目都采用容器运行&#xff0c;开始考虑部署容器化的J…

JAVA毕业设计112—基于Java+Springboot+Vue的宠物领养社区小程序(源码+数据库)

基于JavaSpringbootVue的宠物领养社区小程序(源码数据库)112 一、系统介绍 本系统前后端分离带小程序 小程序&#xff08;用户端&#xff09;&#xff0c;后台管理系统&#xff08;管理员&#xff09; 小程序&#xff1a; 登录、注册、宠物领养、发布寻宠、发布领养、宠物社…

数据黑洞,正在悄悄吞噬你的门店业绩

互联网兴起以来&#xff0c;线下门店的数字化程度始终落后于线上。一个重要的原因是&#xff1a;线下信息不像线上那样简单、集中、易于统计。很多重要数据隐藏于「黑洞」之中&#xff0c;收集和分析成本极为高昂。这极大束缚了门店业绩的提升。 而反过来看&#xff0c;线下场景…

2023亚太杯数学建模A题思路分析 - 采果机器人的图像识别技术

1 赛题 问题A 采果机器人的图像识别技术 中国是世界上最大的苹果生产国&#xff0c;年产量约为3500万吨。与此同时&#xff0c;中国也是世 界上最大的苹果出口国&#xff0c;全球每两个苹果中就有一个&#xff0c;全球超过六分之一的苹果出口 自中国。中国提出了一带一路倡议…

基于亚马逊云科技大语言模型等服务打造企业知识库

背景 大语言模型是自然语言处理领域的一项重要技术&#xff0c;能够通过学习大量的文本数据&#xff0c;生成具有语法和意义的自然语言文本。目前大语言模型已经成为了自然语言处理领域的一个热门话题&#xff0c;引起了广泛的关注和研究。 知识库需求在各行各业中普遍存在&a…

1)业务平台集成电子签章平台

1.前言 电子签章平台随着企业数字化转型逐步渗透到日常运营项目中&#xff0c;如合同盖章/规章制度发布/法审意见等场景下引入电子章解决盖章需求。 作为特定业务下的统一处理方案&#xff0c;需要在业务管理平台与电子签章平台之间构建一个桥梁&#xff0c;简化电子签章平台…

Hadoop学习总结(MapReduce的数据去重)

现在假设有两个数据文件 file1.txtfile2.txt2018-3-1 a 2018-3-2 b 2018-3-3 c 2018-3-4 d 2018-3-5 a 2018-3-6 b 2018-3-7 c 2018-3-3 c2018-3-1 b 2018-3-2 a 2018-3-3 b 2018-3-4 d 2018-3-5 a 2018-3-6 c 2018-3-7 d 2018-3-3 c 上述文件 file1.txt 本身包含重复数据&…

测试Bard和ChatGPT对双休有关法规的认知和简单推理

Bard是试验品&#xff0c;chatgpt是3.5版的。 首先带着问题&#xff0c;借助网络搜索&#xff0c;从政府官方网站等权威网站进行确认&#xff0c;已知正确答案的情况下&#xff0c;再来印证两个大语言模型的优劣。 想要了解的问题是&#xff0c;在中国&#xff0c;跟法定工作…

什么是轻量应用服务器?可以从亚马逊云科技的优势入手了解

什么是轻量应用服务器&#xff1f; 随着如今各行各业对云计算的需求越来越多&#xff0c;云服务器也被越来越多的企业所广泛采用。其中&#xff0c;轻量应用服务器是一种简单、高效、可靠的云计算服务&#xff0c;能够为开发人员、企业和个人提供轻量级的虚拟专用服务器&#x…

Adobe 家族系列download

adobe 前言 Adobe公司的产品线中拥有多个家族桶&#xff0c;下面是Adobe全家桶产品的功能介绍&#xff1a; Creative Cloud&#xff08;创意云&#xff09;&#xff1a;包含Photoshop、Illustrator、InDesign、Premiere Pro、After Effects、Lightroom等创意设计、视频制作和…

解决LocalDateTime传输前端为时间的数组

问题出现如下&#xff1a; 问题出现原因&#xff1a; 默认序列化情况下会使用SerializationFeature.WRITE_DATES_AS_TIMESTAMPS。使用这个解析时就会打印出数组。 解决方法&#xff1a; 我在全文搜索处理方法总结如下&#xff1a; 1.前端自定义函数来书写 ,cols: [[ //表头{…

制造业6S管理方法的卓越价值

在现代制造业中&#xff0c;高效管理和生产流程的优化对企业的成功至关重要&#xff0c;其中&#xff0c;6S管理方法作为精益生产的关键组成部分&#xff0c;为企业提供了卓越的管理模式。下面将深入探讨6S管理方法的价值&#xff0c;特别聚焦于周转箱和工具柜在精益生产中的优…

物流实时数仓:数仓搭建(ODS)

系列文章目录 物流实时数仓&#xff1a;采集通道搭建 物流实时数仓&#xff1a;数仓搭建 文章目录 系列文章目录前言一、IDEA环境准备1.pom.xml2.目录创建 二、代码编写1.log4j.properties2.CreateEnvUtil.java3.KafkaUtil.java4.OdsApp.java 三、代码测试总结 前言 现在我们…

6.显示评论 + 添加评论

1.显示评论 数据层&#xff1a;根据实体查询一页评论数据、根据实体查询评论的数量业务层&#xff1a;处理查询评论的业务、处理查询评论数量的业务表现层&#xff1a;显示帖子详情数据时&#xff0c;同时显示该帖子所有的评论数据 1.1 数据访问层 entity_type&#xff1a;实体…

小红书达人等级有哪些,不同粉丝量有什么区别?

小红书的种草能力和社区加电商的模式&#xff0c;使得越来越多品牌将目光放在小红书笔记上。而在平台的营销与传播&#xff0c;多是借助达人进行的&#xff0c;今天为大家分享下小红书达人等级有哪些&#xff0c;不同粉丝量有什么区别&#xff1f; 一、小红书达人等级划分 虽然…

医院手术麻醉信息系统全套源码,自主版权,支持二次开发

医院手术麻醉信息系统全套商业源码&#xff0c;自主版权&#xff0c;支持二次开发 手术麻醉信息系统是HIS产品的中的一个组成部分&#xff0c;主要应用于医院的麻醉科&#xff0c;属于电子病历类产品。医院麻醉监护的功能覆盖整个手术与麻醉的全过程&#xff0c;包括手术申请与…

uniapp实现多时间段设置

功能说明&#xff1a; 1 点击新增时间&#xff0c;出现一个默认时间段模板&#xff0c;不能提交 2 点击“新增时间文本”&#xff0c;弹出弹窗&#xff0c;选择时间&#xff0c;不允许开始时间和结束时间同时为00:00&#xff0c; <view class"item_cont"> …