主頁 > 移動端開發 > 安卓使用服務完成音樂播放器

安卓使用服務完成音樂播放器

2020-12-24 10:09:03 移動端開發

安卓音樂播放器

  • 使用Service后臺服務實作播放器
      • 自定義封裝Music類
      • 利用Fragment+RadioGroup實作頁面
      • 自定義Music類
      • 配接器
        • 音樂展示布局檔案
      • Fragment音樂界面整體效果布局
        • Fragment代碼

使用Service后臺服務實作播放器

package com.example.day121lx;

import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.MediaPlayer;
import android.os.Binder;
import android.os.IBinder;
import android.widget.RemoteViews;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class MyService extends Service {
    private MediaPlayer mediaPlayer;
    private int index=0;
    private int playmusic=1;

    private List<Music> list=new ArrayList<>();
    public MyService() {
    }

    @Override
    public void onCreate() {
        super.onCreate();
         mediaPlayer = new MediaPlayer();
        list = MusicUtil.getDate(this);
    }

    class MyBinder extends Binder{
        public void callplay(int position){
            play(position);
        }

        //暫停播放 在Fragment里邊呼叫方法
        public int zt(){
            mediaPlayer.pause();
            return 0;
        }
        //繼續播放 在Fragment里邊呼叫方法
        public int jx(){

            mediaPlayer.start();
            return 0;
        }

        //上一首 在Fragment里邊呼叫方法
        public void shang(){
            if (--index<=0){

                index=list.size()-1;
            }

            play(index);

        }

        //下一首 在Fragment里邊呼叫方法
        public void next(){
            if (++index>=list.size()){
                index=list.size();
                index=0;
            }
            play(index);

        }
        //進度條
        public void seekbar(int p){
            mediaPlayer.seekTo(p);
        }

        //進度條最大值
        public int getMax(){
         return mediaPlayer.getDuration();

        }
        //進度條當前位置
        public int getp(){

            return mediaPlayer.getCurrentPosition();
        }

        //判斷播放模式 在Fragment里邊呼叫方法
        public void flish(int i){
            mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                @Override
                public void onCompletion(MediaPlayer mp) {
                    switch (playmusic){
                        case MusicUtil.SHUNXU:
                            next();
                            break;

                        case MusicUtil.SUIJI:
                            int i = new Random().nextInt(list.size());
                            play(i);
                            break;

                        case MusicUtil.DANQU:
                            play(index);
                            break;

                    }
                }

            });
            playmusic=i;

            //注冊廣播
            MyBro myBro = new MyBro();//廣播接收者
            IntentFilter intentFilter = new IntentFilter();
            intentFilter.addAction("com.wang");
            registerReceiver(myBro,intentFilter);
        }

    }

    @SuppressLint("WrongConstant")
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        
        //通知上邊音樂界面
        Notification.Builder builder = new Notification.Builder(this);
       builder.setSmallIcon(R.mipmap.ic_launcher);
       //遠程布局
        RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.inf_layout);
       builder.setCustomContentView(remoteViews);
        
        Intent intent1 = new Intent();
        intent1.setAction("com.wang");
        PendingIntent broadcast = PendingIntent.getBroadcast(this, 0, intent1, 0);


        remoteViews.setOnClickPendingIntent(R.id.zanting,broadcast);
        startForeground(1,builder.build());
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public IBinder onBind(Intent intent) {

       return new MyBinder();
    }

    //開始播放音樂 在Fragment里邊呼叫方法
    public void play(int position){
        mediaPlayer.reset();
        index=position;
        try {
            mediaPlayer.setDataSource(list.get(position).getData());
            mediaPlayer.prepareAsync();
            mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                @Override
                public void onPrepared(MediaPlayer mp) {
                    mediaPlayer.start();
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
    //廣播接收者
    class MyBro extends BroadcastReceiver{
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (action.equals("com.wang")){
                mediaPlayer.pause();
            }

        }
    }
}

自定義封裝Music類

package com.example.day121lx;

import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.provider.MediaStore;

import java.util.ArrayList;
import java.util.List;

public class MusicUtil {
    public static final int DANQU=3;
    public static final int SUIJI=2;
    public static final int SHUNXU=1;



    public static List<Music> getDate(Context context) {
        List<Music> list = new ArrayList<>();

        //內容決議者
        ContentResolver contentResolver = context.getContentResolver();
        //查詢本地音樂檔案
        Cursor query = contentResolver.query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, null, null, null);
        if (query != null) {
            while (query.moveToNext()) {
                String title = query.getString(query.getColumnIndex(MediaStore.Audio.Media.TITLE));
                String artist = query.getString(query.getColumnIndex(MediaStore.Audio.Media.ARTIST));
                String duration = query.getString(query.getColumnIndex(MediaStore.Audio.Media.DURATION));
                String data = query.getString(query.getColumnIndex(MediaStore.Audio.Media.DATA));
                String size = query.getString(query.getColumnIndex(MediaStore.Audio.Media.SIZE));
                String albumId = query.getString(query.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID));
                Music music = new Music(title, artist, duration, data, size, albumId);
                list.add(music);

            }
            query.close();
        }
        return list;
    }


    //獲取專輯圖片
    public static String getPic(Context context,String albumId){
        ContentResolver contentResolver = context.getContentResolver();
        Uri parse = Uri.parse("content://media/external/audio/albums/" + albumId);

        Cursor query = contentResolver.query(parse, null, null, null, null);
        if (query!=null){
            boolean b = query.moveToNext();
            if (b){
                String album_art = query.getString(query.getColumnIndex("album_art"));
                return album_art;
            }
            query.close();
        }
        return null;
    }


    //同步音樂時長
    public static String fmtTime(String s){
        int i = Integer.parseInt(s);
        if (i / 1000 % 60 < 10){
            return i / 1000 / 60 +":0" + i / 1000 % 60;
        }
        return i /1000 /60 +":" + i / 1000 % 60;
    }
}

