• Android学习 问题与答案


      学习 Android 的过程中,碰到很多问题,从问题中也学到了很多。

     

    单位
    写一个视频播放器的时候,时间尺度的把握让我想了一段时间,进度条的刷新,字幕的刷新都要注意些。

    MediaPlayer.getduration()  return int/millisecond
    SeekBar.getProgress()       return int/scecond

     

    static import
    javadoc 的 static import 文档在这里
    为了获取静态成员,必须以所在类修饰引它,例如: double r = Math.cos(Math.PI * theta);
    为了避开这个问题,把静态成员写入接口并继承它会是一个坏主意,这个主义的名字叫 Constant Interface Antipattern,问题是一个类使用另外一个类的静态成员只不过是执行上的细节,当一个类实现了一个接口,那么它成了这个类的 public API,而执行细节不应该向 public API 泄漏的。static import 可以免去这一麻烦,只要

    import static java.lang.Math.PI; // import static CLASS_NAME.MEMBER_NAME;
    或者 // Alternatively
    import static java.lang.Math.*; // import static CLASS_NAME.*;

    一旦导入了静态成员,就可以不加修饰地引用了。   double r = cos(PI * theta);
    最后,你必须谨慎使用 static import ,very sparingly 。 当需要频繁引用时,可以使用该特性;滥用会导致你的程序变得不可读不好维护,污染命名空间,

     
     

    java断言
    如何开启 java 断言,问题英文答案在这里,中文的在下面。
    导入 JUnit Assert 类,注意不要导入 Junit4 framework,那个是 org.junit 包,在 Android 设备或模拟器上你必须使用 junit.framework 包
    import static junit.framework.Assert.*;
    然后尽情使用 assertTrue, assertEquals, assertNull 吧!
    开启断言有两种方法:
    1. 通过 adb shell setprop debug.assert 1 来设置系统属性 debug.assert
    2. 给 Dalvik 虚拟机添加命令行参数 --enable-assert 或简写 -ea

    指定的APK打开
    如果是自己写的播放器,当然知道名字,直接 startActivity(new Intent(HereActivity.this, ThereActivity.class)); 就行了。如果是用其他人写的 apk,就不清楚名字了,怎么办呢?
    如果装了多个应用程序,如播放器 RockPlayer, VPlayer 等等, 但是就是想用 RockPlayer 打开。

    Intent intent = new Intent();
    intent.setComponent(new ComponentName("com.redirectin.rockplayer.android.unified", "com.redirectin.rockplayer.android.OpenRockPlayerActivity"));
    // 包名 类名,解压 apk 文件,利用网上流传的 AXMLPrinter.jar 东西 java -jar AXMLPrinter AndroidManifest.xml,
    // 查 AndroidManifest.xml 文件内容,当然这样有点小题大做了。
    // APK 和 JAR 文件都是以 ZIP 格式压缩的,AXMLPrinter.jar 的下载在这里,下载后去掉扩展名 .zip 就可以用了。
    // 简单一点,可以播放视频,选择 RockPlayer 打开,查看 logcat 信息,然后提取里面字符串,cmp 是 ComponentName。

    Uri name = Uri.parse("http://192.168.1.122/video.flv");
    intent.setData(name);
    startActivity(intent);

    I/ActivityManager( 1079): Starting activity: Intent { act=android.intent.action.VIEW dat=file:///mnt/sdcard/video/Crysis2DirectX11UltraUpgradeTrailer_H.264%20AVC_1280x720.flv typ=video/* cmp=android/com.android.internal.app.ResolverActivity }
    I/ActivityManager( 1079): Displayed activity android/com.android.internal.app.ResolverActivity: 414 ms (total 414 ms)
    I/ActivityManager( 1079): Starting activity: Intent { act=android.intent.action.VIEW dat=file:///mnt/sdcard/video/Crysis2DirectX11UltraUpgradeTrailer_H.264%20AVC_1280x720.flv typ=video/* flg=0x3800000 cmp=com.redirectin.rockplayer.android.unified/com.redirectin.rockplayer.android.OpenRockPlayerActivity }
    I/ActivityManager( 1079): Starting activity: Intent { cmp=com.redirectin.rockplayer.android.unified/com.redirectin.rockplayer.android.RockPlayer (has extras) }
    D/dalvikvm(10505): Trying to load lib /data/data/com.redirectin.rockplayer.android.unified/lib/librockplayer_8.so 0x4a3cbe90
    D/dalvikvm(10505): Shared lib '/data/data/com.redirectin.rockplayer.android.unified/lib/librockplayer_8.so' already loaded in same CL 0x4a3cbe90
    W/drawable(10505): Bad element under <shape>: background
    D/NativeLibName(10505): plugin .so path /data/data/com.redirectin.rockplayer.android.unified/lib/libffmpeg
    D/NativeLibName(10505): ARMv7, idx=8 vfpv3d32=false
    D/NativeLibName(10505): degressionLevel=0, path is /data/data/com.redirectin.rockplayer.android.unified/lib/libffmpeg_7n.so
    D/RockPlayer(10505): open optimized ffmpeg lib: /data/data/com.redirectin.rockplayer.android.unified/lib/libffmpeg_7n.so
    D/RockPlayer(10505): open video height = 720,width=1280
    D/RockPlayer(10505): Surface hasn't been initialized! NativeSurfaceView.setSurfaceChanged never got called?
    D/RockPlayer(10505): NativeSurfaceView.getVideoHeight: 720
    D/RockPlayer(10505): NativeSurfaceView.getVideoWidth: 1280

    image/*的处理

    Intent intent = new Intent();
    Uri uri = Uri.parse("http://www.xxx.com/image/20111126/beautiful.jpg");
    intent.setDataAndType(uri, "image/*"); // video/* 或者 audio/* 两种试过可以的。
    intent.setAction(android.content.Intent.ACTION_GET_CONTENT);
    startActivity(intent);

    运行的话会抛出异常,logcat 信息:
    ERROR/AndroidRuntime(232): android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.GET_CONTENT dat=http://www.xxx.com/image/20111126/beautiful.jpg typ=image/* }

    intent.setDataAndType(uri, "image/*");将其改成intent.setData(uri); 会启动浏览器打开图片。

    final 关键字

    public boolean onItemLongClick(AdapterView<?> parent, View view,int position,long id)
    {
    // final int pos=position;
    @Override
    public void onClick(DialogInterface dialog, int which)
    {
    // do something here..
    // st_color.remove(pos);
    }
    }

    内部匿名类访问外部类变量需要添加 final 属性。
    参数添加 final 属性不算函数重载,试着将上面的参数修改了成 final int postion,final long id
    发现,运行的结果与预期不一致,表现在 lst_color.remove(position); 删除不掉数据
    其中,lst_color 为 ArrayList<String> 型数据。
    然后关掉注释,即添加 final int pos = position; lst_color.remove(pos); 成功删除。

    ArrayList<T>与T[]

    ArrayList<T> 与 T[] 之间的转换,用 get() 方法获取然后对数组赋值显得冗余。

    ArrayList<T> lst_color;
    T[] color = (T[])lst_color.toArray(new String[lst_color.length());
    lst_color = Arrays.asList(color);

      查阅 javadoc,ArrayLis t提供 public <T> T[] toArray(T[] a) 方法返回一个按照正确的顺序包含此列表中所有元素的数组;返回数组的运行时类型就是指定数组的运行时类型。如果列表能放入指定的数组,则返回放入此列表元素的数组。否则,将根据指定数组的运行时类型和此列表的大小分配一个新的数组。
      如果指定的数组能容纳列表并有剩余空间(即数组的元素比列表的多),那么会将数组中紧跟在集合末尾的元素设置为 null。这对确定列表的长度很有用,但只在调用方知道列表中不包含任何 null 元素时才有用。
      asList方法返回一个受指定数组支持的固定大小的列表,此方法同 Collection.toArray 一起,充当了基于数组的 API 与基于 collection 的 API 之间的桥梁。返回的列表是可序列化的,并且实现了 RandomAccess。

    Activity 与 Service 数据交互

    通过 Intent 来传递数据

    Activity 使用 intent.putExtras(KEY,value);
    Service 使用 public void onStartCommand(Intent data, int startId, int flags),
    public void onStart (Intent intent, int startId) This method is deprecated.

    APK 的安装与卸载

    // 安装程序的 apk 文件路径

    String fileName = Environment.getExternalStorageDirectory() + apkName; 
    Uri uri = Uri.fromFile(new File(fileName));
    Intent intent = new Intent(Intent.ACTION_VIEW);
    intent.setDataAndType(Uri, application/vnd.android.package-archive");
    startActivity(intent);

    // 卸载 apk,通过程序的包名创建 URI

    Uri packageURI = Uri.parse("package: poet.android.app.id"); 
    Intent intent = new Intent(Intent.ACTION_DELETE);
    startActivity(intent);

    获取屏幕的分辨率

    DisplayMetrics dm = new DisplayMetrics();
    this.getWindowManager().getDefaultDisplay().getMetrics(dm);
    int width = dm.widthPixels;
    int height = dm.heightPixels;

    不过在  Ice Cream Sandwich,也就是有 Combined bar(开发者请区分 Status/Navigation/Combined Bar)的时候,获取的值是不包括 Combined bar 的高度的。我这里,1280x720 的值会返回 1280x672,即使用下面一行代码设置隐藏属性也不行。 
    getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
    解决方法是利用了 Java 的反射机制调用方法 getRawHeight(), getRawWidth()

    Method mGetRawWidth = Display.class.getMethod("getRawWidth");
    Method mGetRawHeight = Display.class.getMethod("getRawHeight");
    int width = (Integer) mGetRawWidth.invoke(display);
    int height = (Integer) mGetRawHeight.invoke(display);
    

    不过在 Android 4.2 也就是 API Level>=17(Build.VERSION_CODES.JELLY_BEAN_MR1) 后有原生的方法 Display.getRealMetrics 供调用,返回正确的结果。

    修改控件的尺寸大小

    这里在代码中动态修改,而不是 XML 文件中修改。

    // 这里使用LayoutInflater。
    // LayoutInflater inflater= (LayoutInflater)this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    // 下面一行与上一行一个效果
    // LayoutInflater inflater=this.getLayoutInflater();
    View view_background = this.getLayoutInflater().inflate(R.layout.background,null);
    LinearLayout.LayoutParams lp_param = (LinearLayout.LayoutParams)view_background.getLayoutParams();
    lp_param.height = (int)(dm.heightPixels*0.618); // 仅修改个别参数,这里修改高度
    ll_background.setLayoutParams(lp_param);

    // 假如layout/background.xml里面有一个TextView的id是id_result.
    // 要去当前的view里面查找获取,这里是view_background
    TextView tv_result = (TextView)view_background.findViewById(R.id.id_result);
    tv_result.setText(R.string.result);

    未完待续。。。

  • 相关阅读:
    凯撒密文的破解编程实现
    微软ping命令的源代码
    从编程到入侵
    永远的后门
    永远的后门
    奇妙的Base64编码
    用端口截听实现隐藏嗅探与攻击(二)
    奇妙的Base64编码
    Liferea 1.1.2
    Equinox Desktop Environment 1.1
  • 原文地址:https://www.cnblogs.com/Martinium/p/android_learning.html
Copyright © 2020-2023  润新知