Android SDK国内镜像

安装过Android Studio的人估计都体验过下载超慢的问题,有时候直接就不能下载,这里记录一下国内的两个镜像,稍微设置一下就可以解决速度慢的问题。

1.腾讯提供的镜像:

http://android-mirror.bugly.qq.com:8080/include/usage.html

2.东软提供的镜像:

http://mirrors.neusoft.edu.cn/more.we#android

安装的时候还是建议到官方下载一个最新版本的Android Studio,然后选择上面的一个国内镜像,按照配置说明把更新地址配置后,使用起来还是很顺畅的。

Android Activity的生命周期

activity类处于android.app包中,继承体系如下:

1.java.lang.Object

2.android.content.Context

3.android.app.ApplicationContext

4.android.app.Activity

activity是单独的,用于处理用户操作。几乎所有的activity都要和用户打交道,所以activity类创建了一个窗口,开发人员可以通过setContentView(View)接口把UI放到activity创建的窗口上,当 activity指向全屏窗口时,也可以用其他方式实现:作为漂浮窗口(通过windowIsFloating的主题集合),或者嵌入到其他的 activity(使用ActivityGroup)。大部分的Activity子类都需要实现以下两个接口:

  • onCreate(Bundle)接口是初始化activity的地方. 在这儿通常可以调用setContentView(int)设置在资源文件中定义的UI, 使用findViewById(int) 可以获得UI中定义的窗口.
  • onPause()接口是使用者准备离开activity的地方,在这儿,任何的修改都应该被提交(通常用于ContentProvider保存数据).

为了能够使用Context.startActivity(),所有的activity类都必须在AndroidManifest.xml文件中定义有相关的“activity”项。

activity类是Android 应用生命周期的重要部分。

Activity生命周期

在系统中的Activity被一个Activity栈所管理。当一个新的Activity启动时,将被放置到栈顶,成为运行中的Activity,前一个Activity保留在栈中,不再放到前台,直到新的Activity退出为止。

Activity有四种本质区别的状态:

  1. 在屏幕的前台(Activity栈顶),叫做活动状态或者运行状态(active or running)
  2. 如果一个Activity失去焦点,但是依然可见(一个新的非全屏的Activity 或者一个透明的Activity 被放置在栈顶),叫做暂停状态(Paused)。一个暂停状态的Activity依然保持活力(保持所有的状态,成员信息,和窗口管理器保持连接),但是在系统内存极端低下的时候将被杀掉。
  3. 如果一个Activity被另外的Activity完全覆盖掉,叫做停止状态(Stopped)。它依然保持所有状态和成员信息,但是它不再可见,所以它的窗口被隐藏,当系统内存需要被用在其他地方的时候,Stopped的Activity将被杀掉。
  4. 如果一个Activity是Paused或者Stopped状态,系统可以将该Activity从内存中删除,Android系统采用两种方式进行删除,要么要求该Activity结束,要么直接杀掉它的进程。当该Activity再次显示给用户时,它必须重新开始和重置前面的状态。

下面的图显示了Activity的重要状态转换,矩形框表明Activity在状态转换之间的回调接口,开发人员可以重载实现以便执行相关代码,带有颜色的椭圆形表明Activity所处的状态。

activity

在上图中,Activity有三个关键的循环:

  1. 整个的生命周期,从onCreate(Bundle)开始到onDestroy()结束。Activity在onCreate()设置所有的“全局”状态,在onDestory()释放所有的资源。例如:某个Activity有一个在后台运行的线程,用于从网络下载数据,则该Activity可以在onCreate()中创建线程,在onDestory()中停止线程。
  2. 可见的生命周期,从onStart()开始到onStop()结束。在这段时间,可以看到Activity在屏幕上,尽管有可能不在前台,不能和用户交互。在这两个接口之间,需要保持显示给用户的UI数据和资源等,例如:可以在onStart中注册一个IntentReceiver来监听数据变化导致UI的变动,当不再需要显示时候,可以在onStop()中注销它。onStart(),onStop()都可以被多次调用,因为Activity随时可以在可见和隐藏之间转换。
  3. 前台的生命周期,从onResume()开始到onPause()结束。在这段时间里,该Activity处于所有 Activity的最前面,和用户进行交互。Activity可以经常性地在resumed和paused状态之间切换,例如:当设备准备休眠时,当一个 Activity处理结果被分发时,当一个新的Intent被分发时。所以在这些接口方法中的代码应该属于非常轻量级的。