利用Fragment+RadioGroup實作頁面

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".Main4Activity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/a11"
       android:layout_weight="8"
        android:orientation="vertical"
        ></LinearLayout>

    <RadioGroup
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_gravity="bottom"
        android:id="@+id/group"
        >

        <RadioButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="音樂"
        android:button="@null"
            android:drawableTop="@drawable/style1"
            android:gravity="center"
            android:layout_weight="1"
        android:id="@+id/a1"
        ></RadioButton>

        <RadioButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="音樂"
            android:gravity="center"
            android:drawableTop="@drawable/style1"
            android:button="@null"
            android:layout_weight="1"
            android:id="@+id/a2"
            ></RadioButton>

        <RadioButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="音樂"
            android:drawableTop="@drawable/style1"
            android:gravity="center"
            android:layout_weight="1"
            android:button="@null"
            android:id="@+id/a3"
            ></RadioButton>

        <RadioButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="音樂"
            android:button="@null"
            android:gravity="center"
            android:drawableTop="@drawable/style1"
            android:layout_weight="1"
            android:id="@+id/a4"
            ></RadioButton>
    </RadioGroup>

</LinearLayout>
blic class Main4Activity extends AppCompatActivity {
    private LinearLayout a11;
    private RadioGroup group;
    private RadioButton a1;
    private RadioButton a2;
    private RadioButton a3;
    private RadioButton a4;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main4);

        FragmentManager supportFragmentManager = getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction();
        fragmentTransaction.add(R.id.a11,new BlankFragment4());
        fragmentTransaction.commit();

        a11 = (LinearLayout) findViewById(R.id.a11);
        group = (RadioGroup) findViewById(R.id.group);
        a1 = (RadioButton) findViewById(R.id.a1);
        a2 = (RadioButton) findViewById(R.id.a2);
        a3 = (RadioButton) findViewById(R.id.a3);
        a4 = (RadioButton) findViewById(R.id.a4);



        group.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                switch (checkedId){
                    case R.id.a1:
                        FragmentManager supportFragmentManager = getSupportFragmentManager();
                        FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction();
                        fragmentTransaction.replace(R.id.a11,new BlankFragment4());
                        fragmentTransaction.commit();

                        break;

                    case R.id.a2:

                        FragmentManager supportFragmentManager1 = getSupportFragmentManager();
                        FragmentTransaction fragmentTransaction1 = supportFragmentManager1.beginTransaction();
                        fragmentTransaction1.replace(R.id.a11,new BlankFragment5());
                        fragmentTransaction1.commit();
                        break;
                }
            }
        });



    }
}

自定義Music類

package com.example.day121lx;

public class Music {
    private String title;
    private String artist;
    private String duartion;
    private String data;
    private String size;
    private String albumId;
    private Integer id;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    @Override
    public String toString() {
        return "Music{" +
                "title='" + title + '\'' +
                ", artist='" + artist + '\'' +
                ", duartion='" + duartion + '\'' +
                ", data='" + data + '\'' +
                ", size='" + size + '\'' +
                ", albumId='" + albumId + '\'' +
                ", id=" + id +
                '}';
    }

    public Music(Integer id) {
        this.id = id;
    }

    public Music(String title, String artist, String duartion, String data, String size, String albumId) {
        this.title = title;
        this.artist = artist;
        this.duartion = duartion;
        this.data = data;
        this.size = size;
        this.albumId = albumId;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getArtist() {
        return artist;
    }

    public void setArtist(String artist) {
        this.artist = artist;
    }

    public String getDuartion() {
        return duartion;
    }

    public void setDuartion(String duartion) {
        this.duartion = duartion;
    }

    public String getData() {
        return data;
    }

    public void setData(String data) {
        this.data = data;
    }

    public String getSize() {
        return size;
    }

    public void setSize(String size) {
        this.size = size;
    }

    public String getAlbumId() {
        return albumId;
    }

    public void setAlbumId(String albumId) {
        this.albumId = albumId;
    }

    public Music() {
    }
}

配接器

package com.example.day121lx;

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import com.bumptech.glide.Glide;

import java.util.List;

public class MyAdapter extends BaseAdapter {

    private List<Music> list;
    private Context context;

    public MyAdapter(List<Music> list, Context context) {
        this.list = list;
        this.context = context;
    }

    @Override
    public int getCount() {
        return list.size();
    }

    @Override
    public Object getItem(int position) {
        return list.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder=null;
        if (convertView==null){
            holder=new ViewHolder();
            convertView = convertView.inflate(context, R.layout.lv_layout, null);
             holder.title = convertView.findViewById(R.id.title);
             holder.artist = convertView.findViewById(R.id.artist);
            holder.duration  = convertView.findViewById(R.id.duration);
            holder.lv_img  = convertView.findViewById(R.id.lv_img);
            convertView.setTag(holder);

        }else {
             holder = (ViewHolder) convertView.getTag();
        }

        Music music=list.get(position);
        holder.artist.setText(music.getArtist());
        holder.title.setText(music.getTitle());
        holder.duration.setText(MusicUtil.fmtTime(list.get(position).getDuartion()));
        Glide.with(context).load(MusicUtil.getPic(context,music.getAlbumId())).into(holder.lv_img);

        return convertView;
    }

    class ViewHolder{
        TextView title;
        TextView artist;
        TextView duration;
        ImageView lv_img;

    }
}

音樂展示布局檔案

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        >
        <ImageView
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:src="@mipmap/ic_launcher"
            android:id="@+id/lv_img"
            ></ImageView>

        <TextView
            android:layout_width="100dp"
            android:layout_height="wrap_content"
            android:text="111"
            android:id="@+id/title"
            ></TextView>

        <TextView
            android:layout_width="100dp"
            android:layout_height="wrap_content"
            android:text="222"
            android:id="@+id/artist"
            android:layout_marginLeft="100dp"
            ></TextView>

        <TextView
            android:layout_width="100dp"
            android:layout_height="wrap_content"
            android:text="333"
            android:id="@+id/duration"
            android:layout_marginTop="30dp"
            android:layout_marginLeft="-100dp"
            ></TextView>

    </LinearLayout>



</LinearLayout>

Fragment音樂界面整體效果布局


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".BlankFragment4">


    <ListView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/lv"
        android:layout_weight="8"
        ></ListView>

    <SeekBar
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/seekbar"
        ></SeekBar>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        >

        <ImageView
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:src="@drawable/shangyishou"
            android:id="@+id/shang"
            android:layout_marginLeft="80dp"
            ></ImageView>

       <ImageView
           android:layout_width="50dp"
           android:layout_height="50dp"
           android:src="@drawable/bofang2"
           android:id="@+id/bofang"
           ></ImageView>

        <ImageView
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:src="@drawable/bofang2"
           android:id="@+id/bofang1"
            ></ImageView>

        <ImageView
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:src="@drawable/xiayishou"
            android:id="@+id/next"
            ></ImageView>


        <ImageView
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:src="@drawable/moshi"
            android:id="@+id/model"
            ></ImageView>


    </LinearLayout>




</LinearLayout>

Fragment代碼

package com.example.day121lx;


import android.Manifest;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;

import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;

import android.os.IBinder;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.PopupWindow;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;


/**
 * A simple {@link Fragment} subclass.
 */
public class BlankFragment4 extends Fragment {
    private List<Music> list;
    private ListView lv;
    private ImageView shang;//上一首
    private ImageView next;//下一首
    private ImageView bofang;
    private SeekBar seekbar;
    private ImageView bofang1;
    private ImageView model;//模式
    private Timer timer;