Activity的整个生命周期都定义在下面的接口方法中,所有方法都可以被重载。所有的Activity都需要实现 onCreate(Bundle)去初始化设置,大部分Activity需要实现onPause()去提交更改过的数据,当前大部分的Activity也需要实现onFreeze()接口,以便恢复在onCreate(Bundle)里面设置的状态。

public class Activity extends ApplicationContext {
	protected void onCreate(Bundle icicle);
	protected void onStart();
	protected void onRestart();
	protected void onResume();
	protected void onFreeze(Bundle outIcicle);
	protected void onPause();
	protected void onStop();
	protected void onDestroy();

}

android中播放视频的几种方法

播放视频的方法有很多种,使用andorid自带的也可以播放大部分的视频,有些格式的视频需要专门的解码才能播放,大部分的视频网站都有自己的视频格式,同时自己提供播放软件,这就是最简单的防止盗版,同时也是根据需要压缩自己的视频文件可以减少存储空间,当然最重要的还是节省带宽;

在Android中,我们有三种方式来实现视频的播放:
1、使用其自带的播放器。指定Action为ACTION_VIEW,Data为Uri,Type为其MIME类型。
2、使用VideoView来播放。在布局文件中使用VideoView结合MediaController来实现对其控制。
3、使用MediaPlayer类和SurfaceView来实现,这种方式很灵活。

1.调用其自带的播放器:

Uri uri = Uri.parse(Environment.getExternalStorageDirectory().getPath()+"/Test_Movie.m4v");     
//调用系统自带的播放器    
Intent intent = new Intent(Intent.ACTION_VIEW);    
Log.v("URI:::::::::", uri.toString());    
intent.setDataAndType(uri, "video/mp4");    
startActivity(intent);

2.使用VideoView来实现:

Uri uri = Uri.parse(Environment.getExternalStorageDirectory().getPath()+"/Test_Movie.m4v");    
VideoView videoView = (VideoView)this.findViewById(R.id.video_view);    
videoView.setMediaController(new MediaController(this));    
videoView.setVideoURI(uri);    
videoView.start();    
videoView.requestFocus();

3.使用MediaPlayer:

布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent"
    android:layout_height="fill_parent" android:weightSum="1">
    <SurfaceView android:layout_height="220dip" android:layout_gravity="center" android:id="@+id/surface" android:layout_weight="0.25" android:layout_width="320dip"></SurfaceView>
    <LinearLayout android:id="@+id/linearLayout1" android:layout_height="wrap_content" android:layout_width="fill_parent">
        <Button android:text="播放" android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
        <Button android:text="暂停" android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
        <Button android:text="停止" android:id="@+id/button3" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
    </LinearLayout>
</LinearLayout>

主程序:

public class SurfaceActivity extends Activity implements SurfaceHolder.Callback {
    /** Called when the activity is first created. */
    MediaPlayer player;
    SurfaceView surface;
    SurfaceHolder surfaceHolder;
    Button play,pause,stop;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        play=(Button)findViewById(R.id.button1);
        pause=(Button)findViewById(R.id.button2);
        stop=(Button)findViewById(R.id.button3);
        surface=(SurfaceView)findViewById(R.id.surface);
 
        surfaceHolder=surface.getHolder();  //SurfaceHolder是SurfaceView的控制接口
        surfaceHolder.addCallback(this);   //因为这个类实现了SurfaceHolder.Callback接口,所以回调参数直接this
        surfaceHolder.setFixedSize(320, 220);  //显示的分辨率,不设置为视频默认
        surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);  //Surface类型
 
        play.setOnClickListener(new OnClickListener(){
             @Override
            public void onClick(View v) {
                player.start();
            }});
        pause.setOnClickListener(new OnClickListener(){
            @Override
            public void onClick(View v) {
                player.pause();
            }});
        stop.setOnClickListener(new OnClickListener(){
             @Override
            public void onClick(View v) {
                player.stop();
            }});
    }
 
    @Override
    public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
    }
 
    @Override
    public void surfaceCreated(SurfaceHolder arg0) {
//必须在surface创建后才能初始化MediaPlayer,否则不会显示图像
        player=new MediaPlayer();
        player.setAudioStreamType(AudioManager.STREAM_MUSIC);
        player.setDisplay(surfaceHolder);
        //设置显示视频显示在SurfaceView上
            try {
                player.setDataSource("/sdcard/3.mp4");
                player.prepare();
            } catch (Exception e) {
                e.printStackTrace();
            }
    }
 
    @Override
    public void surfaceDestroyed(SurfaceHolder arg0) {
        // TODO Auto-generated method stub
 
    }
 
    @Override
    protected void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
        if(player.isPlaying()){
        player.stop();
        }
        player.release();
        //Activity销毁时停止播放,释放资源。不做这个操作,即使退出还是能听到视频播放的声音
    }
}