    private   MyService.MyBinder myBinder;


    public BlankFragment4() {
        // Required empty public constructor
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        View inflate = inflater.inflate(R.layout.fragment_blank_fragment4, container, false);


        lv = (ListView)inflate. findViewById(R.id.lv);

        seekbar = (SeekBar)inflate. findViewById(R.id.seekbar);
        shang = (ImageView)inflate. findViewById(R.id.shang);
        next = (ImageView)inflate. findViewById(R.id.next);
        bofang1 = (ImageView)inflate. findViewById(R.id.bofang1);
        bofang = (ImageView) inflate.findViewById(R.id.bofang);


        model = (ImageView) inflate.findViewById(R.id.model);

        //初始化List
        list=new ArrayList<>();


        //模式點擊事件
        model.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                //使用popWindow彈窗實作
                final PopupWindow popupWindow = new PopupWindow();
                popupWindow.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);
                popupWindow.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);

                //單曲回圈

                View inflate1 = LayoutInflater.from(getActivity()).inflate(R.layout.pop_layout, null);
                final TextView danqu = inflate1.findViewById(R.id.pop_danqu);
                    danqu.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            myBinder.flish(MusicUtil.DANQU);
                            Toast.makeText(getActivity(), "單曲回圈", Toast.LENGTH_SHORT).show();
                            popupWindow.dismiss();
                        }
                    });
                //隨機播放
                TextView suiji  = inflate1.findViewById(R.id.pop_suiji);
                suiji.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        myBinder.flish(MusicUtil.SUIJI);
                        Toast.makeText(getActivity(), "隨機播放", Toast.LENGTH_SHORT).show();
                        popupWindow.dismiss();
                    }
                });

                TextView shunxu  = inflate1.findViewById(R.id.pop_shunxu);
                shunxu.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        myBinder.flish(MusicUtil.SHUNXU);
                        Toast.makeText(getActivity(), "順序播放", Toast.LENGTH_SHORT).show();
                        popupWindow.dismiss();
                    }
                });
                //內容
                popupWindow.setContentView(inflate1);
                //點擊對話框消失
                popupWindow.setOutsideTouchable(true);

                popupWindow.showAsDropDown(model,0,-350);
            }
        });



        //進度條
        seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {

                if (fromUser){
                    //后臺服務呼叫方法
                    myBinder.seekbar(progress);
                }

            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });


        //點擊暫停更換圖片
        bofang.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                myBinder.zt();
                bofang.setImageResource(R.drawable.bofang2);
                bofang1.setImageResource(R.drawable.bofang2);
            }
        });


        //點擊繼續圖片更換
        bofang1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                myBinder.jx();
                bofang1.setImageResource(R.drawable.bofang1);

            }
        });


        //上一首
        shang.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                myBinder.shang();
            }
        });

        //下一首
        next.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                myBinder.next();
            }
        });

        //啟動一個后臺服務
        Intent intent = new Intent(getActivity(),MyService.class);
        getActivity().startService(intent);


        //跟Service服務進行系結
        ServiceConnection serviceConnection=new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                 myBinder= (MyService.MyBinder) service;
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {

            }
        };
      getActivity().bindService(intent,serviceConnection,Context.BIND_ABOVE_CLIENT);

      //版本判斷
        if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){
            //讀取SD卡權限
            requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},100);
        }


        //ListView點擊事件
        lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                //呼叫服務方法
                myBinder.callplay(position);
                bofang.setImageResource(R.drawable.bofang1);
                myBinder.flish(position);
                if (timer==null){
                    timer = new Timer();
                    timer.schedule(new TimerTask() {
                        @Override
                        public void run() {
                            //設定進度條進度
                            seekbar.setMax(myBinder.getMax());
                            seekbar.setProgress(myBinder.getp());
                        }
                    },0,1000);
                }

            }
        });

        // Inflate the layout for this fragment
        return inflate;
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        //判斷是否同意讀取sd卡
        if (requestCode==100&&grantResults[0]==PackageManager.PERMISSION_GRANTED){

           list  = MusicUtil.getDate(getActivity());
            MyAdapter myAdapter = new MyAdapter(list,getActivity());
            lv.setAdapter(myAdapter);

        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
}

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/239542.html

標籤:其他

上一篇:Android WebView常見問題

下一篇:Android studio4.1下報錯Failed to open zip file. Gradle‘s dependency cache may be corrupt

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【從零開始擼一個App】Dagger2

    Dagger2是一個IOC框架,一般用于Android平臺,第一次接觸的朋友,一定會被搞得暈頭轉向。它延續了Java平臺Spring框架代碼碎片化,注解滿天飛的傳統。嘗試將各處代碼片段串聯起來,理清思緒,真不是件容易的事。更不用說還有各版本細微的差別。 與Spring不同的是,Spring是通過反射 ......

    uj5u.com 2020-09-10 06:57:59 more
  • Flutter Weekly Issue 66

    新聞 Flutter 季度調研結果分享 教程 Flutter+FaaS一體化任務編排的思考與設計 詳解Dart中如何通過注解生成代碼 GitHub 用對了嗎?Flutter 團隊分享如何管理大型開源專案 插件 flutter-bubble-tab-indicator A Flutter librar ......

    uj5u.com 2020-09-10 06:58:52 more
  • Proguard 常用規則

    介紹 Proguard 入口,如何查看輸出,如何使用 keep 設定入口以及使用實體,如何配置壓縮,混淆,校驗等規則。

    ......

    uj5u.com 2020-09-10 06:59:00 more
  • Android 開發技術周報 Issue#292

    新聞 Android即將獲得類AirDrop功能:可向附近設備快速分享檔案 谷歌為安卓檔案管理應用引入可安全隱藏資料的Safe Folder功能 Android TV新主界面將顯示電影、電視節目和應用推薦內容 泄露的Android檔案暗示了傳說中的谷歌Pixel 5a與折疊屏新機 谷歌發布Andro ......

    uj5u.com 2020-09-10 07:00:37 more
  • AutoFitTextureView Error inflating class

    報錯: Binary XML file line #0: Binary XML file line #0: Error inflating class xxx.AutoFitTextureView 解決: <com.example.testy2.AutoFitTextureView android: ......

    uj5u.com 2020-09-10 07:00:41 more
  • 根據Uri,Cursor沒有獲取到對應的屬性

    Android: 背景:呼叫攝像頭,拍攝視頻,指定保存的地址,但是回傳的Cursor檔案,只有名稱和大小的屬性,沒有其他諸如時長,連ID屬性都沒有 使用 cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATIO ......

    uj5u.com 2020-09-10 07:00:44 more
  • Android連載29-持久化技術

    一、持久化技術 我們平時所使用的APP產生的資料,在記憶體中都是瞬時的,會隨著斷電、關機等丟失資料,因此android系統采用了持久化技術,用于存盤這些“瞬時”資料 持久化技術包括:檔案存盤、SharedPreference存盤以及資料庫存盤,還有更復雜的SD卡記憶體儲。 二、檔案存盤 最基本存盤方式, ......

    uj5u.com 2020-09-10 07:00:47 more
  • Android Camera2Video整合到自己專案里

    背景: Android專案里呼叫攝像頭拍攝視頻,原本使用的 MediaStore.ACTION_VIDEO_CAPTURE, 后來因專案需要,改成了camera2 1.Camera2Video 官方demo有點問題,下載后,不能直接整合到專案 問題1.多次拍攝視頻崩潰 問題2.雙擊record按鈕, ......

    uj5u.com 2020-09-10 07:00:50 more
  • Android 開發技術周報 Issue#293

    新聞 谷歌為Android TV開發者提供多種新功能 Android 11將自動填表功能整合到鍵盤輸入建議中 谷歌宣布Android Auto即將支持更多的導航和數字停車應用 谷歌Pixel 5只有XL版本 搭載驍龍765G且將比Pixel 4更便宜 [圖]Wear OS將迎來重磅更新:應用啟動時間 ......

    uj5u.com 2020-09-10 07:01:38 more
  • 海豚星空掃碼投屏 Android 接收端 SDK 集成 六步驟

    掃碼投屏,開放網路,獨占設備,不需要額外下載軟體,微信掃碼,發現設備。支持標準DLNA協議,支持倍速播放。視頻,音頻,圖片投屏。好點意思。還支持自定義基于 DLNA 擴展的操作動作。好像要收費,沒體驗。 這里簡單記錄一下集成程序。 一 跟目錄的build.gradle添加私有mevan倉庫 mave ......

    uj5u.com 2020-09-10 07:01:43 more
最新发布
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:40:31 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:40:11 more
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:39:36 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:39:13 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:16:23 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:16:15 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:15:46 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:14:53 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:14:08 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:08:34 more