总结

第三种算是比较常用的播放方式,比较灵活可以对视频进行控制,当然这毕竟是自带的播放器,支持视频格式根据系统安装的情况而定,那么可以使用一些第三方播放器来实现,比如说vlc开源播放器http://www.videolan.org/,或者其他的开源播放器都可以做的很好。

android使用ACTION_SEND分享内容

几乎是所有的app现在都有分享的功能,分享一些文本,链接和图片之类的到各大社交平台,那么这么一个简单的功能是如何实现的能,android里面有一个默认的接口,我们来看看怎么使用。

android默认的intent ACTION_SEND可以实现这个分享的功能,看看下面的示例

Intent sharingIntent = new Intent(Intent.ACTION_SEND);
sharingIntent.setType("text/html");
sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, Html.fromHtml("<p>This is the text that will be shared.</p>"));
startActivity(Intent.createChooser(sharingIntent,"Share using"));

以上是分享一段html,也是最常用的分享方式,也可以分享一些图片如下

Intent sharingIntent = new Intent(Intent.ACTION_SEND);
Uri screenshotUri = Uri.parse(path);

sharingIntent.setType("image/png");
sharingIntent.putExtra(Intent.EXTRA_STREAM, screenshotUri);
startActivity(Intent.createChooser(sharingIntent, "Share image using"));

分享多个图片

ArrayList<Uri> imageUris = new ArrayList<Uri>();
imageUris.add(imageUri1); // Add your image URIs here
imageUris.add(imageUri2);

Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND_MULTIPLE);
shareIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, imageUris);
shareIntent.setType("image/*");
startActivity(Intent.createChooser(shareIntent, "Share images to.."));

上面的分享当然是在手机上有可以分享的软件才能接受到分享的内容,以上的分享事件都会打开一个选择分享软件的列表,比如微信或者微博之类的,用户选择一个之后发送分享内容,那么下面这段xml可以让你的app可以出现在分享列表中,以实现分享的效果:

<activity android:name=".ui.MyActivity" >
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="image/*" />
    </intent-filter>
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="text/plain" />
    </intent-filter>
    <intent-filter>
        <action android:name="android.intent.action.SEND_MULTIPLE" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="image/*" />
    </intent-filter>
</activity>

下面这段代码是处理接收到消息之后的基本过程

void onCreate (Bundle savedInstanceState) {
    ...
    // Get intent, action and MIME type
    Intent intent = getIntent();
    String action = intent.getAction();
    String type = intent.getType();

    if (Intent.ACTION_SEND.equals(action) && type != null) {
        if ("text/plain".equals(type)) {
            handleSendText(intent); // Handle text being sent
        } else if (type.startsWith("image/")) {
            handleSendImage(intent); // Handle single image being sent
        }
    } else if (Intent.ACTION_SEND_MULTIPLE.equals(action) && type != null) {
        if (type.startsWith("image/")) {
            handleSendMultipleImages(intent); // Handle multiple images being sent
        }
    } else {
        // Handle other intents, such as being started from the home screen
    }
    ...
}

void handleSendText(Intent intent) {
    String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
    if (sharedText != null) {
        // Update UI to reflect text being shared
    }
}

void handleSendImage(Intent intent) {
    Uri imageUri = (Uri) intent.getParcelableExtra(Intent.EXTRA_STREAM);
    if (imageUri != null) {
        // Update UI to reflect image being shared
    }
}

void handleSendMultipleImages(Intent intent) {
    ArrayList<Uri> imageUris = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
    if (imageUris != null) {
        // Update UI to reflect multiple images being shared
    }
}

总结

android自带的分享只是列出接收分享内容的app列表,由用户选择启动对应的app进行分享,当系统中没有安装目标app的时候是没办法分享的,那么对一般的应用来说这就已经足够了,系统自带的功能一般都是比较基本的东西,另一个办法是使用第三方分享sdk可以实现更加复杂的分享功能。

ANDROID WebView简单使用

现在的很多应用都使用了原生与网页相结合的模式,同时网页也可以通过javascript借助webview与原生部分进行交互,这种模式在现有的很多应用里面都可以体验到,比如微信之流的这样可以大大减少APP的体量又能快速更新内容而不需要让最终用户跟新APP。

我们来做一个简单的全屏幕的Webview,activity_webview.xml如下

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

    <WebView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/webView"
        android:layout_margin="0dp"
        android:padding="0dp"
        android:layout_centerInParent="true"
        />


</RelativeLayout>

这里需要实现一个WebViewClient,可以监听到页面加载的事件

public class MyWebViewClient extends WebViewClient {

    private Context context;

    public MyWebViewClient(Context cxt){
        this.context = cxt;
    }

    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        view.loadUrl(url);
        return true;
    }
    @Override
    public void onPageStarted(WebView view, String url, Bitmap favicon) {
        super.onPageStarted(view, url, favicon);
        //开始进度条
    }

    @Override
    public void onPageFinished(WebView view, String url)
    {
        super.onPageFinished(view,url);
        //结束进度条
    }


}

这里就看这是三个方法,其他的可以根据需要去重载,shouldOverrideUrlLoading 这个方法默认情况下页面上有连接的时候他是不会自动打开链接指向的页面的,重写他然后加载url,这样页面上的链接就又笑了,onPageStarted ,onPageFinished 这两个方法可以控制页面上的进度条,提示用户页面正在加载。

在Activity里面加载页面

@SuppressLint("SetJavaScriptEnabled")
public class WebViewActivity  extends AppCompatActivity {


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_webview);


        String url = "http://www.fullstacks.cn");

        webView = (WebView)this.findViewById(R.id.webView);
        //webView.clearCache(false);

        webView.setWebViewClient(new MyWebViewClient(this));

        webView.getSettings().setLoadsImagesAutomatically(true);//自动加载图片
        webView.getSettings().setJavaScriptEnabled(true);//允许使用javascript
        webView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
        webView.getSettings().setDefaultTextEncodingName("utf-8");
        webView.addJavascriptInterface(this, "WebViewJavascriptBridge");//添加javascript与原生交互的接口


        webView.loadUrl(url);
    }
    /**
     * 关闭当前页面
     * @param args 返回参数
     */
    @JavascriptInterface
    public void close(String args){
        this.finish();
    }
}

与javascript的交互接口可以独立实现,这里就直接在activity上实现了,类名上需要加个注解@SuppressLint(“SetJavaScriptEnabled”)  , 方法上加上注解@JavascriptInterface 表示javascritp可以访问到该方法了。

那么到这里App里面的代码就大功告成了,运行起来之后就可以看到打开的网页了

页面上调用Webview里面注册的接口webView.addJavascriptInterface(this, “WebViewJavascriptBridge”);

根据注册的这个名字WebViewJavascriptBridge ,可以在加载的页面上访问到如window.WebViewJavascriptBridge ,直接可以在上面调用注解@JavascriptInterface暴露出来的方法window.WebViewJavascriptBridge(“args…”) ,但是有时候注册的过程可能比较慢,页面出来这个接口还没注册完毕所以需要判断一下如下这个方法

function connectWebViewJavascriptBridge(callback) {
	if (window.WebViewJavascriptBridge) {
		callback(WebViewJavascriptBridge);
	} else {
		document.addEventListener('WebViewJavascriptBridgeReady', function() {
			callback(WebViewJavascriptBridge);
		}, false)
	}
}

function closeWebView(){
	connectWebViewJavascriptBridge(function(bridge){
		bridge.close();
	});
}

connectWebViewJavascriptBridge这样我们可以传入一个回调方法进去,当获取到接口的时候就调用这个回调方法,然后再执行需要的代码,这就就不会出现空指针的错误了,后面的方法closeWebView就是简单的调用了关闭webview的接口。

在html上一个按钮上加上事件就可以了

<button onclick="closeWebView()">关闭</button>

总结

通过javascript与webview的通讯,页面就可以辅以更多的能力,比如说打开一个文档,传入url让app下载然后打开,也可以进行分享,调用分享接口,使用支付功能等等。